From: Richard Smith Date: Thu, 5 Nov 2015 00:54:55 +0000 (+0000) Subject: [modules] If we're given a module file, via -fmodule-file=, for a module, but X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=72617428e768e273850d5bfdf637d0b63e79b229;p=clang [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@252114 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index cb3341026f..fa032e9eb6 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -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 diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 4188cefc84..0b78326369 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -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; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index c3f19a3a00..c0cf64cecb 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index b7b56f68b8..3265603792 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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"); diff --git a/test/Modules/merge-target-features.cpp b/test/Modules/merge-target-features.cpp index 0ca5679ad1..9ca0539e6a 100644 --- a/test/Modules/merge-target-features.cpp +++ b/test/Modules/merge-target-features.cpp @@ -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"