forked from OSchip/llvm-project
Parse inferred submodules in module maps, track their contents in
Module, and (de-)serialize this information. Semantics of inferred submodules to follow. llvm-svn: 145864
This commit is contained in:
parent
b8c719ccc6
commit
734410916a
|
@ -384,7 +384,7 @@ def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">;
|
|||
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 @@ def err_mmap_missing_module_unqualified : Error<
|
|||
"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 "
|
||||
|
|
|
@ -59,10 +59,24 @@ public:
|
|||
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 @@ public:
|
|||
///\ 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 @@ public:
|
|||
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 @@ public:
|
|||
/// \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.
|
||||
///
|
||||
|
|
|
@ -37,6 +37,14 @@ bool Module::isSubModuleOf(Module *Other) const {
|
|||
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 @@ std::string Module::getFullModuleName() const {
|
|||
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 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
|
|||
}
|
||||
|
||||
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 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
|
|||
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";
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -3049,11 +3049,19 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
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 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
return Failure;
|
||||
}
|
||||
|
||||
CurrentModule->InferSubmodules = InferSubmodules;
|
||||
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
|
||||
CurrentModule->InferExportWildcard = InferExportWildcard;
|
||||
if (DeserializationListener)
|
||||
DeserializationListener->ModuleRead(
|
||||
CurrentModuleGlobalIndex + NUM_PREDEF_SUBMODULE_IDS,
|
||||
|
|
|
@ -1884,6 +1884,9 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
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 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
}
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
framework module DependsOnModule {
|
||||
umbrella "DependsOnModule.h"
|
||||
header "other.h"
|
||||
module * {
|
||||
export *
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue