From: Douglas Gregor Date: Thu, 8 Dec 2011 17:39:04 +0000 (+0000) Subject: Within the module representation, generalize the notion of an umbrella X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=10694cee2588442bee1e717f5042c58ffee25279;p=clang Within the module representation, generalize the notion of an umbrella header to also support umbrella directories. The umbrella directory for an umbrella header is the directory in which the umbrella header resides. No functionality change yet, but it's coming. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146158 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 26a0b28182..0f2a9a7b3d 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -29,7 +30,8 @@ namespace llvm { namespace clang { class FileEntry; - +class DirectoryEntry; + /// \brief Describes the name of a module. typedef llvm::SmallVector, 2> ModuleId; @@ -47,10 +49,8 @@ public: /// module. Module *Parent; - /// \brief The umbrella header, if any. - /// - /// Only the top-level module can have an umbrella header. - const FileEntry *UmbrellaHeader; + /// \brief The umbrella header or directory. + llvm::PointerUnion Umbrella; /// \brief The submodules of this module, indexed by name. llvm::StringMap SubModules; @@ -130,7 +130,7 @@ public: /// \brief Construct a top-level module. explicit Module(StringRef Name, SourceLocation DefinitionLoc, bool IsFramework) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0), + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(), IsFramework(IsFramework), IsExplicit(false), InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), NameVisibility(Hidden) { } @@ -139,7 +139,7 @@ public: Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit), + Umbrella(), IsFramework(IsFramework), IsExplicit(IsExplicit), InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false),NameVisibility(Hidden) { } @@ -184,6 +184,16 @@ public: return getTopLevelModule()->Name; } + /// \brief Retrieve the directory for which this module serves as the + /// umbrella. + const DirectoryEntry *getUmbrellaDir() const; + + /// \brief Retrieve the header that serves as the umbrella header for this + /// module. + const FileEntry *getUmbrellaHeader() const { + return Umbrella.dyn_cast(); + } + /// \brief Print the module map for this module to the given stream. /// void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 97bddfa97e..169715736b 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -65,6 +65,13 @@ std::string Module::getFullModuleName() const { return Result; } +const DirectoryEntry *Module::getUmbrellaDir() const { + if (const FileEntry *Header = getUmbrellaHeader()) + return Header->getDir(); + + return Umbrella.dyn_cast(); +} + static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) { for (unsigned I = 0, N = Id.size(); I != N; ++I) { if (I) @@ -81,7 +88,7 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const { OS << "explicit "; OS << "module " << Name << " {\n"; - if (UmbrellaHeader) { + if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(UmbrellaHeader->getName()); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 1a2df01bdf..190cdba582 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -145,14 +145,16 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, Includes += "\"\n"; } - if (Module->UmbrellaHeader && Module->Parent) { - // Include the umbrella header for submodules. - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += Module->UmbrellaHeader->getName(); - Includes += "\"\n"; + if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { + if (Module->Parent) { + // Include the umbrella header for submodules. + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += UmbrellaHeader->getName(); + Includes += "\"\n"; + } } // Recurse into submodules. @@ -197,29 +199,32 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, return false; } + // Do we have an umbrella header for this module? + const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader(); + // Collect the set of #includes we need to build the module. llvm::SmallString<256> HeaderContents; collectModuleHeaderIncludes(CI.getLangOpts(), Module, HeaderContents); - if (Module->UmbrellaHeader && HeaderContents.empty()) { + if (UmbrellaHeader && HeaderContents.empty()) { // Simple case: we have an umbrella header and there are no additional // includes, we can just parse the umbrella header directly. - setCurrentFile(Module->UmbrellaHeader->getName(), getCurrentFileKind()); + setCurrentFile(UmbrellaHeader->getName(), getCurrentFileKind()); return true; } FileManager &FileMgr = CI.getFileManager(); llvm::SmallString<128> HeaderName; time_t ModTime; - if (Module->UmbrellaHeader) { + if (UmbrellaHeader) { // Read in the umbrella header. // FIXME: Go through the source manager; the umbrella header may have // been overridden. std::string ErrorStr; llvm::MemoryBuffer *UmbrellaContents - = FileMgr.getBufferForFile(Module->UmbrellaHeader, &ErrorStr); + = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr); if (!UmbrellaContents) { CI.getDiagnostics().Report(diag::err_missing_umbrella_header) - << Module->UmbrellaHeader->getName() << ErrorStr; + << UmbrellaHeader->getName() << ErrorStr; return false; } @@ -232,8 +237,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, HeaderContents += OldContents; // Pretend that we're parsing the umbrella header. - HeaderName = Module->UmbrellaHeader->getName(); - ModTime = Module->UmbrellaHeader->getModificationTime(); + HeaderName = UmbrellaHeader->getName(); + ModTime = UmbrellaHeader->getModificationTime(); delete UmbrellaContents; } else { diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 0c9922ff2a..8457b1cea9 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -106,9 +106,9 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { Module *Result = KnownDir->second; // Search up the module stack until we find a module with an umbrella - // header. + // directory. Module *UmbrellaModule = Result; - while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent) + while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) UmbrellaModule = UmbrellaModule->Parent; if (UmbrellaModule->InferSubmodules) { @@ -260,7 +260,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, Modules[ModuleName] = Result; // umbrella "umbrella-header-name" - Result->UmbrellaHeader = UmbrellaHeader; + Result->Umbrella = UmbrellaHeader; Headers[UmbrellaHeader] = Result; UmbrellaDirs[FrameworkDir] = Result; @@ -336,7 +336,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ Headers[UmbrellaHeader] = Mod; - Mod->UmbrellaHeader = UmbrellaHeader; + Mod->Umbrella = UmbrellaHeader; const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir(); if (Mod->IsFramework) @@ -864,10 +864,10 @@ void ModuleMapParser::parseUmbrellaDecl() { SourceLocation FileNameLoc = consumeToken(); // Check whether we already have an umbrella header. - if (ActiveModule->UmbrellaHeader) { + if (ActiveModule->getUmbrellaHeader()) { Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) << ActiveModule->getFullModuleName() - << ActiveModule->UmbrellaHeader->getName(); + << ActiveModule->getUmbrellaHeader()->getName(); HadError = true; return; } @@ -1064,7 +1064,7 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { } // Inferred modules must have umbrella headers. - if (!Failed && !ActiveModule->UmbrellaHeader) { + if (!Failed && !ActiveModule->getUmbrellaHeader()) { Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); Failed = true; } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 76ba9e2b26..21be3aa50c 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3099,9 +3099,9 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { StringRef FileName(BlobStart, BlobLen); if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) { - if (!CurrentModule->UmbrellaHeader) + if (!CurrentModule->getUmbrellaHeader()) ModMap.setUmbrellaHeader(CurrentModule, Umbrella); - else if (CurrentModule->UmbrellaHeader != Umbrella) { + else if (CurrentModule->getUmbrellaHeader() != Umbrella) { Error("mismatched umbrella headers in submodule"); return Failure; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 946bc76c40..1bd9050fe0 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1941,11 +1941,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); // Emit the umbrella header, if there is one. - if (Mod->UmbrellaHeader) { + if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) { Record.clear(); Record.push_back(SUBMODULE_UMBRELLA); Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, - Mod->UmbrellaHeader->getName()); + UmbrellaHeader->getName()); } // Emit the headers.