summaryrefslogtreecommitdiffstats
path: root/clang/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
commitb65dbfff527537c10406632e14ecd94b8896a042 (patch)
tree72e38ff66539dbf2e9295efb14a1bd6aed1202a1 /clang/lib/Lex/ModuleMap.cpp
parentf4d2e0d458394a537e9ca82f6ef16ae72995b4bf (diff)
downloadbcm5719-llvm-b65dbfff527537c10406632e14ecd94b8896a042.tar.gz
bcm5719-llvm-b65dbfff527537c10406632e14ecd94b8896a042.zip
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. llvm-svn: 144859
Diffstat (limited to 'clang/lib/Lex/ModuleMap.cpp')
-rw-r--r--clang/lib/Lex/ModuleMap.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index bc43e01ac5c..f6751b78f1e 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/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)
OpenPOWER on IntegriCloud