r190497 - Support for modular module-map-files

Daniel Jasper djasper at google.com
Wed Sep 11 00:20:44 PDT 2013


Author: djasper
Date: Wed Sep 11 02:20:44 2013
New Revision: 190497

URL: http://llvm.org/viewvc/llvm-project?rev=190497&view=rev
Log:
Support for modular module-map-files

This patch is the first step to make module-map-files modular (instead
of requiring a single "module.map"-file per include directory). This
step adds a new "extern module" declaration that enables
module-map-files to reference one another along with a very basic
implementation.

The next steps are:

* Combine this with the use-declaration (from
  http://llvm-reviews.chandlerc.com/D1546) in order to only load module
  map files required for a specific compilation.
* Add an additional flag to start with a specific module-map-file (instead
  of requiring there to be at least one "module.map").

Review: http://llvm-reviews.chandlerc.com/D1637

Added:
    cfe/trunk/test/Modules/Inputs/modular_maps/
    cfe/trunk/test/Modules/Inputs/modular_maps/a.h
    cfe/trunk/test/Modules/Inputs/modular_maps/b.h
    cfe/trunk/test/Modules/Inputs/modular_maps/module.map
    cfe/trunk/test/Modules/Inputs/modular_maps/moduleb.map
    cfe/trunk/test/Modules/modular_maps.cpp
Modified:
    cfe/trunk/docs/Modules.rst
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/lib/Lex/ModuleMap.cpp

Modified: cfe/trunk/docs/Modules.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=190497&r1=190496&r2=190497&view=diff
==============================================================================
--- cfe/trunk/docs/Modules.rst (original)
+++ cfe/trunk/docs/Modules.rst Wed Sep 11 02:20:44 2013
@@ -238,6 +238,7 @@ Module map files use a simplified form o
   ``conflict``      ``framework``  ``requires``
   ``exclude``       ``header``     ``private``
   ``explicit``      ``link``       ``umbrella``
+  ``extern``
 
 Module map file
 ---------------
@@ -263,6 +264,7 @@ A module declaration describes a module,
 
   *module-declaration*:
     ``explicit``:sub:`opt` ``framework``:sub:`opt` ``module`` *module-id* *attributes*:sub:`opt` '{' *module-member** '}'
+    ``extern`` ``module`` *module-id* *string-literal*
 
 The *module-id* should consist of only a single *identifier*, which provides the name of the module being defined. Each module shall have a single definition. 
 
@@ -295,6 +297,8 @@ Modules can have a number of different k
     *config-macros-declaration*
     *conflict-declaration*
 
+An extern module references a module defined by the *module-id* in a file given by the *string-literal*. The file can be referenced either by an absolute path or by a path relative to the current map file.
+
 Requires declaration
 ~~~~~~~~~~~~~~~~~~~~
 A *requires-declaration* specifies the requirements that an importing translation unit must satisfy to use the module.

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=190497&r1=190496&r2=190497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Wed Sep 11 02:20:44 2013
@@ -527,6 +527,7 @@ def note_mmap_lsquare_match : Note<"to m
 def err_mmap_expected_member : Error<
   "expected umbrella, header, submodule, or module export">;
 def err_mmap_expected_header : Error<"expected a header name after '%0'">;
+def err_mmap_expected_mmap_file : Error<"expected a module map file name">;
 def err_mmap_module_redefinition : Error<
   "redefinition of module '%0'">;
 def note_mmap_prev_definition : Note<"previously defined here">;

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=190497&r1=190496&r2=190497&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Wed Sep 11 02:20:44 2013
@@ -722,6 +722,7 @@ namespace clang {
       ExcludeKeyword,
       ExplicitKeyword,
       ExportKeyword,
+      ExternKeyword,
       FrameworkKeyword,
       LinkKeyword,
       ModuleKeyword,
@@ -814,6 +815,7 @@ namespace clang {
     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
     bool parseModuleId(ModuleId &Id);
     void parseModuleDecl();
+    void parseExternModuleDecl();
     void parseRequiresDecl();
     void parseHeaderDecl(clang::MMToken::TokenKind,
                          SourceLocation LeadingLoc);
@@ -865,6 +867,7 @@ retry:
                  .Case("exclude", MMToken::ExcludeKeyword)
                  .Case("explicit", MMToken::ExplicitKeyword)
                  .Case("export", MMToken::ExportKeyword)
+                 .Case("extern", MMToken::ExternKeyword)
                  .Case("framework", MMToken::FrameworkKeyword)
                  .Case("header", MMToken::HeaderKeyword)
                  .Case("link", MMToken::LinkKeyword)
@@ -1033,6 +1036,7 @@ namespace {
 /// \brief Parse a module declaration.
 ///
 ///   module-declaration:
+///     'extern' 'module' module-id string-literal
 ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 
 ///       { module-member* }
 ///
@@ -1048,7 +1052,12 @@ namespace {
 ///     inferred-submodule-declaration
 void ModuleMapParser::parseModuleDecl() {
   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
-         Tok.is(MMToken::FrameworkKeyword));
+         Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
+  if (Tok.is(MMToken::ExternKeyword)) {
+    parseExternModuleDecl();
+    return;
+  }
+
   // Parse 'explicit' or 'framework' keyword, if present.
   SourceLocation ExplicitLoc;
   bool Explicit = false;
@@ -1193,11 +1202,12 @@ void ModuleMapParser::parseModuleDecl()
       break;
 
     case MMToken::ExplicitKeyword:
+    case MMToken::ExternKeyword:
     case MMToken::FrameworkKeyword:
     case MMToken::ModuleKeyword:
       parseModuleDecl();
       break;
-        
+
     case MMToken::ExportKeyword:
       parseExportDecl();
       break;
@@ -1271,6 +1281,50 @@ void ModuleMapParser::parseModuleDecl()
   ActiveModule = PreviousActiveModule;
 }
 
+/// \brief Parse an extern module declaration.
+///
+///   extern module-declaration:
+///     'extern' 'module' module-id string-literal
+void ModuleMapParser::parseExternModuleDecl() {
+  assert(Tok.is(MMToken::ExternKeyword));
+  consumeToken(); // 'extern' keyword
+
+  // Parse 'module' keyword.
+  if (!Tok.is(MMToken::ModuleKeyword)) {
+    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
+    consumeToken();
+    HadError = true;
+    return;
+  }
+  consumeToken(); // 'module' keyword
+
+  // Parse the module name.
+  ModuleId Id;
+  if (parseModuleId(Id)) {
+    HadError = true;
+    return;
+  }
+
+  // Parse the referenced module map file name.
+  if (!Tok.is(MMToken::StringLiteral)) {
+    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
+    HadError = true;
+    return;
+  }
+  std::string FileName = Tok.getString();
+  consumeToken(); // filename
+
+  StringRef FileNameRef = FileName;
+  SmallString<128> ModuleMapFileName;
+  if (llvm::sys::path::is_relative(FileNameRef)) {
+    ModuleMapFileName += Directory->getName();
+    llvm::sys::path::append(ModuleMapFileName, FileName);
+    FileNameRef = ModuleMapFileName.str();
+  }
+  if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
+    Map.parseModuleMapFile(File, /*IsSystem=*/false);
+}
+
 /// \brief Parse a requires declaration.
 ///
 ///   requires-declaration:
@@ -1925,6 +1979,7 @@ bool ModuleMapParser::parseModuleMapFile
       return HadError;
       
     case MMToken::ExplicitKeyword:
+    case MMToken::ExternKeyword:
     case MMToken::ModuleKeyword:
     case MMToken::FrameworkKeyword:
       parseModuleDecl();

Added: cfe/trunk/test/Modules/Inputs/modular_maps/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/a.h?rev=190497&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/a.h Wed Sep 11 02:20:44 2013
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+const int a = 2;
+#endif

Added: cfe/trunk/test/Modules/Inputs/modular_maps/b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/b.h?rev=190497&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/b.h (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/b.h Wed Sep 11 02:20:44 2013
@@ -0,0 +1,4 @@
+#ifndef B_H
+#define B_H
+const int b = 3;
+#endif

Added: cfe/trunk/test/Modules/Inputs/modular_maps/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/module.map?rev=190497&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/module.map (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/module.map Wed Sep 11 02:20:44 2013
@@ -0,0 +1,6 @@
+module A {
+  header "a.h"
+}
+
+extern module B "moduleb.map"
+

Added: cfe/trunk/test/Modules/Inputs/modular_maps/moduleb.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/moduleb.map?rev=190497&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/moduleb.map (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/moduleb.map Wed Sep 11 02:20:44 2013
@@ -0,0 +1,3 @@
+module B {
+  private header "b.h"
+}

Added: cfe/trunk/test/Modules/modular_maps.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/modular_maps.cpp?rev=190497&view=auto
==============================================================================
--- cfe/trunk/test/Modules/modular_maps.cpp (added)
+++ cfe/trunk/test/Modules/modular_maps.cpp Wed Sep 11 02:20:44 2013
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -I %S/Inputs/modular_maps %s -verify
+
+#include "a.h"
+#include "b.h" // expected-error {{private header}}
+const int val = a + b; // expected-error {{undeclared identifier}}





More information about the cfe-commits mailing list