diff options
author | Daniel Jasper <djasper@google.com> | 2013-10-22 08:09:47 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2013-10-22 08:09:47 +0000 |
commit | 97da9178ce5167da1bbad45ffcbb80b067a6f7f2 (patch) | |
tree | bf472689291f0acd800f76212155a804afff2313 /clang/lib/Lex/ModuleMap.cpp | |
parent | 2f8dc08b8cf4a18c09ec7ca8eb2b619f22cbfbd0 (diff) | |
download | bcm5719-llvm-97da9178ce5167da1bbad45ffcbb80b067a6f7f2.tar.gz bcm5719-llvm-97da9178ce5167da1bbad45ffcbb80b067a6f7f2.zip |
Allow a header to be part of multiple modules.
This patch changes two things:
a) Allow a header to be part of multiple modules. The reasoning is that
in existing codebases that have a module-like build system, the same
headers might be used in several build targets. Simple reasons might be
that they defined different classes that are declared in the same
header. Supporting a header as a part of multiple modules will make the
transistion easier for those cases. A later step in clang can then
determine whether the two modules are actually compatible and can be
merged and error out appropriately. The later check is similar to what
needs to be done for template specializations anyway.
b) Allow modules to be stored in a directory tree separate from the
headers they describe.
Review: http://llvm-reviews.chandlerc.com/D1951
llvm-svn: 193151
Diffstat (limited to 'clang/lib/Lex/ModuleMap.cpp')
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 86 |
1 files changed, 59 insertions, 27 deletions
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index a10679af158..25d68ace0f1 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -168,14 +168,41 @@ static bool isBuiltinHeader(StringRef FileName) { .Default(false); } -ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { +ModuleMap::KnownHeader +ModuleMap::findModuleForHeader(const FileEntry *File, + Module *RequestingModule) { HeadersMap::iterator Known = Headers.find(File); if (Known != Headers.end()) { - // If a header is not available, don't report that it maps to anything. - if (!Known->second.isAvailable()) - return KnownHeader(); + ModuleMap::KnownHeader Result = KnownHeader(); + + // Iterate over all modules that 'File' is part of to find the best fit. + for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(), + E = Known->second.end(); + I != E; ++I) { + // Cannot use a module if the header is excluded or unavailable in it. + if (I->getRole() == ModuleMap::ExcludedHeader || + !I->getModule()->isAvailable()) + continue; - return Known->second; + // If 'File' is part of 'RequestingModule', 'RequestingModule' is the + // module we are looking for. + if (I->getModule() == RequestingModule) + return *I; + + // If uses need to be specified explicitly, we are only allowed to return + // modules that are explicitly used by the requesting module. + if (RequestingModule && LangOpts.ModulesDeclUse && + std::find(RequestingModule->DirectUses.begin(), + RequestingModule->DirectUses.end(), + I->getModule()) == RequestingModule->DirectUses.end()) + continue; + Result = *I; + // If 'File' is a public header of this module, this is as good as we + // are going to get. + if (I->getRole() == ModuleMap::NormalHeader) + break; + } + return Result; } // If we've found a builtin header within Clang's builtin include directory, @@ -186,14 +213,8 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { HeaderInfo.loadTopLevelSystemModules(); // Check again. - Known = Headers.find(File); - if (Known != Headers.end()) { - // If a header is not available, don't report that it maps to anything. - if (!Known->second.isAvailable()) - return KnownHeader(); - - return Known->second; - } + if (Headers.find(File) != Headers.end()) + return findModuleForHeader(File, RequestingModule); } const DirectoryEntry *Dir = File->getDir(); @@ -262,14 +283,14 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { UmbrellaDirs[SkippedDirs[I]] = Result; } - Headers[File] = KnownHeader(Result, NormalHeader); + Headers[File].push_back(KnownHeader(Result, NormalHeader)); // If a header corresponds to an unavailable module, don't report // that it maps to anything. if (!Result->isAvailable()) return KnownHeader(); - return Headers[File]; + return Headers[File].back(); } SkippedDirs.push_back(Dir); @@ -288,8 +309,16 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { HeadersMap::const_iterator Known = Headers.find(Header); - if (Known != Headers.end()) - return !Known->second.isAvailable(); + if (Known != Headers.end()) { + for (SmallVectorImpl<KnownHeader>::const_iterator + I = Known->second.begin(), + E = Known->second.end(); + I != E; ++I) { + if (I->isAvailable()) + return false; + } + return true; + } const DirectoryEntry *Dir = Header->getDir(); SmallVector<const DirectoryEntry *, 2> SkippedDirs; @@ -534,7 +563,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, // umbrella header "umbrella-header-name" Result->Umbrella = UmbrellaHeader; - Headers[UmbrellaHeader] = KnownHeader(Result, NormalHeader); + Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader)); UmbrellaDirs[UmbrellaHeader->getDir()] = Result; // export * @@ -598,7 +627,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, } void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ - Headers[UmbrellaHeader] = KnownHeader(Mod, NormalHeader); + Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); Mod->Umbrella = UmbrellaHeader; UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; } @@ -620,7 +649,7 @@ void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader); } - Headers[Header] = KnownHeader(Mod, Role); + Headers[Header].push_back(KnownHeader(Mod, Role)); } const FileEntry * @@ -642,8 +671,15 @@ void ModuleMap::dump() { llvm::errs() << "Headers:"; for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); H != HEnd; ++H) { - llvm::errs() << " \"" << H->first->getName() << "\" -> " - << H->second.getModule()->getFullModuleName() << "\n"; + llvm::errs() << " \"" << H->first->getName() << "\" -> "; + for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), + E = H->second.end(); + I != E; ++I) { + if (I != H->second.begin()) + llvm::errs() << ","; + llvm::errs() << I->getModule()->getFullModuleName(); + } + llvm::errs() << "\n"; } } @@ -1494,11 +1530,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // Come up with a lazy way to do this. if (File) { - if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) { - Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) - << FileName << OwningModule.getModule()->getFullModuleName(); - HadError = true; - } else if (LeadingToken == MMToken::UmbrellaKeyword) { + if (LeadingToken == MMToken::UmbrellaKeyword) { const DirectoryEntry *UmbrellaDir = File->getDir(); if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) |