forked from OSchip/llvm-project
[modules] If we're given a module file, via -fmodule-file=, for a module, but
we can't load that file due to a configuration mismatch, and implicit module building is disabled, and the user turns off the error-by-default warning for that situation, then fall back to textual inclusion for the module rather than giving an error if any of its headers are included. llvm-svn: 252114
This commit is contained in:
parent
192c748027
commit
8a308ec24d
|
@ -152,6 +152,9 @@ public:
|
|||
/// \brief Whether this module is missing a feature from \c Requirements.
|
||||
unsigned IsMissingRequirement : 1;
|
||||
|
||||
/// \brief Whether we tried and failed to load a module file for this module.
|
||||
unsigned HasIncompatibleModuleFile : 1;
|
||||
|
||||
/// \brief Whether this module is available in the current translation unit.
|
||||
///
|
||||
/// If the module is missing headers or does not meet all requirements then
|
||||
|
|
|
@ -28,11 +28,12 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
|
|||
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
|
||||
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
|
||||
Umbrella(), Signature(0), ASTFile(nullptr), VisibilityID(VisibilityID),
|
||||
IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
|
||||
IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
|
||||
IsExternC(false), IsInferred(false), InferSubmodules(false),
|
||||
InferExplicitSubmodules(false), InferExportWildcard(false),
|
||||
ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
|
||||
IsMissingRequirement(false), HasIncompatibleModuleFile(false),
|
||||
IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
|
||||
IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
|
||||
IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
|
||||
InferExportWildcard(false), ConfigMacrosExhaustive(false),
|
||||
NameVisibility(Hidden) {
|
||||
if (Parent) {
|
||||
if (!Parent->isAvailable())
|
||||
IsAvailable = false;
|
||||
|
|
|
@ -1327,6 +1327,17 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
|
|||
}
|
||||
LoadedModules.clear();
|
||||
}
|
||||
|
||||
void markAllUnavailable() {
|
||||
for (auto *II : LoadedModules) {
|
||||
if (Module *M = CI.getPreprocessor()
|
||||
.getHeaderSearchInfo()
|
||||
.getModuleMap()
|
||||
.findModule(II->getName()))
|
||||
M->HasIncompatibleModuleFile = true;
|
||||
}
|
||||
LoadedModules.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// If we don't already have an ASTReader, create one now.
|
||||
|
@ -1343,15 +1354,18 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
|
|||
SourceLocation(),
|
||||
ASTReader::ARR_ConfigurationMismatch)) {
|
||||
case ASTReader::Success:
|
||||
// We successfully loaded the module file; remember the set of provided
|
||||
// modules so that we don't try to load implicit modules for them.
|
||||
ListenerRef.registerAll();
|
||||
return true;
|
||||
// We successfully loaded the module file; remember the set of provided
|
||||
// modules so that we don't try to load implicit modules for them.
|
||||
ListenerRef.registerAll();
|
||||
return true;
|
||||
|
||||
case ASTReader::ConfigurationMismatch:
|
||||
// Ignore unusable module files.
|
||||
getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch)
|
||||
<< FileName;
|
||||
// All modules provided by any files we tried and failed to load are now
|
||||
// unavailable; includes of those modules should now be handled textually.
|
||||
ListenerRef.markAllUnavailable();
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -1407,6 +1421,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
std::string ModuleFileName =
|
||||
PP->getHeaderSearchInfo().getModuleFileName(Module);
|
||||
if (ModuleFileName.empty()) {
|
||||
if (Module->HasIncompatibleModuleFile) {
|
||||
// We tried and failed to load a module file for this module. Fall
|
||||
// back to textual inclusion for its headers.
|
||||
return ModuleLoadResult(nullptr, /*missingExpected*/true);
|
||||
}
|
||||
|
||||
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
|
||||
<< ModuleName;
|
||||
ModuleBuildFailed = true;
|
||||
|
|
|
@ -2151,6 +2151,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
const ModuleFile *ImportedBy,
|
||||
unsigned ClientLoadCapabilities) {
|
||||
BitstreamCursor &Stream = F.Stream;
|
||||
ASTReadResult Result = Success;
|
||||
|
||||
if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
|
||||
Error("malformed block record in AST file");
|
||||
|
@ -2211,7 +2212,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
return Result;
|
||||
}
|
||||
|
||||
case llvm::BitstreamEntry::SubBlock:
|
||||
|
@ -2239,16 +2240,21 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
bool AllowCompatibleConfigurationMismatch =
|
||||
F.Kind == MK_ExplicitModule;
|
||||
|
||||
auto Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
|
||||
AllowCompatibleConfigurationMismatch,
|
||||
*Listener, SuggestedPredefines);
|
||||
Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
|
||||
AllowCompatibleConfigurationMismatch,
|
||||
*Listener, SuggestedPredefines);
|
||||
if (Result == Failure) {
|
||||
Error("malformed block record in AST file");
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (!DisableValidation && Result != Success &&
|
||||
(Result != ConfigurationMismatch || !AllowConfigurationMismatch))
|
||||
if (DisableValidation ||
|
||||
(AllowConfigurationMismatch && Result == ConfigurationMismatch))
|
||||
Result = Success;
|
||||
|
||||
// If we've diagnosed a problem, we're done.
|
||||
if (Result != Success &&
|
||||
isDiagnosedResult(Result, ClientLoadCapabilities))
|
||||
return Result;
|
||||
} else if (Stream.SkipBlock()) {
|
||||
Error("malformed block record in AST file");
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
// RUN: -target-cpu i386 \
|
||||
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=SUBSET %s
|
||||
// SUBSET-NOT: error:
|
||||
// SUBSET: error: {{.*}} configuration mismatch
|
||||
// SUBSET-NOT: error:
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
|
||||
// RUN: -iquote Inputs/merge-target-features \
|
||||
|
@ -56,7 +58,9 @@
|
|||
// RUN: -target-cpu i386 -target-feature +cx16 \
|
||||
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=MISMATCH %s
|
||||
// MISMATCH-NOT: error:
|
||||
// MISMATCH: error: {{.*}} configuration mismatch
|
||||
// MISMATCH-NOT: error:
|
||||
|
||||
#include "foo.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue