]> granicus.if.org Git - clang/commitdiff
Within the module representation, generalize the notion of an umbrella
authorDouglas Gregor <dgregor@apple.com>
Thu, 8 Dec 2011 17:39:04 +0000 (17:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 8 Dec 2011 17:39:04 +0000 (17:39 +0000)
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

include/clang/Basic/Module.h
lib/Basic/Module.cpp
lib/Frontend/FrontendActions.cpp
lib/Lex/ModuleMap.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index 26a0b28182ad9e5008b7d66c01f9d94d0d72ba51..0f2a9a7b3d222b5752d2a6f312131ddd516b126a 100644 (file)
@@ -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;
index 97bddfa97ea10feeb095ee42f952bb3bf4978a58..169715736bc8729ffec93f85175b9bc80d0c05af 100644 (file)
@@ -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());
index 1a2df01bdfd551d47a12d1aad9d1d47337c822ec..190cdba5820ec732b5e2f7cdfa8ecb8495f97094 100644 (file)
@@ -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 {
index 0c9922ff2a1f0c51aa2b79ece026d4799c23b2d6..8457b1cea93bb2870ba5db60e2d9c89151e515f4 100644 (file)
@@ -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;
   }
index 76ba9e2b2631386e9102a024cabd552c5e3434ad..21be3aa50c7f39f123e0ed9abd9adeaca45c9305 100644 (file)
@@ -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;
         }
index 946bc76c40d05b0e601bedb0bf3ef59197a91f2b..1bd9050fe0bc8965208d684a79aec2b649a61d25 100644 (file)
@@ -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.