aboutsummaryrefslogtreecommitdiff
path: root/lib/Lex/ModuleMap.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-16 23:02:25 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-16 23:02:25 +0000
commitadb979924ade3e25342c38a5b564400b4e0540c1 (patch)
tree6a1a626999f8c57453479faa97e6d893ef1db2f5 /lib/Lex/ModuleMap.cpp
parent960809e7e9f4a6e949797d20bc081da80495c0e1 (diff)
A module with an umbrella header assumes that all of the headers in
the umbrella header's directory and its subdirectories are part of the module (that's why it's an umbrella). Make sure that these headers are considered to be part of the module for lookup purposes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144859 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r--lib/Lex/ModuleMap.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index bc43e01ac5..f6751b78f1 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -81,6 +81,41 @@ ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
if (Known != Headers.end())
return Known->second;
+ const DirectoryEntry *Dir = File->getDir();
+ llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
+ = UmbrellaDirs.find(Dir);
+ if (KnownDir != UmbrellaDirs.end())
+ return KnownDir->second;
+
+ // Walk up the directory hierarchy looking for umbrella headers.
+ llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
+ StringRef DirName = Dir->getName();
+ do {
+ // Retrieve our parent path.
+ DirName = llvm::sys::path::parent_path(DirName);
+ if (DirName.empty())
+ break;
+
+ // Resolve the parent path to a directory entry.
+ Dir = SourceMgr->getFileManager().getDirectory(DirName);
+ if (!Dir)
+ break;
+
+ KnownDir = UmbrellaDirs.find(Dir);
+ if (KnownDir != UmbrellaDirs.end()) {
+ Module *Result = KnownDir->second;
+
+ // Record each of the directories we stepped through as being part of
+ // the module we found, since the umbrella header covers them all.
+ for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
+ UmbrellaDirs[SkippedDirs[I]] = Result;
+
+ return Result;
+ }
+
+ SkippedDirs.push_back(Dir);
+ } while (true);
+
return 0;
}
@@ -493,10 +528,15 @@ void ModuleMapParser::parseUmbrellaDecl() {
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
<< FileName << OwningModule->getFullModuleName();
HadError = true;
+ } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
+ Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
+ << OwningModule->getFullModuleName();
+ HadError = true;
} else {
// Record this umbrella header.
ActiveModule->UmbrellaHeader = File;
Map.Headers[File] = ActiveModule;
+ Map.UmbrellaDirs[Directory] = ActiveModule;
}
} else {
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)