aboutsummaryrefslogtreecommitdiff
path: root/lib/Lex/ModuleMap.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-12-05 22:27:44 +0000
committerDouglas Gregor <dgregor@apple.com>2011-12-05 22:27:44 +0000
commit1e12368db12005ddd92fd9188c86383fe30ef443 (patch)
tree8715bebf398d98fa142c8ac7b80c642b1eb56615 /lib/Lex/ModuleMap.cpp
parentbd7d82878c1588afccbee6c68fa6e17bbbab7f2c (diff)
Parse inferred submodules in module maps, track their contents in
Module, and (de-)serialize this information. Semantics of inferred submodules to follow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145864 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r--lib/Lex/ModuleMap.cpp104
1 files changed, 103 insertions, 1 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 6d227d003e..164eb27e72 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -351,6 +351,7 @@ namespace clang {
void parseUmbrellaDecl();
void parseHeaderDecl();
void parseExportDecl();
+ void parseInferredSubmoduleDecl(bool Explicit);
public:
explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
@@ -485,8 +486,12 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
/// 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 @@ void ModuleMapParser::parseModuleDecl() {
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 @@ void ModuleMapParser::parseExportDecl() {
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: