[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