diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp | 516 |
1 files changed, 431 insertions, 85 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index 931145a..d688e23 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp @@ -13,6 +13,8 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderMap.h" +#include "clang/Lex/Lexer.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/Support/FileSystem.h" @@ -36,8 +38,12 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} -HeaderSearch::HeaderSearch(FileManager &FM) - : FileMgr(FM), FrameworkMap(64) { +HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, + const LangOptions &LangOpts, + const TargetInfo *Target) + : FileMgr(FM), Diags(Diags), FrameworkMap(64), + ModMap(FileMgr, *Diags.getClient(), LangOpts, Target) +{ AngledDirIdx = 0; SystemDirIdx = 0; NoCurDirSearch = false; @@ -98,58 +104,81 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { return 0; } -const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName, - std::string *ModuleFileName, - std::string *UmbrellaHeader) { +std::string HeaderSearch::getModuleFileName(Module *Module) { // If we don't have a module cache path, we can't do anything. - if (ModuleCachePath.empty()) { - if (ModuleFileName) - ModuleFileName->clear(); - return 0; - } + if (ModuleCachePath.empty()) + return std::string(); + + + SmallString<256> Result(ModuleCachePath); + llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm"); + return Result.str().str(); +} + +std::string HeaderSearch::getModuleFileName(StringRef ModuleName) { + // If we don't have a module cache path, we can't do anything. + if (ModuleCachePath.empty()) + return std::string(); - // Try to find the module path. - llvm::SmallString<256> FileName(ModuleCachePath); - llvm::sys::path::append(FileName, ModuleName + ".pcm"); - 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; + SmallString<256> Result(ModuleCachePath); + llvm::sys::path::append(Result, ModuleName + ".pcm"); + return Result.str().str(); +} + +Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { + // Look in the module map to determine if there is a module by this name. + Module *Module = ModMap.findModule(ModuleName); + if (Module || !AllowSearch) + return Module; - // Look in each of the framework directories for an umbrella header with - // the same name as the module. - // FIXME: We need a way for non-frameworks to provide umbrella headers. - llvm::SmallString<128> UmbrellaHeaderName; - UmbrellaHeaderName = ModuleName; - UmbrellaHeaderName += '/'; - UmbrellaHeaderName += ModuleName; - UmbrellaHeaderName += ".h"; + // Look through the various header search paths to load any avai;able module + // maps, searching for a module map that describes this module. for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { - // Skip non-framework include paths - if (!SearchDirs[Idx].isFramework()) + if (SearchDirs[Idx].isFramework()) { + // Search for or infer a module map for a framework. + SmallString<128> FrameworkDirName; + FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); + llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework"); + if (const DirectoryEntry *FrameworkDir + = FileMgr.getDirectory(FrameworkDirName)) { + bool IsSystem + = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; + Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); + 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; - // 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; + // Search for a module map file in this directory. + if (loadModuleMapFile(SearchDirs[Idx].getDir()) == LMM_NewlyLoaded) { + // We just loaded a module map file; check whether the module is + // available now. + Module = ModMap.findModule(ModuleName); + if (Module) + break; + } + + // Search for a module map in a subdirectory with the same name as the + // module. + SmallString<128> NestedModuleMapDirName; + NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); + llvm::sys::path::append(NestedModuleMapDirName, ModuleName); + if (loadModuleMapFile(NestedModuleMapDirName) == LMM_NewlyLoaded) { + // If we just loaded a module map file, look for the module again. + Module = ModMap.findModule(ModuleName); + if (Module) + break; } } - // We did not find an umbrella header. Clear out the UmbrellaHeader pointee - // so our caller knows that we failed. - UmbrellaHeader->clear(); - return 0; + return Module; } //===----------------------------------------------------------------------===// @@ -175,9 +204,11 @@ const FileEntry *DirectoryLookup::LookupFile( HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const { - llvm::SmallString<1024> TmpDir; + Module **SuggestedModule, + bool &InUserSpecifiedSystemFramework) const { + InUserSpecifiedSystemFramework = false; + + SmallString<1024> TmpDir; if (isNormalDir()) { // Concatenate the requested file onto the directory. TmpDir = getDir()->getName(); @@ -191,12 +222,27 @@ const FileEntry *DirectoryLookup::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } + + // If we have a module map that might map this header, load it and + // check whether we'll have a suggestion for a module. + if (SuggestedModule && HS.hasModuleMap(TmpDir, getDir())) { + const FileEntry *File = HS.getFileMgr().getFile(TmpDir.str(), + /*openFile=*/false); + if (!File) + return File; + + // If there is a module that corresponds to this header, + // suggest it. + *SuggestedModule = HS.findModuleForHeader(File); + return File; + } + return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); } if (isFramework()) return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, - BuildingModule, SuggestedModule); + SuggestedModule, InUserSpecifiedSystemFramework); assert(isHeaderMap() && "Unknown directory lookup"); const FileEntry * const Result = getHeaderMap()->LookupFile( @@ -223,8 +269,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const + Module **SuggestedModule, + bool &InUserSpecifiedSystemFramework) const { FileManager &FileMgr = HS.getFileMgr(); @@ -233,49 +279,71 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( if (SlashPos == StringRef::npos) return 0; // Find out if this is the home for the specified framework, by checking - // HeaderSearch. Possible answer are yes/no and unknown. - const DirectoryEntry *&FrameworkDirCache = + // HeaderSearch. Possible answers are yes/no and unknown. + HeaderSearch::FrameworkCacheEntry &CacheEntry = HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); // If it is known and in some other directory, fail. - if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) + if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) return 0; // Otherwise, construct the path to this framework dir. // FrameworkName = "/System/Library/Frameworks/" - llvm::SmallString<1024> FrameworkName; + SmallString<1024> FrameworkName; FrameworkName += getFrameworkDir()->getName(); if (FrameworkName.empty() || FrameworkName.back() != '/') FrameworkName.push_back('/'); // FrameworkName = "/System/Library/Frameworks/Cocoa" - FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); + StringRef ModuleName(Filename.begin(), SlashPos); + FrameworkName += ModuleName; // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" FrameworkName += ".framework/"; - // If the cache entry is still unresolved, query to see if the cache entry is - // still unresolved. If so, check its existence now. - if (FrameworkDirCache == 0) { + // If the cache entry was unresolved, populate it now. + if (CacheEntry.Directory == 0) { HS.IncrementFrameworkLookupCount(); // If the framework dir doesn't exist, we fail. - // FIXME: It's probably more efficient to query this with FileMgr.getDir. - bool Exists; - if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists) - return 0; + const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); + if (Dir == 0) return 0; // Otherwise, if it does, remember that this is the right direntry for this // framework. - FrameworkDirCache = getFrameworkDir(); + CacheEntry.Directory = getFrameworkDir(); + + // If this is a user search directory, check if the framework has been + // user-specified as a system framework. + if (getDirCharacteristic() == SrcMgr::C_User) { + SmallString<1024> SystemFrameworkMarker(FrameworkName); + SystemFrameworkMarker += ".system_framework"; + if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) { + CacheEntry.IsUserSpecifiedSystemFramework = true; + } + } } + // Set the 'user-specified system framework' flag. + InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; + if (RelativePath != NULL) { RelativePath->clear(); RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); } + // If we're allowed to look for modules, try to load or create the module + // corresponding to this framework. + Module *Module = 0; + if (SuggestedModule) { + if (const DirectoryEntry *FrameworkDir + = FileMgr.getDirectory(FrameworkName)) { + bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; + Module = HS.loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); + } + } + // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); @@ -287,16 +355,13 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); } - /// Determine whether this is the module we're building or not. - bool AutomaticImport = SuggestedModule && - (BuildingModule != StringRef(Filename.begin(), SlashPos)) && - !Filename.substr(SlashPos + 1).startswith(".."); - + // Determine whether this is the module we're building or not. + bool AutomaticImport = Module; FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!AutomaticImport)) { if (AutomaticImport) - *SuggestedModule = StringRef(Filename.begin(), SlashPos); + *SuggestedModule = HS.findModuleForHeader(FE); return FE; } @@ -311,10 +376,14 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!AutomaticImport); if (FE && AutomaticImport) - *SuggestedModule = StringRef(Filename.begin(), SlashPos); + *SuggestedModule = HS.findModuleForHeader(FE); return FE; } +void HeaderSearch::setTarget(const TargetInfo &Target) { + ModMap.setTarget(Target); +} + //===----------------------------------------------------------------------===// // Header File Location. @@ -334,10 +403,11 @@ const FileEntry *HeaderSearch::LookupFile( const FileEntry *CurFileEnt, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule) + Module **SuggestedModule, + bool SkipCache) { if (SuggestedModule) - *SuggestedModule = StringRef(); + *SuggestedModule = 0; // If 'Filename' is absolute, check to see if it exists and no searching. if (llvm::sys::path::is_absolute(Filename)) { @@ -362,7 +432,7 @@ const FileEntry *HeaderSearch::LookupFile( // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". // This search is not done for <> headers. if (CurFileEnt && !isAngled && !NoCurDirSearch) { - llvm::SmallString<1024> TmpDir; + SmallString<1024> TmpDir; // Concatenate the requested file onto the directory. // FIXME: Portability. Filename concatenation should be in sys::Path. TmpDir += CurFileEnt->getDir()->getName(); @@ -410,7 +480,7 @@ const FileEntry *HeaderSearch::LookupFile( // If the entry has been previously looked up, the first value will be // non-zero. If the value is equal to i (the start point of our search), then // this is a matching hit. - if (CacheLookup.first == i+1) { + if (!SkipCache && CacheLookup.first == i+1) { // Skip querying potentially lots of directories for this lookup. i = CacheLookup.second; } else { @@ -422,9 +492,10 @@ const FileEntry *HeaderSearch::LookupFile( // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { + bool InUserSpecifiedSystemFramework = false; const FileEntry *FE = SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, - BuildingModule, SuggestedModule); + SuggestedModule, InUserSpecifiedSystemFramework); if (!FE) continue; CurDir = &SearchDirs[i]; @@ -433,6 +504,12 @@ const FileEntry *HeaderSearch::LookupFile( HeaderFileInfo &HFI = getFileInfo(FE); HFI.DirInfo = CurDir->getDirCharacteristic(); + // If the directory characteristic is User but this framework was + // user-specified to be treated as a system framework, promote the + // characteristic. + if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) + HFI.DirInfo = SrcMgr::C_System; + // If this file is found in a header map and uses the framework style of // includes, then this header is part of a framework we're building. if (CurDir->isIndexHeaderMap()) { @@ -456,7 +533,7 @@ const FileEntry *HeaderSearch::LookupFile( if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); if (IncludingHFI.IndexHeaderMapHeader) { - llvm::SmallString<128> ScratchFilename; + SmallString<128> ScratchFilename; ScratchFilename += IncludingHFI.Framework; ScratchFilename += '/'; ScratchFilename += Filename; @@ -491,6 +568,7 @@ LookupSubframeworkHeader(StringRef Filename, assert(ContextFileEnt && "No context file?"); // Framework names must have a '/' in the filename. Find it. + // FIXME: Should we permit '\' on Windows? size_t SlashPos = Filename.find('/'); if (SlashPos == StringRef::npos) return 0; @@ -498,30 +576,32 @@ LookupSubframeworkHeader(StringRef Filename, const char *ContextName = ContextFileEnt->getName(); // If the context info wasn't a framework, couldn't be a subframework. - const char *FrameworkPos = strstr(ContextName, ".framework/"); - if (FrameworkPos == 0) + const unsigned DotFrameworkLen = 10; + const char *FrameworkPos = strstr(ContextName, ".framework"); + if (FrameworkPos == 0 || + (FrameworkPos[DotFrameworkLen] != '/' && + FrameworkPos[DotFrameworkLen] != '\\')) return 0; - llvm::SmallString<1024> FrameworkName(ContextName, - FrameworkPos+strlen(".framework/")); + SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1); // Append Frameworks/HIToolbox.framework/ FrameworkName += "Frameworks/"; FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); FrameworkName += ".framework/"; - llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = + llvm::StringMapEntry<FrameworkCacheEntry> &CacheLookup = FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); // Some other location? - if (CacheLookup.getValue() && + if (CacheLookup.getValue().Directory && CacheLookup.getKeyLength() == FrameworkName.size() && memcmp(CacheLookup.getKeyData(), &FrameworkName[0], CacheLookup.getKeyLength()) != 0) return 0; // Cache subframework. - if (CacheLookup.getValue() == 0) { + if (CacheLookup.getValue().Directory == 0) { ++NumSubFrameworkLookups; // If the framework dir doesn't exist, we fail. @@ -530,7 +610,7 @@ LookupSubframeworkHeader(StringRef Filename, // Otherwise, if it does, remember that this is the right direntry for this // framework. - CacheLookup.setValue(Dir); + CacheLookup.getValue().Directory = Dir; } const FileEntry *FE = 0; @@ -541,7 +621,7 @@ LookupSubframeworkHeader(StringRef Filename, } // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" - llvm::SmallString<1024> HeadersFilename(FrameworkName); + SmallString<1024> HeadersFilename(FrameworkName); HeadersFilename += "Headers/"; if (SearchPath != NULL) { SearchPath->clear(); @@ -576,6 +656,28 @@ LookupSubframeworkHeader(StringRef Filename, return FE; } +/// \brief Helper static function to normalize a path for injection into +/// a synthetic header. +/*static*/ std::string +HeaderSearch::NormalizeDashIncludePath(StringRef File, FileManager &FileMgr) { + // Implicit include paths should be resolved relative to the current + // working directory first, and then use the regular header search + // mechanism. The proper way to handle this is to have the + // predefines buffer located at the current working directory, but + // it has no file entry. For now, workaround this by using an + // absolute path if we find the file here, and otherwise letting + // header search handle it. + SmallString<128> Path(File); + llvm::sys::fs::make_absolute(Path); + bool exists; + if (llvm::sys::fs::exists(Path.str(), exists) || !exists) + Path = File; + else if (exists) + FileMgr.getFile(File); + + return Lexer::Stringify(Path.str()); +} + //===----------------------------------------------------------------------===// // File Info Management. //===----------------------------------------------------------------------===// @@ -687,3 +789,247 @@ size_t HeaderSearch::getTotalMemory() const { StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { return FrameworkNames.GetOrCreateValue(Framework).getKey(); } + +bool HeaderSearch::hasModuleMap(StringRef FileName, + const DirectoryEntry *Root) { + llvm::SmallVector<const DirectoryEntry *, 2> FixUpDirectories; + + StringRef DirName = FileName; + do { + // Get the parent directory name. + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.empty()) + return false; + + // Determine whether this directory exists. + const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); + if (!Dir) + return false; + + // Try to load the module map file in this directory. + switch (loadModuleMapFile(Dir)) { + case LMM_NewlyLoaded: + case LMM_AlreadyLoaded: + // Success. All of the directories we stepped through inherit this module + // map file. + for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I) + DirectoryHasModuleMap[FixUpDirectories[I]] = true; + + return true; + + case LMM_NoDirectory: + case LMM_InvalidModuleMap: + break; + } + + // If we hit the top of our search, we're done. + if (Dir == Root) + return false; + + // Keep track of all of the directories we checked, so we can mark them as + // having module maps if we eventually do find a module map. + FixUpDirectories.push_back(Dir); + } while (true); +} + +Module *HeaderSearch::findModuleForHeader(const FileEntry *File) { + if (Module *Mod = ModMap.findModuleForHeader(File)) + return Mod; + + return 0; +} + +bool HeaderSearch::loadModuleMapFile(const FileEntry *File) { + const DirectoryEntry *Dir = File->getDir(); + + llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir + = DirectoryHasModuleMap.find(Dir); + if (KnownDir != DirectoryHasModuleMap.end()) + return !KnownDir->second; + + bool Result = ModMap.parseModuleMapFile(File); + 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); + } + + DirectoryHasModuleMap[Dir] = !Result; + return Result; +} + +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)) { + case LMM_InvalidModuleMap: + break; + + case LMM_AlreadyLoaded: + case LMM_NoDirectory: + return 0; + + case LMM_NewlyLoaded: + return ModMap.findModule(Name); + } + + // The top-level framework directory, from which we'll infer a framework + // module. + const DirectoryEntry *TopFrameworkDir = Dir; + + // The path from the module we're actually looking for back to the top-level + // framework name. + llvm::SmallVector<StringRef, 2> SubmodulePath; + SubmodulePath.push_back(Name); + + // Walk the directory structure to find any enclosing frameworks. + StringRef DirName = Dir->getName(); + do { + // Get the parent directory name. + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.empty()) + break; + + // Determine whether this directory exists. + Dir = FileMgr.getDirectory(DirName); + if (!Dir) + break; + + // If this is a framework directory, then we're a subframework of this + // framework. + if (llvm::sys::path::extension(DirName) == ".framework") { + SubmodulePath.push_back(llvm::sys::path::stem(DirName)); + TopFrameworkDir = Dir; + } + } while (true); + + // Try to infer a module map from the top-level framework directory. + Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), + TopFrameworkDir, + IsSystem, + /*Parent=*/0); + + // Follow the submodule path to find the requested (sub)framework module + // within the top-level framework module. + SubmodulePath.pop_back(); + while (!SubmodulePath.empty() && Result) { + Result = ModMap.lookupModuleQualified(SubmodulePath.back(), Result); + SubmodulePath.pop_back(); + } + return Result; +} + + +HeaderSearch::LoadModuleMapResult +HeaderSearch::loadModuleMapFile(StringRef DirName) { + if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) + return loadModuleMapFile(Dir); + + return LMM_NoDirectory; +} + +HeaderSearch::LoadModuleMapResult +HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir) { + llvm::DenseMap<const DirectoryEntry *, bool>::iterator 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)) { + // 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)) { + // No suitable module map. + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; + } + } + + return LMM_NewlyLoaded; + } + + // No suitable module map. + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; +} + +void HeaderSearch::collectAllModules(llvm::SmallVectorImpl<Module *> &Modules) { + Modules.clear(); + + // Load module maps for each of the header search directories. + for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { + if (SearchDirs[Idx].isFramework()) { + llvm::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(), + DirNative); + + // Search each of the ".framework" directories to load them as modules. + bool IsSystem = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; + for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + if (llvm::sys::path::extension(Dir->path()) != ".framework") + continue; + + const DirectoryEntry *FrameworkDir = FileMgr.getDirectory(Dir->path()); + if (!FrameworkDir) + continue; + + // Load this framework module. + loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, + IsSystem); + } + continue; + } + + // FIXME: Deal with header maps. + if (SearchDirs[Idx].isHeaderMap()) + continue; + + // Try to load a module map file for the search directory. + loadModuleMapFile(SearchDirs[Idx].getDir()); + + // Try to load module map files for immediate subdirectories of this search + // directory. + llvm::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(SearchDirs[Idx].getDir()->getName(), DirNative); + for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + loadModuleMapFile(Dir->path()); + } + } + + // Populate the list of modules. + for (ModuleMap::module_iterator M = ModMap.module_begin(), + MEnd = ModMap.module_end(); + M != MEnd; ++M) { + Modules.push_back(M->getValue()); + } +} + |