diff options
-rw-r--r-- | include/clang/Basic/Module.h | 24 | ||||
-rw-r--r-- | lib/Basic/Module.cpp | 9 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 35 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 14 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 4 |
6 files changed, 56 insertions, 34 deletions
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<std::pair<std::string, SourceLocation>, 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<const DirectoryEntry *, const FileEntry *> Umbrella; /// \brief The submodules of this module, indexed by name. llvm::StringMap<Module *> 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<const FileEntry *>(); + } + /// \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<const DirectoryEntry *>(); +} + 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. |