diff options
Diffstat (limited to 'clang/lib/Lex/HeaderSearch.cpp')
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 154 |
1 files changed, 91 insertions, 63 deletions
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 46d4d41b9af..cb76923f2d6 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -165,8 +165,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); // Search for a module map file in this directory. - if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem) - == LMM_NewlyLoaded) { + if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, + /*IsFramework*/false) == LMM_NewlyLoaded) { // We just loaded a module map file; check whether the module is // available now. Module = ModMap.findModule(ModuleName); @@ -179,7 +179,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { SmallString<128> NestedModuleMapDirName; NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); llvm::sys::path::append(NestedModuleMapDirName, ModuleName); - if (loadModuleMapFile(NestedModuleMapDirName, IsSystem) == LMM_NewlyLoaded){ + if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, + /*IsFramework*/false) == LMM_NewlyLoaded){ // If we just loaded a module map file, look for the module again. Module = ModMap.findModule(ModuleName); if (Module) @@ -1097,8 +1098,8 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, if (!Dir) return false; - // Try to load the "module.map" file in this directory. - switch (loadModuleMapFile(Dir, IsSystem)) { + // Try to load the module map file in this directory. + switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/false)) { case LMM_NewlyLoaded: case LMM_AlreadyLoaded: // Success. All of the directories we stepped through inherit this module @@ -1132,36 +1133,84 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const { return ModMap.findModuleForHeader(File); } +static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath, + const DirectoryEntry *Directory, + FileManager &FileMgr) { + StringRef Filename = llvm::sys::path::filename(ModuleMapPath); + SmallString<128> PrivateFilename(Directory->getName()); + if (Filename == "module.map") + llvm::sys::path::append(PrivateFilename, "module_private.map"); + else if (Filename == "module.modulemap") + llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); + else + return nullptr; + return FileMgr.getFile(PrivateFilename); +} + bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { + switch (loadModuleMapFileImpl(File, IsSystem)) { + case LMM_AlreadyLoaded: + case LMM_NewlyLoaded: + return false; + case LMM_NoDirectory: + case LMM_InvalidModuleMap: + return true; + } +} + +HeaderSearch::LoadModuleMapResult +HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) { + assert(File && "expected FileEntry"); + const DirectoryEntry *Dir = File->getDir(); - - llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir - = DirectoryHasModuleMap.find(Dir); + auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) - return !KnownDir->second; - - bool Result = ModMap.parseModuleMapFile(File, IsSystem); - if (!Result && llvm::sys::path::filename(File->getName()) == "module.map") { - // If the file we loaded was a module.map, look for the corresponding - // module_private.map. - SmallString<128> PrivateFilename(Dir->getName()); - llvm::sys::path::append(PrivateFilename, "module_private.map"); - if (const FileEntry *PrivateFile = FileMgr.getFile(PrivateFilename)) - Result = ModMap.parseModuleMapFile(PrivateFile, IsSystem); + return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; + + if (ModMap.parseModuleMapFile(File, IsSystem)) { + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; } - - DirectoryHasModuleMap[Dir] = !Result; - return Result; + + // Try to load a corresponding private module map. + if (const FileEntry *PMMFile = + getPrivateModuleMap(File->getName(), Dir, FileMgr)) { + if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) { + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; + } + } + + // This directory has a module map. + DirectoryHasModuleMap[Dir] = true; + return LMM_NewlyLoaded; +} + +const FileEntry * +HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { + // For frameworks, the preferred spelling is Modules/module.modulemap, but + // module.map at the framework root is also accepted. + SmallString<128> ModuleMapFileName(Dir->getName()); + if (IsFramework) + llvm::sys::path::append(ModuleMapFileName, "Modules"); + llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); + if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) + return F; + + // Continue to allow module.map + ModuleMapFileName = Dir->getName(); + llvm::sys::path::append(ModuleMapFileName, "module.map"); + return FileMgr.getFile(ModuleMapFileName); } -Module *HeaderSearch::loadFrameworkModule(StringRef Name, +Module *HeaderSearch::loadFrameworkModule(StringRef Name, const DirectoryEntry *Dir, bool IsSystem) { if (Module *Module = ModMap.findModule(Name)) return Module; // Try to load a module map file. - switch (loadModuleMapFile(Dir, IsSystem)) { + switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { case LMM_InvalidModuleMap: break; @@ -1201,53 +1250,30 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem) { +HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, + bool IsFramework) { if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) - return loadModuleMapFile(Dir, IsSystem); + return loadModuleMapFile(Dir, IsSystem, IsFramework); return LMM_NoDirectory; } HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem) { - llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir - = DirectoryHasModuleMap.find(Dir); +HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, + bool IsFramework) { + auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - - SmallString<128> ModuleMapFileName; - ModuleMapFileName += Dir->getName(); - unsigned ModuleMapDirNameLen = ModuleMapFileName.size(); - llvm::sys::path::append(ModuleMapFileName, "module.map"); - if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) { - // We have found a module map file. Try to parse it. - if (ModMap.parseModuleMapFile(ModuleMapFile, IsSystem)) { - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; - return LMM_InvalidModuleMap; - } - // This directory has a module map. - DirectoryHasModuleMap[Dir] = true; - - // Check whether there is a private module map that we need to load as well. - ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen, - ModuleMapFileName.end()); - llvm::sys::path::append(ModuleMapFileName, "module_private.map"); - if (const FileEntry *PrivateModuleMapFile - = FileMgr.getFile(ModuleMapFileName)) { - if (ModMap.parseModuleMapFile(PrivateModuleMapFile, IsSystem)) { - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; - return LMM_InvalidModuleMap; - } - } - - return LMM_NewlyLoaded; + if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { + LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem); + // Add Dir explicitly in case ModuleMapFile is in a subdirectory. + // E.g. Foo.framework/Modules/module.modulemap + // ^Dir ^ModuleMapFile + if (Result == LMM_NewlyLoaded) + DirectoryHasModuleMap[Dir] = true; + return Result; } - - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; return LMM_InvalidModuleMap; } @@ -1285,7 +1311,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { continue; // Try to load a module map file for the search directory. - loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem); + loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, /*IsFramework*/false); // Try to load module map files for immediate subdirectories of this search // directory. @@ -1310,7 +1336,8 @@ void HeaderSearch::loadTopLevelSystemModules() { // Try to load a module map file for the search directory. loadModuleMapFile(SearchDirs[Idx].getDir(), - SearchDirs[Idx].isSystemHeaderDirectory()); + SearchDirs[Idx].isSystemHeaderDirectory(), + SearchDirs[Idx].isFramework()); } } @@ -1323,7 +1350,8 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative); for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { - loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory()); + loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), + SearchDir.isFramework()); } SearchDir.setSearchedAllModuleMaps(true); |