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}} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
