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

Douglas Gregor dgregor at apple.com
Mon Dec 5 14:27:44 PST 2011


Author: dgregor
Date: Mon Dec  5 16:27:44 2011
New Revision: 145864

URL: http://llvm.org/viewvc/llvm-project?rev=145864&view=rev
Log:
Parse inferred submodules in module maps, track their contents in
Module, and (de-)serialize this information. Semantics of inferred
submodules to follow.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/include/clang/Basic/Module.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/DependsOnModule.framework/module.map

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Mon Dec  5 16:27:44 2011
@@ -384,7 +384,7 @@
 def err_mmap_expected_rbrace : Error<"expected '}'">;
 def note_mmap_lbrace_match : Note<"to match this '{'">;
 def err_mmap_expected_member : Error<
-  "expected umbrella header, header, or submodule">;
+  "expected umbrella header, header, submodule, or module export">;
 def err_mmap_expected_header : Error<"expected a header name after '%0'">;
 def err_mmap_module_redefinition : Error<
   "redefinition of module '%0'">;
@@ -405,6 +405,18 @@
   "no module named '%0' visible from '%1'">;
 def err_mmap_missing_module_qualified : Error<
   "no module named '%0' in '%1'">;
+def err_mmap_top_level_inferred_submodule : Error<
+  "only submodules may be inferred with wildcard syntax">;
+def err_mmap_inferred_no_umbrella : Error<
+  "inferred submodules require a module with an umbrella header">;
+def err_mmap_inferred_redef : Error<
+  "redefinition of inferred submodule">;
+def err_mmap_expected_lbrace_wildcard : Error<
+  "expected '{' to start inferred submodule">;
+def err_mmap_expected_wildcard_member : Error<
+  "expected module export wildcard">;
+def err_mmap_expected_export_wildcard : Error<
+  "only '*' can be exported from an inferred submodule">;
 
 def warn_auto_module_import : Warning<
   "treating #%select{include|import|include_next|__include_macros}0 as an "

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Mon Dec  5 16:27:44 2011
@@ -59,10 +59,24 @@
   llvm::SmallVector<const FileEntry *, 2> Headers;
   
   /// \brief Whether this is a framework module.
-  bool IsFramework;
+  unsigned IsFramework : 1;
   
   /// \brief Whether this is an explicit submodule.
-  bool IsExplicit;
+  unsigned IsExplicit : 1;
+  
+  /// \brief Whether we should infer submodules for this module based on 
+  /// the headers.
+  ///
+  /// Submodules can only be inferred for modules with an umbrella header.
+  unsigned InferSubmodules : 1;
+  
+  /// \brief Whether, when inferring submodules, the inferred submodules
+  /// should be explicit.
+  unsigned InferExplicitSubmodules : 1;
+  
+  /// \brief Whether, when inferring submodules, the inferr submodules should
+  /// export all modules they import (e.g., the equivalent of "export *").
+  unsigned InferExportWildcard : 1;
   
   /// \brief Describes the visibility of the various names within a
   /// particular module.
@@ -79,6 +93,9 @@
   ///\ brief The visibility of names within this particular module.
   NameVisibilityKind NameVisibility;
 
+  /// \brief The location of the inferred submodule.
+  SourceLocation InferredSubmoduleLoc;
+
   /// \brief The set of modules imported by this module, and on which this
   /// module depends.
   llvm::SmallVector<Module *, 2> Imports;
@@ -114,14 +131,17 @@
   explicit Module(StringRef Name, SourceLocation DefinitionLoc,
                   bool IsFramework)
     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0),
-      IsFramework(IsFramework), IsExplicit(false), NameVisibility(Hidden) { }
+      IsFramework(IsFramework), IsExplicit(false), InferSubmodules(false),
+      InferExplicitSubmodules(false), InferExportWildcard(false),
+      NameVisibility(Hidden) { }
   
   /// \brief Construct  a new module or submodule.
   Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, 
          bool IsFramework, bool IsExplicit)
     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), 
       UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit), 
-      NameVisibility(Hidden) { }
+      InferSubmodules(false), InferExplicitSubmodules(false), 
+      InferExportWildcard(false),NameVisibility(Hidden) { }
   
   ~Module();
   
@@ -146,10 +166,23 @@
   /// \brief Retrieve the full name of this module, including the path from
   /// its top-level module.
   std::string getFullModuleName() const;
+
+  /// \brief Retrieve the top-level module for this (sub)module, which may
+  /// be this module.
+  Module *getTopLevelModule() {
+    return const_cast<Module *>(
+             const_cast<const Module *>(this)->getTopLevelModule());
+  }
+
+  /// \brief Retrieve the top-level module for this (sub)module, which may
+  /// be this module.
+  const Module *getTopLevelModule() const;
   
   /// \brief Retrieve the name of the top-level module.
   ///
-  StringRef getTopLevelModuleName() const;
+  StringRef getTopLevelModuleName() const {
+    return getTopLevelModule()->Name;
+  }
   
   /// \brief Print the module map for this module to the given stream. 
   ///

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Mon Dec  5 16:27:44 2011
@@ -37,6 +37,14 @@
   return false;
 }
 
+const Module *Module::getTopLevelModule() const {
+  const Module *Result = this;
+  while (Result->Parent)
+    Result = Result->Parent;
+  
+  return Result;
+}
+
 std::string Module::getFullModuleName() const {
   llvm::SmallVector<StringRef, 2> Names;
   
@@ -57,14 +65,6 @@
   return Result;
 }
 
-StringRef Module::getTopLevelModuleName() const {
-  const Module *Top = this;
-  while (Top->Parent)
-    Top = Top->Parent;
-  
-  return Top->Name;
-}
-
 static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
     if (I)
@@ -96,7 +96,7 @@
   }
   
   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(), 
-       MIEnd = SubModules.end();
+                                              MIEnd = SubModules.end();
        MI != MIEnd; ++MI)
     MI->getValue()->print(OS, Indent + 2);
   
@@ -126,6 +126,19 @@
     OS << "\n";
   }
 
+  if (InferSubmodules) {
+    OS.indent(Indent + 2);
+    if (InferExplicitSubmodules)
+      OS << "explicit ";
+    OS << "module * {\n";
+    if (InferExportWildcard) {
+      OS.indent(Indent + 4);
+      OS << "export *\n";
+    }
+    OS.indent(Indent + 2);
+    OS << "}\n";
+  }
+  
   OS.indent(Indent);
   OS << "}\n";
 }

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Dec  5 16:27:44 2011
@@ -351,6 +351,7 @@
     void parseUmbrellaDecl();
     void parseHeaderDecl();
     void parseExportDecl();
+    void parseInferredSubmoduleDecl(bool Explicit);
     
   public:
     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 
@@ -485,8 +486,12 @@
 ///   module-member:
 ///     umbrella-declaration
 ///     header-declaration
-///     'explicit'[opt] module-declaration
+///     'explicit'[opt] submodule-declaration
 ///     export-declaration
+///
+///   submodule-declaration:
+///     module-declaration
+///     inferred-submodule-declaration
 void ModuleMapParser::parseModuleDecl() {
   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
          Tok.is(MMToken::FrameworkKeyword));
@@ -514,6 +519,11 @@
     return;
   }
   consumeToken(); // 'module' keyword
+
+  // If we have a wildcard for the module name, this is an inferred submodule.
+  // Parse it. 
+  if (Tok.is(MMToken::Star))
+    return parseInferredSubmoduleDecl(Explicit);
   
   // Parse the module name.
   if (!Tok.is(MMToken::Identifier)) {
@@ -790,6 +800,98 @@
   ActiveModule->UnresolvedExports.push_back(Unresolved);
 }
 
+void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
+  assert(Tok.is(MMToken::Star));
+  SourceLocation StarLoc = consumeToken();
+  bool Failed = false;
+  
+  // Inferred modules must be submodules.
+  if (!ActiveModule) {
+    Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
+    Failed = true;
+  }
+  
+  // Inferred modules must have umbrella headers.
+  if (!Failed && !ActiveModule->getTopLevelModule()->UmbrellaHeader) {
+    Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
+    Failed = true;
+  }
+  
+  // Check for redefinition of an inferred module.
+  if (!Failed && ActiveModule->getTopLevelModule()->InferSubmodules) {
+    Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
+    if (ActiveModule->getTopLevelModule()->InferredSubmoduleLoc.isValid())
+      Diags.Report(ActiveModule->getTopLevelModule()->InferredSubmoduleLoc,
+                   diag::note_mmap_prev_definition);
+    Failed = true;
+  }
+  
+  // If there were any problems with this inferred submodule, skip its body.
+  if (Failed) {
+    if (Tok.is(MMToken::LBrace)) {
+      consumeToken();
+      skipUntil(MMToken::RBrace);
+      if (Tok.is(MMToken::RBrace))
+        consumeToken();
+    }
+    HadError = true;
+    return;
+  }
+  
+  // Note that we have an inferred submodule.
+  Module *TopModule = ActiveModule->getTopLevelModule();
+  TopModule->InferSubmodules = true;
+  TopModule->InferredSubmoduleLoc = StarLoc;
+  TopModule->InferExplicitSubmodules = Explicit;
+  
+  // Parse the opening brace.
+  if (!Tok.is(MMToken::LBrace)) {
+    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
+    HadError = true;
+    return;
+  }  
+  SourceLocation LBraceLoc = consumeToken();
+
+  // Parse the body of the inferred submodule.
+  bool Done = false;
+  do {
+    switch (Tok.Kind) {
+    case MMToken::EndOfFile:
+    case MMToken::RBrace:
+      Done = true;
+      break;
+      
+    case MMToken::ExportKeyword: {
+      consumeToken();
+      if (Tok.is(MMToken::Star)) 
+        TopModule->InferExportWildcard = true;
+      else
+        Diags.Report(Tok.getLocation(), 
+                     diag::err_mmap_expected_export_wildcard);
+      consumeToken();
+      break;
+    }
+      
+    case MMToken::ExplicitKeyword:
+    case MMToken::ModuleKeyword:
+    case MMToken::HeaderKeyword:
+    case MMToken::UmbrellaKeyword:
+    default:
+      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
+      consumeToken();
+      break;        
+    }
+  } while (!Done);
+  
+  if (Tok.is(MMToken::RBrace))
+    consumeToken();
+  else {
+    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
+    Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
+    HadError = true;
+  }
+}
+
 /// \brief Parse a module map file.
 ///
 ///   module-map-file:

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Dec  5 16:27:44 2011
@@ -3049,11 +3049,19 @@
         return Failure;
       }
 
+      if (Record.size() < 6) {
+        Error("malformed module definition");
+        return Failure;
+      }
+      
       StringRef Name(BlobStart, BlobLen);
       unsigned Parent = getGlobalSubmoduleID(F, Record[0]);
       bool IsFramework = Record[1];
       bool IsExplicit = Record[2];
-
+      bool InferSubmodules = Record[3];
+      bool InferExplicitSubmodules = Record[4];
+      bool InferExportWildcard = Record[5];
+      
       Module *ParentModule = 0;
       if (Parent)
         ParentModule = getSubmodule(Parent);
@@ -3070,6 +3078,9 @@
         return Failure;
       }
       
+      CurrentModule->InferSubmodules = InferSubmodules;
+      CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
+      CurrentModule->InferExportWildcard = InferExportWildcard;
       if (DeserializationListener)
         DeserializationListener->ModuleRead(
           CurrentModuleGlobalIndex + NUM_PREDEF_SUBMODULE_IDS, 

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Dec  5 16:27:44 2011
@@ -1884,6 +1884,9 @@
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
   unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev);
 
@@ -1923,6 +1926,9 @@
     }
     Record.push_back(Mod->IsFramework);
     Record.push_back(Mod->IsExplicit);
+    Record.push_back(Mod->InferSubmodules);
+    Record.push_back(Mod->InferExplicitSubmodules);
+    Record.push_back(Mod->InferExportWildcard);
     Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
     
     // Emit the umbrella header, if there is one.

Modified: cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map?rev=145864&r1=145863&r2=145864&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map Mon Dec  5 16:27:44 2011
@@ -1,4 +1,7 @@
 framework module DependsOnModule {
   umbrella "DependsOnModule.h"
   header "other.h"
+  module * {
+    export *
+  }
 }





More information about the cfe-commits mailing list