diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-16 23:02:25 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-16 23:02:25 +0000 |
commit | b65dbfff527537c10406632e14ecd94b8896a042 (patch) | |
tree | 72e38ff66539dbf2e9295efb14a1bd6aed1202a1 /clang/lib/Lex/ModuleMap.cpp | |
parent | f4d2e0d458394a537e9ca82f6ef16ae72995b4bf (diff) | |
download | bcm5719-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.cpp | 40 |
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) |