diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-11 19:10:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-11 19:10:28 +0000 |
commit | a30cfe5026b12c28b7b575b48176e0a3543ce939 (patch) | |
tree | 3a53c6c81dd0abdebd12dc69b71f5f1e90b90432 /lib/Lex/HeaderSearch.cpp | |
parent | b1ce730962fba225a7d59215e1a0ee71ce633b89 (diff) |
Introduce basic support for parsing module map files.
Module map files provide a way to map between headers and modules, so
that we can layer a module system on top of existing headers without
changing those headers at all.
This commit introduces the module map file parser and the module map
that it generates, and wires up the module map file parser so that
we'll automatically find module map files as part of header
search. Note that we don't yet use the information stored in the
module map.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144402 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/HeaderSearch.cpp')
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 837b913d47..6403cfb868 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -13,6 +13,7 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderMap.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/Support/FileSystem.h" @@ -37,7 +38,8 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags) - : FileMgr(FM), Diags(Diags), FrameworkMap(64) + : FileMgr(FM), Diags(Diags), FrameworkMap(64), + ModMap(FileMgr, *Diags.getClient()) { AngledDirIdx = 0; SystemDirIdx = 0; @@ -192,6 +194,24 @@ 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. + StringRef Module = HS.getModuleForHeader(File); + if (!Module.empty() && Module != BuildingModule) + *SuggestedModule = Module; + + return File; + } + return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); } @@ -688,3 +708,73 @@ 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; + + llvm::DenseMap<const DirectoryEntry *, bool>::iterator + KnownDir = DirectoryHasModuleMap.find(Dir); + if (KnownDir != DirectoryHasModuleMap.end()) { + // We have seen this directory before. If it has no module map file, + // we're done. + if (!KnownDir->second) + return false; + + // 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; + } + + // We have not checked for a module map file in this directory yet; + // do so now. + llvm::SmallString<128> ModuleMapFileName; + ModuleMapFileName += Dir->getName(); + 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)) { + // This directory has a module map. + DirectoryHasModuleMap[Dir] = true; + + // 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; + } + } + + // This directory did not have a module map file. + DirectoryHasModuleMap[Dir] = 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); + + return false; +} + +StringRef HeaderSearch::getModuleForHeader(const FileEntry *File) { + // FIXME: Actually look for the corresponding module for this header. + return StringRef(); +} + + |