forked from OSchip/llvm-project
<rdar://problem/12368093> Extend module maps with a 'conflict' declaration, and warn when a newly-imported module conflicts with an already-imported module.
llvm-svn: 177577
This commit is contained in:
parent
f83a664a40
commit
fb9126578e
|
@ -159,6 +159,7 @@ def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
|
|||
def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
|
||||
def MismatchedTags : DiagGroup<"mismatched-tags">;
|
||||
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
|
||||
def ModuleConflict : DiagGroup<"module-conflict">;
|
||||
def NullArithmetic : DiagGroup<"null-arithmetic">;
|
||||
def NullCharacter : DiagGroup<"null-character">;
|
||||
def NullDereference : DiagGroup<"null-dereference">;
|
||||
|
|
|
@ -536,6 +536,10 @@ def err_mmap_config_macro_submodule : Error<
|
|||
"configuration macros are only allowed on top-level modules">;
|
||||
def err_mmap_expected_config_macro : Error<
|
||||
"expected configuration macro name after ','">;
|
||||
def err_mmap_expected_conflicts_comma : Error<
|
||||
"expected ',' after conflicting module name">;
|
||||
def err_mmap_expected_conflicts_message : Error<
|
||||
"expected a message describing the conflict with '%0'">;
|
||||
def err_mmap_missing_module_unqualified : Error<
|
||||
"no module named '%0' visible from '%1'">;
|
||||
def err_mmap_missing_module_qualified : Error<
|
||||
|
|
|
@ -44,7 +44,10 @@ def warn_pch_different_branch : Error<
|
|||
def err_pch_with_compiler_errors : Error<
|
||||
"PCH file contains compiler errors">;
|
||||
|
||||
|
||||
def warn_module_conflict : Warning<
|
||||
"module '%0' conflicts with already-imported module '%1': %2">,
|
||||
InGroup<ModuleConflict>;
|
||||
|
||||
def err_pch_macro_def_undef : Error<
|
||||
"macro '%0' was %select{defined|undef'd}1 in the precompiled header but "
|
||||
"%select{undef'd|defined}1 on the command line">;
|
||||
|
|
|
@ -201,6 +201,31 @@ public:
|
|||
/// (intentionally) change how this module is built.
|
||||
std::vector<std::string> ConfigMacros;
|
||||
|
||||
/// \brief An unresolved conflict with another module.
|
||||
struct UnresolvedConflict {
|
||||
/// \brief The (unresolved) module id.
|
||||
ModuleId Id;
|
||||
|
||||
/// \brief The message provided to the user when there is a conflict.
|
||||
std::string Message;
|
||||
};
|
||||
|
||||
/// \brief The list of conflicts for which the module-id has not yet been
|
||||
/// resolved.
|
||||
std::vector<UnresolvedConflict> UnresolvedConflicts;
|
||||
|
||||
/// \brief A conflict between two modules.
|
||||
struct Conflict {
|
||||
/// \brief The module that this module conflicts with.
|
||||
Module *Other;
|
||||
|
||||
/// \brief The message provided to the user when there is a conflict.
|
||||
std::string Message;
|
||||
};
|
||||
|
||||
/// \brief The list of conflicts.
|
||||
std::vector<Conflict> Conflicts;
|
||||
|
||||
/// \brief Construct a top-level module.
|
||||
explicit Module(StringRef Name, SourceLocation DefinitionLoc,
|
||||
bool IsFramework)
|
||||
|
|
|
@ -843,7 +843,8 @@ public:
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) { }
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) { }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -663,7 +663,8 @@ public:
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc);
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ public:
|
|||
/// \brief Make the given module visible.
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) = 0;
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -134,7 +134,20 @@ class ModuleMap {
|
|||
Module::ExportDecl
|
||||
resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved,
|
||||
bool Complain) const;
|
||||
|
||||
|
||||
/// \brief Resolve the given module id to an actual module.
|
||||
///
|
||||
/// \param Id The module-id to resolve.
|
||||
///
|
||||
/// \param Mod The module in which we're resolving the module-id.
|
||||
///
|
||||
/// \param Complain Whether this routine should complain about unresolvable
|
||||
/// module-ids.
|
||||
///
|
||||
/// \returns The resolved module, or null if the module-id could not be
|
||||
/// resolved.
|
||||
Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
|
||||
|
||||
public:
|
||||
/// \brief Construct a new module map.
|
||||
///
|
||||
|
@ -265,7 +278,17 @@ public:
|
|||
/// false otherwise.
|
||||
bool resolveExports(Module *Mod, bool Complain);
|
||||
|
||||
/// \brief Infers the (sub)module based on the given source location and
|
||||
/// \brief Resolve all of the unresolved conflicts in the given module.
|
||||
///
|
||||
/// \param Mod The module whose conflicts should be resolved.
|
||||
///
|
||||
/// \param Complain Whether to emit diagnostics for failures.
|
||||
///
|
||||
/// \returns true if any errors were encountered while resolving conflicts,
|
||||
/// false otherwise.
|
||||
bool resolveConflicts(Module *Mod, bool Complain);
|
||||
|
||||
/// \brief Infers the (sub)module based on the given source location and
|
||||
/// source manager.
|
||||
///
|
||||
/// \param Loc The location within the source that we are querying, along
|
||||
|
|
|
@ -611,7 +611,9 @@ namespace clang {
|
|||
/// \brief Specifies a library or framework to link against.
|
||||
SUBMODULE_LINK_LIBRARY = 10,
|
||||
/// \brief Specifies a configuration macro for this module.
|
||||
SUBMODULE_CONFIG_MACRO = 11
|
||||
SUBMODULE_CONFIG_MACRO = 11,
|
||||
/// \brief Specifies a conflict with another module.
|
||||
SUBMODULE_CONFLICT = 12
|
||||
};
|
||||
|
||||
/// \brief Record types used within a comments block.
|
||||
|
|
|
@ -520,27 +520,30 @@ private:
|
|||
HiddenNamesMapType HiddenNamesMap;
|
||||
|
||||
|
||||
/// \brief A module import or export that hasn't yet been resolved.
|
||||
struct UnresolvedModuleImportExport {
|
||||
/// \brief A module import, export, or conflict that hasn't yet been resolved.
|
||||
struct UnresolvedModuleRef {
|
||||
/// \brief The file in which this module resides.
|
||||
ModuleFile *File;
|
||||
|
||||
/// \brief The module that is importing or exporting.
|
||||
Module *Mod;
|
||||
|
||||
|
||||
/// \brief The kind of module reference.
|
||||
enum { Import, Export, Conflict } Kind;
|
||||
|
||||
/// \brief The local ID of the module that is being exported.
|
||||
unsigned ID;
|
||||
|
||||
/// \brief Whether this is an import (vs. an export).
|
||||
unsigned IsImport : 1;
|
||||
|
||||
|
||||
/// \brief Whether this is a wildcard export.
|
||||
unsigned IsWildcard : 1;
|
||||
|
||||
/// \brief String data.
|
||||
StringRef String;
|
||||
};
|
||||
|
||||
/// \brief The set of module imports and exports that still need to be
|
||||
/// resolved.
|
||||
SmallVector<UnresolvedModuleImportExport, 2> UnresolvedModuleImportExports;
|
||||
SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs;
|
||||
|
||||
/// \brief A vector containing selectors that have already been loaded.
|
||||
///
|
||||
|
@ -1188,9 +1191,14 @@ public:
|
|||
///
|
||||
/// \param NameVisibility The level of visibility to give the names in the
|
||||
/// module. Visibility can only be increased over time.
|
||||
///
|
||||
/// \param ImportLoc The location at which the import occurs.
|
||||
///
|
||||
/// \param Complain Whether to complain about conflicting module imports.
|
||||
void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind NameVisibility,
|
||||
SourceLocation ImportLoc);
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain);
|
||||
|
||||
/// \brief Make the names within this set of hidden names visible.
|
||||
void makeNamesVisible(const HiddenNames &Names);
|
||||
|
|
|
@ -347,6 +347,24 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
|
|||
OS << "\"";
|
||||
}
|
||||
|
||||
for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {
|
||||
OS.indent(Indent + 2);
|
||||
OS << "conflict ";
|
||||
printModuleId(OS, UnresolvedConflicts[I].Id);
|
||||
OS << ", \"";
|
||||
OS.write_escaped(UnresolvedConflicts[I].Message);
|
||||
OS << "\"\n";
|
||||
}
|
||||
|
||||
for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
|
||||
OS.indent(Indent + 2);
|
||||
OS << "conflict ";
|
||||
OS << Conflicts[I].Other->getFullModuleName();
|
||||
OS << ", \"";
|
||||
OS.write_escaped(Conflicts[I].Message);
|
||||
OS << "\"\n";
|
||||
}
|
||||
|
||||
if (InferSubmodules) {
|
||||
OS.indent(Indent + 2);
|
||||
if (InferExplicitSubmodules)
|
||||
|
|
|
@ -1007,7 +1007,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
// Make the named module visible.
|
||||
if (LastModuleImportResult)
|
||||
ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
|
||||
ImportLoc);
|
||||
ImportLoc, /*Complain=*/false);
|
||||
return LastModuleImportResult;
|
||||
}
|
||||
|
||||
|
@ -1265,7 +1265,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
return ModuleLoadResult();
|
||||
}
|
||||
|
||||
ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
|
||||
ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc,
|
||||
/*Complain=*/true);
|
||||
}
|
||||
|
||||
// Check for any configuration macros that have changed.
|
||||
|
@ -1294,7 +1295,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
|
||||
void CompilerInstance::makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc){
|
||||
ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc);
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain){
|
||||
ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,35 +45,42 @@ ModuleMap::resolveExport(Module *Mod,
|
|||
return Module::ExportDecl(0, true);
|
||||
}
|
||||
|
||||
// Resolve the module-id.
|
||||
Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
|
||||
if (!Context)
|
||||
return Module::ExportDecl();
|
||||
|
||||
return Module::ExportDecl(Context, Unresolved.Wildcard);
|
||||
}
|
||||
|
||||
Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
|
||||
bool Complain) const {
|
||||
// Find the starting module.
|
||||
Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
|
||||
Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
|
||||
if (!Context) {
|
||||
if (Complain)
|
||||
Diags->Report(Unresolved.Id[0].second,
|
||||
diag::err_mmap_missing_module_unqualified)
|
||||
<< Unresolved.Id[0].first << Mod->getFullModuleName();
|
||||
|
||||
return Module::ExportDecl();
|
||||
Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
|
||||
<< Id[0].first << Mod->getFullModuleName();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dig into the module path.
|
||||
for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
|
||||
Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
|
||||
Context);
|
||||
for (unsigned I = 1, N = Id.size(); I != N; ++I) {
|
||||
Module *Sub = lookupModuleQualified(Id[I].first, Context);
|
||||
if (!Sub) {
|
||||
if (Complain)
|
||||
Diags->Report(Unresolved.Id[I].second,
|
||||
diag::err_mmap_missing_module_qualified)
|
||||
<< Unresolved.Id[I].first << Context->getFullModuleName()
|
||||
<< SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
|
||||
|
||||
return Module::ExportDecl();
|
||||
Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified)
|
||||
<< Id[I].first << Context->getFullModuleName()
|
||||
<< SourceRange(Id[0].second, Id[I-1].second);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Context = Sub;
|
||||
}
|
||||
|
||||
return Module::ExportDecl(Context, Unresolved.Wildcard);
|
||||
|
||||
return Context;
|
||||
}
|
||||
|
||||
ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
|
||||
|
@ -603,6 +610,25 @@ bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
|
|||
return HadError;
|
||||
}
|
||||
|
||||
bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
|
||||
bool HadError = false;
|
||||
for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
|
||||
Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
|
||||
Mod, Complain);
|
||||
if (!OtherMod) {
|
||||
HadError = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Module::Conflict Conflict;
|
||||
Conflict.Other = OtherMod;
|
||||
Conflict.Message = Mod->UnresolvedConflicts[I].Message;
|
||||
Mod->Conflicts.push_back(Conflict);
|
||||
}
|
||||
Mod->UnresolvedConflicts.clear();
|
||||
return HadError;
|
||||
}
|
||||
|
||||
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
|
||||
if (Loc.isInvalid())
|
||||
return 0;
|
||||
|
@ -644,6 +670,7 @@ namespace clang {
|
|||
enum TokenKind {
|
||||
Comma,
|
||||
ConfigMacros,
|
||||
Conflict,
|
||||
EndOfFile,
|
||||
HeaderKeyword,
|
||||
Identifier,
|
||||
|
@ -744,6 +771,7 @@ namespace clang {
|
|||
void parseExportDecl();
|
||||
void parseLinkDecl();
|
||||
void parseConfigMacros();
|
||||
void parseConflict();
|
||||
void parseInferredModuleDecl(bool Framework, bool Explicit);
|
||||
bool parseOptionalAttributes(Attributes &Attrs);
|
||||
|
||||
|
@ -782,6 +810,7 @@ retry:
|
|||
Tok.StringLength = LToken.getLength();
|
||||
Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
|
||||
.Case("config_macros", MMToken::ConfigMacros)
|
||||
.Case("conflict", MMToken::Conflict)
|
||||
.Case("exclude", MMToken::ExcludeKeyword)
|
||||
.Case("explicit", MMToken::ExplicitKeyword)
|
||||
.Case("export", MMToken::ExportKeyword)
|
||||
|
@ -1107,6 +1136,10 @@ void ModuleMapParser::parseModuleDecl() {
|
|||
parseConfigMacros();
|
||||
break;
|
||||
|
||||
case MMToken::Conflict:
|
||||
parseConflict();
|
||||
break;
|
||||
|
||||
case MMToken::ExplicitKeyword:
|
||||
case MMToken::FrameworkKeyword:
|
||||
case MMToken::ModuleKeyword:
|
||||
|
@ -1554,6 +1587,56 @@ void ModuleMapParser::parseConfigMacros() {
|
|||
} while (true);
|
||||
}
|
||||
|
||||
/// \brief Format a module-id into a string.
|
||||
static std::string formatModuleId(const ModuleId &Id) {
|
||||
std::string result;
|
||||
{
|
||||
llvm::raw_string_ostream OS(result);
|
||||
|
||||
for (unsigned I = 0, N = Id.size(); I != N; ++I) {
|
||||
if (I)
|
||||
OS << ".";
|
||||
OS << Id[I].first;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Parse a conflict declaration.
|
||||
///
|
||||
/// module-declaration:
|
||||
/// 'conflict' module-id ',' string-literal
|
||||
void ModuleMapParser::parseConflict() {
|
||||
assert(Tok.is(MMToken::Conflict));
|
||||
SourceLocation ConflictLoc = consumeToken();
|
||||
Module::UnresolvedConflict Conflict;
|
||||
|
||||
// Parse the module-id.
|
||||
if (parseModuleId(Conflict.Id))
|
||||
return;
|
||||
|
||||
// Parse the ','.
|
||||
if (!Tok.is(MMToken::Comma)) {
|
||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
|
||||
<< SourceRange(ConflictLoc);
|
||||
return;
|
||||
}
|
||||
consumeToken();
|
||||
|
||||
// Parse the message.
|
||||
if (!Tok.is(MMToken::StringLiteral)) {
|
||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
|
||||
<< formatModuleId(Conflict.Id);
|
||||
return;
|
||||
}
|
||||
Conflict.Message = Tok.getString().str();
|
||||
consumeToken();
|
||||
|
||||
// Add this unresolved conflict.
|
||||
ActiveModule->UnresolvedConflicts.push_back(Conflict);
|
||||
}
|
||||
|
||||
/// \brief Parse an inferred module declaration (wildcard modules).
|
||||
///
|
||||
/// module-declaration:
|
||||
|
@ -1801,6 +1884,7 @@ bool ModuleMapParser::parseModuleMapFile() {
|
|||
|
||||
case MMToken::Comma:
|
||||
case MMToken::ConfigMacros:
|
||||
case MMToken::Conflict:
|
||||
case MMToken::ExcludeKeyword:
|
||||
case MMToken::ExportKeyword:
|
||||
case MMToken::HeaderKeyword:
|
||||
|
|
|
@ -634,11 +634,12 @@ void Sema::ActOnEndOfTranslationUnit() {
|
|||
Module *Mod = Stack.back();
|
||||
Stack.pop_back();
|
||||
|
||||
// Resolve the exported declarations.
|
||||
// Resolve the exported declarations and conflicts.
|
||||
// FIXME: Actually complain, once we figure out how to teach the
|
||||
// diagnostic client to deal with complains in the module map at this
|
||||
// diagnostic client to deal with complaints in the module map at this
|
||||
// point.
|
||||
ModMap.resolveExports(Mod, /*Complain=*/false);
|
||||
ModMap.resolveConflicts(Mod, /*Complain=*/false);
|
||||
|
||||
// Queue the submodules, so their exports will also be resolved.
|
||||
for (Module::submodule_iterator Sub = Mod->submodule_begin(),
|
||||
|
|
|
@ -11826,7 +11826,8 @@ void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
|
|||
Consumer.HandleImplicitImportDecl(ImportD);
|
||||
|
||||
// Make the module visible.
|
||||
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc);
|
||||
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
|
||||
/*Complain=*/false);
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
|
||||
|
|
|
@ -2716,7 +2716,8 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names) {
|
|||
|
||||
void ASTReader::makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind NameVisibility,
|
||||
SourceLocation ImportLoc) {
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) {
|
||||
llvm::SmallPtrSet<Module *, 4> Visited;
|
||||
SmallVector<Module *, 4> Stack;
|
||||
Stack.push_back(Mod);
|
||||
|
@ -2764,6 +2765,20 @@ void ASTReader::makeModuleVisible(Module *Mod,
|
|||
if (Visited.insert(Exported))
|
||||
Stack.push_back(Exported);
|
||||
}
|
||||
|
||||
// Detect any conflicts.
|
||||
if (Complain) {
|
||||
assert(ImportLoc.isValid() && "Missing import location");
|
||||
for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) {
|
||||
if (Mod->Conflicts[I].Other->NameVisibility >= NameVisibility) {
|
||||
Diag(ImportLoc, diag::warn_module_conflict)
|
||||
<< Mod->getFullModuleName()
|
||||
<< Mod->Conflicts[I].Other->getFullModuleName()
|
||||
<< Mod->Conflicts[I].Message;
|
||||
// FIXME: Need note where the other module was imported.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2879,22 +2894,34 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
|||
Id->second->setOutOfDate(true);
|
||||
|
||||
// Resolve any unresolved module exports.
|
||||
for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
|
||||
UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
|
||||
for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) {
|
||||
UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I];
|
||||
SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
|
||||
Module *ResolvedMod = getSubmodule(GlobalID);
|
||||
|
||||
if (Unresolved.IsImport) {
|
||||
|
||||
switch (Unresolved.Kind) {
|
||||
case UnresolvedModuleRef::Conflict:
|
||||
if (ResolvedMod) {
|
||||
Module::Conflict Conflict;
|
||||
Conflict.Other = ResolvedMod;
|
||||
Conflict.Message = Unresolved.String.str();
|
||||
Unresolved.Mod->Conflicts.push_back(Conflict);
|
||||
}
|
||||
continue;
|
||||
|
||||
case UnresolvedModuleRef::Import:
|
||||
if (ResolvedMod)
|
||||
Unresolved.Mod->Imports.push_back(ResolvedMod);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ResolvedMod || Unresolved.IsWildcard)
|
||||
Unresolved.Mod->Exports.push_back(
|
||||
Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
|
||||
case UnresolvedModuleRef::Export:
|
||||
if (ResolvedMod || Unresolved.IsWildcard)
|
||||
Unresolved.Mod->Exports.push_back(
|
||||
Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UnresolvedModuleImportExports.clear();
|
||||
UnresolvedModuleRefs.clear();
|
||||
|
||||
InitializeContext();
|
||||
|
||||
|
@ -3196,7 +3223,8 @@ void ASTReader::InitializeContext() {
|
|||
for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {
|
||||
if (Module *Imported = getSubmodule(ImportedModules[I]))
|
||||
makeModuleVisible(Imported, Module::AllVisible,
|
||||
/*ImportLoc=*/SourceLocation());
|
||||
/*ImportLoc=*/SourceLocation(),
|
||||
/*Complain=*/false);
|
||||
}
|
||||
ImportedModules.clear();
|
||||
}
|
||||
|
@ -3534,9 +3562,11 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
|
||||
SubmodulesLoaded[GlobalIndex] = CurrentModule;
|
||||
|
||||
// Clear out link libraries and config macros; the module file has them.
|
||||
// Clear out data that will be replaced by what is the module file.
|
||||
CurrentModule->LinkLibraries.clear();
|
||||
CurrentModule->ConfigMacros.clear();
|
||||
CurrentModule->UnresolvedConflicts.clear();
|
||||
CurrentModule->Conflicts.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3660,13 +3690,13 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
break;
|
||||
|
||||
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
|
||||
UnresolvedModuleImportExport Unresolved;
|
||||
UnresolvedModuleRef Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[Idx];
|
||||
Unresolved.IsImport = true;
|
||||
Unresolved.Kind = UnresolvedModuleRef::Import;
|
||||
Unresolved.IsWildcard = false;
|
||||
UnresolvedModuleImportExports.push_back(Unresolved);
|
||||
UnresolvedModuleRefs.push_back(Unresolved);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3681,13 +3711,13 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
break;
|
||||
|
||||
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
|
||||
UnresolvedModuleImportExport Unresolved;
|
||||
UnresolvedModuleRef Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[Idx];
|
||||
Unresolved.IsImport = false;
|
||||
Unresolved.Kind = UnresolvedModuleRef::Export;
|
||||
Unresolved.IsWildcard = Record[Idx + 1];
|
||||
UnresolvedModuleImportExports.push_back(Unresolved);
|
||||
UnresolvedModuleRefs.push_back(Unresolved);
|
||||
}
|
||||
|
||||
// Once we've loaded the set of exports, there's no reason to keep
|
||||
|
@ -3733,6 +3763,26 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
|
||||
CurrentModule->ConfigMacros.push_back(Blob.str());
|
||||
break;
|
||||
|
||||
case SUBMODULE_CONFLICT: {
|
||||
if (First) {
|
||||
Error("missing submodule metadata record at beginning of block");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!CurrentModule)
|
||||
break;
|
||||
|
||||
UnresolvedModuleRef Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[0];
|
||||
Unresolved.Kind = UnresolvedModuleRef::Conflict;
|
||||
Unresolved.IsWildcard = false;
|
||||
Unresolved.String = Blob;
|
||||
UnresolvedModuleRefs.push_back(Unresolved);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2180,6 +2180,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name
|
||||
unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||
|
||||
Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message
|
||||
unsigned ConflictAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||
|
||||
// Write the submodule metadata block.
|
||||
RecordData Record;
|
||||
Record.push_back(getNumberOfModules(WritingModule));
|
||||
|
@ -2295,6 +2301,17 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
Mod->LinkLibraries[I].Library);
|
||||
}
|
||||
|
||||
// Emit the conflicts.
|
||||
for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) {
|
||||
Record.clear();
|
||||
Record.push_back(SUBMODULE_CONFLICT);
|
||||
unsigned OtherID = getSubmoduleID(Mod->Conflicts[I].Other);
|
||||
assert(OtherID && "Unknown submodule!");
|
||||
Record.push_back(OtherID);
|
||||
Stream.EmitRecordWithBlob(ConflictAbbrev, Record,
|
||||
Mod->Conflicts[I].Message);
|
||||
}
|
||||
|
||||
// Emit the configuration macros.
|
||||
for (unsigned I = 0, N = Mod->ConfigMacros.size(); I != N; ++I) {
|
||||
Record.clear();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
int conflict_a;
|
|
@ -0,0 +1 @@
|
|||
int conflict_b;
|
|
@ -0,0 +1,10 @@
|
|||
module Conflicts {
|
||||
explicit module A {
|
||||
header "conflict_a.h"
|
||||
conflict B, "we just don't like B"
|
||||
}
|
||||
|
||||
module B {
|
||||
header "conflict_b.h"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -I %S/Inputs/Conflicts %s -verify
|
||||
|
||||
@import Conflicts;
|
||||
|
||||
@import Conflicts.A; // expected-warning{{module 'Conflicts.A' conflicts with already-imported module 'Conflicts.B': we just don't like B}}
|
||||
|
|
@ -61,7 +61,8 @@ class VoidModuleLoader : public ModuleLoader {
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) { }
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) { }
|
||||
};
|
||||
|
||||
TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
|
||||
|
|
|
@ -62,7 +62,8 @@ class VoidModuleLoader : public ModuleLoader {
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) { }
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) { }
|
||||
};
|
||||
|
||||
TEST_F(LexerTest, LexAPI) {
|
||||
|
|
|
@ -39,7 +39,8 @@ class VoidModuleLoader : public ModuleLoader {
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) { }
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) { }
|
||||
};
|
||||
|
||||
// Stub to collect data from InclusionDirective callbacks.
|
||||
|
|
|
@ -62,7 +62,8 @@ class VoidModuleLoader : public ModuleLoader {
|
|||
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc) { }
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) { }
|
||||
};
|
||||
|
||||
TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) {
|
||||
|
|
Loading…
Reference in New Issue