[cfe-commits] r165921 - in /cfe/trunk: include/clang/Basic/Module.h include/clang/Lex/ModuleMap.h include/clang/Serialization/ASTBitCodes.h lib/Basic/Module.cpp lib/Lex/ModuleMap.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/Modules/Inputs/NoUmbrella.framework/module.map

Douglas Gregor dgregor at apple.com
Sun Oct 14 23:28:11 PDT 2012


Author: dgregor
Date: Mon Oct 15 01:28:11 2012
New Revision: 165921

URL: http://llvm.org/viewvc/llvm-project?rev=165921&view=rev
Log:
Introduce the notion of excluded headers into the module map
description. Previously, one could emulate this behavior by placing
the header in an always-unavailable submodule, but Argyrios guilted me
into expressing this idea properly.

Modified:
    cfe/trunk/include/clang/Basic/Module.h
    cfe/trunk/include/clang/Lex/ModuleMap.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/Basic/Module.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Mon Oct 15 01:28:11 2012
@@ -73,6 +73,9 @@
   /// \brief The headers that are part of this module.
   llvm::SmallVector<const FileEntry *, 2> Headers;
 
+  /// \brief The headers that are explicitly excluded from this module.
+  llvm::SmallVector<const FileEntry *, 2> ExcludedHeaders;
+
   /// \brief The top-level headers associated with this module.
   llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;
 

Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Mon Oct 15 01:28:11 2012
@@ -52,10 +52,37 @@
 
   /// \brief The top-level modules that are known.
   llvm::StringMap<Module *> Modules;
-  
+
+  /// \brief A header that is known to reside within a given module,
+  /// whether it was included or excluded.
+  class KnownHeader {
+    llvm::PointerIntPair<Module *, 1, bool> Storage;
+
+  public:
+    KnownHeader() : Storage(0, false) { }
+    KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { }
+
+    /// \brief Retrieve the module the header is stored in.
+    Module *getModule() const { return Storage.getPointer(); }
+
+    /// \brief Whether this header is explicitly excluded from the module.
+    bool isExcluded() const { return Storage.getInt(); }
+
+    /// \brief Whether this header is available in the module.
+    bool isAvailable() const { 
+      return !isExcluded() && getModule()->isAvailable(); 
+    }
+
+    // \brief Whether this known header is valid (i.e., it has an
+    // associated module).
+    operator bool() const { return Storage.getPointer() != 0; }
+  };
+
+  typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
+
   /// \brief Mapping from each header to the module that owns the contents of the
   /// that header.
-  llvm::DenseMap<const FileEntry *, Module *> Headers;
+  HeadersMap Headers;
   
   /// \brief Mapping from directories with umbrella headers to the module
   /// that is generated from the umbrella header.
@@ -215,7 +242,9 @@
   void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
 
   /// \brief Adds this header to the given module.
-  void addHeader(Module *Mod, const FileEntry *Header);
+  /// \param Excluded Whether this header is explicitly excluded from the
+  /// module; otherwise, it's included in the module.
+  void addHeader(Module *Mod, const FileEntry *Header, bool Excluded);
 
   /// \brief Parse the given module map file, and record any modules we 
   /// encounter.

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Oct 15 01:28:11 2012
@@ -565,7 +565,10 @@
       /// submodule.
       SUBMODULE_EXPORTS = 7,
       /// \brief Specifies a required feature.
-      SUBMODULE_REQUIRES = 8
+      SUBMODULE_REQUIRES = 8,
+      /// \brief Specifies a header that has been explicitly excluded
+      /// from this submodule.
+      SUBMODULE_EXCLUDED_HEADER = 9
     };
 
     /// \brief Record types used within a comments block.

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Mon Oct 15 01:28:11 2012
@@ -219,6 +219,13 @@
     OS.write_escaped(Headers[I]->getName());
     OS << "\"\n";
   }
+
+  for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) {
+    OS.indent(Indent + 2);
+    OS << "exclude header \"";
+    OS.write_escaped(ExcludedHeaders[I]->getName());
+    OS << "\"\n";
+  }
   
   for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
        MI != MIEnd; ++MI)

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Oct 15 01:28:11 2012
@@ -146,15 +146,13 @@
 }
 
 Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
-  llvm::DenseMap<const FileEntry *, Module *>::iterator Known
-    = Headers.find(File);
+  HeadersMap::iterator Known = Headers.find(File);
   if (Known != Headers.end()) {
-    // If a header corresponds to an unavailable module, don't report
-    // that it maps to anything.
-    if (!Known->second->isAvailable())
+    // If a header is not available, don't report that it maps to anything.
+    if (!Known->second.isAvailable())
       return 0;
 
-    return Known->second;
+    return Known->second.getModule();
   }
   
   const DirectoryEntry *Dir = File->getDir();
@@ -218,7 +216,7 @@
           UmbrellaDirs[SkippedDirs[I]] = Result;
       }
       
-      Headers[File] = Result;
+      Headers[File] = KnownHeader(Result, /*Excluded=*/false);
 
       // If a header corresponds to an unavailable module, don't report
       // that it maps to anything.
@@ -243,10 +241,9 @@
 }
 
 bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
-  llvm::DenseMap<const FileEntry *, Module *>::iterator Known
-    = Headers.find(Header);
+  HeadersMap::iterator Known = Headers.find(Header);
   if (Known != Headers.end())
-    return !Known->second->isAvailable();
+    return !Known->second.isAvailable();
   
   const DirectoryEntry *Dir = Header->getDir();
   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
@@ -381,7 +378,7 @@
   
   // umbrella header "umbrella-header-name"
   Result->Umbrella = UmbrellaHeader;
-  Headers[UmbrellaHeader] = Result;
+  Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
   
   // export *
@@ -447,7 +444,7 @@
 }
 
 void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
-  Headers[UmbrellaHeader] = Mod;
+  Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
   Mod->Umbrella = UmbrellaHeader;
   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
 }
@@ -457,9 +454,13 @@
   UmbrellaDirs[UmbrellaDir] = Mod;
 }
 
-void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
-  Mod->Headers.push_back(Header);
-  Headers[Header] = Mod;
+void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
+                          bool Excluded) {
+  if (Excluded)
+    Mod->ExcludedHeaders.push_back(Header);
+  else
+    Mod->Headers.push_back(Header);
+  Headers[Header] = KnownHeader(Mod, Excluded);
 }
 
 const FileEntry *
@@ -479,12 +480,10 @@
     M->getValue()->print(llvm::errs(), 2);
   
   llvm::errs() << "Headers:";
-  for (llvm::DenseMap<const FileEntry *, Module *>::iterator 
-            H = Headers.begin(),
-         HEnd = Headers.end();
+  for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
        H != HEnd; ++H) {
     llvm::errs() << "  \"" << H->first->getName() << "\" -> " 
-                 << H->second->getFullModuleName() << "\n";
+                 << H->second.getModule()->getFullModuleName() << "\n";
   }
 }
 
@@ -545,6 +544,7 @@
       EndOfFile,
       HeaderKeyword,
       Identifier,
+      ExcludeKeyword,
       ExplicitKeyword,
       ExportKeyword,
       FrameworkKeyword,
@@ -623,7 +623,7 @@
     bool parseModuleId(ModuleId &Id);
     void parseModuleDecl();
     void parseRequiresDecl();
-    void parseHeaderDecl(SourceLocation UmbrellaLoc);
+    void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
     void parseExportDecl();
     void parseInferredSubmoduleDecl(bool Explicit);
@@ -666,6 +666,7 @@
     Tok.StringLength = LToken.getLength();
     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
                  .Case("header", MMToken::HeaderKeyword)
+                 .Case("exclude", MMToken::ExcludeKeyword)
                  .Case("explicit", MMToken::ExplicitKeyword)
                  .Case("export", MMToken::ExportKeyword)
                  .Case("framework", MMToken::FrameworkKeyword)
@@ -1044,14 +1045,25 @@
     case MMToken::UmbrellaKeyword: {
       SourceLocation UmbrellaLoc = consumeToken();
       if (Tok.is(MMToken::HeaderKeyword))
-        parseHeaderDecl(UmbrellaLoc);
+        parseHeaderDecl(UmbrellaLoc, SourceLocation());
       else
         parseUmbrellaDirDecl(UmbrellaLoc);
       break;
     }
         
+    case MMToken::ExcludeKeyword: {
+      SourceLocation ExcludeLoc = consumeToken();
+      if (Tok.is(MMToken::HeaderKeyword)) {
+        parseHeaderDecl(SourceLocation(), ExcludeLoc);
+      } else {
+        Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+          << "exclude";
+      }
+      break;
+    }
+      
     case MMToken::HeaderKeyword:
-      parseHeaderDecl(SourceLocation());
+      parseHeaderDecl(SourceLocation(), SourceLocation());
       break;
         
     default:
@@ -1153,12 +1165,15 @@
 ///
 ///   header-declaration:
 ///     'umbrella'[opt] 'header' string-literal
-void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
+///     'exclude'[opt] 'header' string-literal
+void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
+                                      SourceLocation ExcludeLoc) {
   assert(Tok.is(MMToken::HeaderKeyword));
   consumeToken();
 
   bool Umbrella = UmbrellaLoc.isValid();
-  
+  bool Exclude = ExcludeLoc.isValid();
+  assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
   // Parse the header name.
   if (!Tok.is(MMToken::StringLiteral)) {
     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 
@@ -1236,15 +1251,15 @@
   // 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 (const Module *OwningModule = Map.Headers[File]) {
+    if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
-        << FileName << OwningModule->getFullModuleName();
+        << FileName << OwningModule.getModule()->getFullModuleName();
       HadError = true;
     } else if (Umbrella) {
       const DirectoryEntry *UmbrellaDir = File->getDir();
-      if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
+      if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
-          << OwningModule->getFullModuleName();
+          << UmbrellaModule->getFullModuleName();
         HadError = true;
       } else {
         // Record this umbrella header.
@@ -1252,11 +1267,11 @@
       }
     } else {
       // Record this header.
-      Map.addHeader(ActiveModule, File);
+      Map.addHeader(ActiveModule, File, Exclude);
       
       // If there is a builtin counterpart to this file, add it now.
       if (BuiltinFile)
-        Map.addHeader(ActiveModule, BuiltinFile);
+        Map.addHeader(ActiveModule, BuiltinFile, Exclude);
     }
   } else {
     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
@@ -1489,6 +1504,7 @@
       break;
       
     case MMToken::Comma:
+    case MMToken::ExcludeKeyword:
     case MMToken::ExportKeyword:
     case MMToken::HeaderKeyword:
     case MMToken::Identifier:

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Oct 15 01:28:11 2012
@@ -3322,7 +3322,27 @@
         if (std::find(CurrentModule->Headers.begin(), 
                       CurrentModule->Headers.end(), 
                       File) == CurrentModule->Headers.end())
-          ModMap.addHeader(CurrentModule, File);
+          ModMap.addHeader(CurrentModule, File, false);
+      }
+      break;      
+    }
+
+    case SUBMODULE_EXCLUDED_HEADER: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return Failure;
+      }
+
+      if (!CurrentModule)
+        break;
+      
+      // FIXME: Be more lazy about this!
+      StringRef FileName(BlobStart, BlobLen);
+      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+        if (std::find(CurrentModule->Headers.begin(), 
+                      CurrentModule->Headers.end(), 
+                      File) == CurrentModule->Headers.end())
+          ModMap.addHeader(CurrentModule, File, true);
       }
       break;      
     }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Oct 15 01:28:11 2012
@@ -1983,6 +1983,11 @@
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
   unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev);
 
+  Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+  unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
   // Write the submodule metadata block.
   RecordData Record;
   Record.push_back(getNumberOfModules(WritingModule));
@@ -2044,6 +2049,13 @@
       Stream.EmitRecordWithBlob(HeaderAbbrev, Record, 
                                 Mod->Headers[I]->getName());
     }
+    // Emit the excluded headers.
+    for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
+      Record.clear();
+      Record.push_back(SUBMODULE_EXCLUDED_HEADER);
+      Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record, 
+                                Mod->ExcludedHeaders[I]->getName());
+    }
     for (unsigned I = 0, N = Mod->TopHeaders.size(); I != N; ++I) {
       Record.clear();
       Record.push_back(SUBMODULE_TOPHEADER);

Modified: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map Mon Oct 15 01:28:11 2012
@@ -2,8 +2,5 @@
   umbrella "Headers"
   module * { }
 
-  module unavailable {
-    requires unavailable
-    header "Boom.h"
-  }
+  exclude header "Boom.h"
 }





More information about the cfe-commits mailing list