When attempting to load a module that is not in the module cache,

return the module itself (in the module map) rather than returning the
umbrella header used to build the module. While doing this, make sure
that we're inferring modules for frameworks to build that module.

llvm-svn: 145310
This commit is contained in:
Douglas Gregor 2011-11-28 23:16:06 +00:00
parent 67f5d88869
commit ca295457e5
3 changed files with 41 additions and 64 deletions

View File

@ -350,19 +350,17 @@ public:
/// \brief Search in the module cache path for a module with the given
/// name.
///
/// \param Module The module that was found with the given name, which
/// describes the module and how to build it.
///
/// \param If non-NULL, will be set to the module file name we expected to
/// find (regardless of whether it was actually found or not).
///
/// \param UmbrellaHeader If non-NULL, and no module was found in the module
/// cache, this routine will search in the framework paths to determine
/// whether a module can be built from an umbrella header. If so, the pointee
/// will be set to the path of the umbrella header.
///
/// \returns A file describing the named module, if available, or NULL to
/// indicate that the module could not be found.
/// \returns A file describing the named module, if already available in the
/// cases, or NULL to indicate that the module could not be found.
const FileEntry *lookupModule(StringRef ModuleName,
std::string *ModuleFileName = 0,
std::string *UmbrellaHeader = 0);
ModuleMap::Module *&Module,
std::string *ModuleFileName = 0);
void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }

View File

@ -1045,15 +1045,14 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
// Search for a module with the given name.
std::string UmbrellaHeader;
ModuleMap::Module *Module = 0;
std::string ModuleFileName;
const FileEntry *ModuleFile
= PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(),
&ModuleFileName,
&UmbrellaHeader);
= PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(), Module,
&ModuleFileName);
bool BuildingModule = false;
if (!ModuleFile && !UmbrellaHeader.empty()) {
if (!ModuleFile && Module && Module->UmbrellaHeader) {
// We didn't find the module, but there is an umbrella header that
// can be used to create the module file. Create a separate compilation
// module to do so.
@ -1080,8 +1079,9 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build)
<< ModuleName.getName();
BuildingModule = true;
compileModule(*this, ModuleName.getName(), ModuleFileName, UmbrellaHeader);
ModuleFile = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName());
compileModule(*this, ModuleName.getName(), ModuleFileName,
Module->UmbrellaHeader->getName());
ModuleFile = FileMgr->getFile(ModuleFileName);
}
if (!ModuleFile) {

View File

@ -102,8 +102,10 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
}
const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName,
std::string *ModuleFileName,
std::string *UmbrellaHeader) {
ModuleMap::Module *&Module,
std::string *ModuleFileName) {
Module = 0;
// If we don't have a module cache path, we can't do anything.
if (ModuleCachePath.empty()) {
if (ModuleFileName)
@ -117,23 +119,28 @@ const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName,
if (ModuleFileName)
*ModuleFileName = FileName.str();
if (const FileEntry *ModuleFile
= getFileMgr().getFile(FileName, /*OpenFile=*/false,
/*CacheFailure=*/false))
return ModuleFile;
// We didn't find the module. If we're not supposed to look for an
// umbrella header, this is the end of the road.
if (!UmbrellaHeader)
return 0;
// Look in the module map to determine if there is a module by this name.
ModuleMap::Module *Module = ModMap.findModule(ModuleName);
Module = ModMap.findModule(ModuleName);
if (!Module) {
// Look through the various header search paths to load any avaiable module
// maps, searching for a module map that describes this module.
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
// Skip non-normal include paths
if (SearchDirs[Idx].isFramework()) {
// Search for or infer a module map for a framework.
llvm::SmallString<128> FrameworkDirName;
FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
if (const DirectoryEntry *FrameworkDir
= FileMgr.getDirectory(FrameworkDirName)) {
Module = getFrameworkModule(ModuleName, FrameworkDir);
if (Module)
break;
}
}
// FIXME: Figure out how header maps and module maps will work together.
// Only deal with normal search directories.
if (!SearchDirs[Idx].isNormalDir())
continue;
@ -160,39 +167,11 @@ const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName,
}
}
// If we have a module with an umbrella header
// FIXME: Even if it doesn't have an umbrella header, we should be able to
// handle the module. However, the caller isn't ready for that yet.
if (Module && Module->UmbrellaHeader) {
*UmbrellaHeader = Module->UmbrellaHeader->getName();
return 0;
}
// Look in each of the framework directories for an umbrella header with
// the same name as the module.
llvm::SmallString<128> UmbrellaHeaderName;
UmbrellaHeaderName = ModuleName;
UmbrellaHeaderName += '/';
UmbrellaHeaderName += ModuleName;
UmbrellaHeaderName += ".h";
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
// Skip non-framework include paths
if (!SearchDirs[Idx].isFramework())
continue;
// Look for the umbrella header in this directory.
if (const FileEntry *HeaderFile
= SearchDirs[Idx].LookupFile(UmbrellaHeaderName, *this, 0, 0,
StringRef(), 0)) {
*UmbrellaHeader = HeaderFile->getName();
return 0;
}
}
// We did not find an umbrella header. Clear out the UmbrellaHeader pointee
// so our caller knows that we failed.
UmbrellaHeader->clear();
return 0;
// Look for the module file in the module cache.
// FIXME: If we didn't find a description of the module itself, should we
// even try to find the module in the cache?
return getFileMgr().getFile(FileName, /*OpenFile=*/false,
/*CacheFailure=*/false);
}
//===----------------------------------------------------------------------===//