From cefd54750c4216d515b019df09eccd7c13c7612c Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 26 Jul 2016 17:12:17 +0000 Subject: [PATCH] Modules: add command line option fmodules-disable-diagnostic-validation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With PCH+Module, sometimes compiler gives a hard error: Module file ‘.pcm' is out of date and needs to be rebuilt This happens when we have a pch importing a module and the module gets overwritten by another compiler instance after we build the pch (one example is that both compiler instances hash to the same pcm file but use different diagnostic options). When we try to load the pch later on, the compiler notices that the imported module is out of date (modification date, size do not match) but it can't handle this out of date pcm (i.e it does not know how to rebuild the pch). This commit introduces a new command line option so for PCH + module, we can turn on this option and if two compiler instances only differ in diagnostic options, the latter instance will not invalidate the original pcm. rdar://26675801 Differential Revision: http://reviews.llvm.org/D22773 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@276769 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 3 +++ include/clang/Lex/HeaderSearchOptions.h | 4 +++- include/clang/Serialization/ASTReader.h | 5 +++-- lib/Frontend/CompilerInvocation.cpp | 5 ++++- lib/Frontend/FrontendActions.cpp | 6 +++++- lib/Serialization/ASTReader.cpp | 18 ++++++++++++------ test/Driver/modules.m | 6 ++++++ test/Modules/Inputs/DiagOutOfDate.h | 1 + test/Modules/Inputs/module.map | 4 ++++ .../Inputs/pch-import-module-out-of-date.pch | 1 + test/Modules/diagnostic-options-out-of-date.m | 12 ++++++++++++ 11 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 test/Modules/Inputs/DiagOutOfDate.h create mode 100644 test/Modules/Inputs/pch-import-module-out-of-date.pch create mode 100644 test/Modules/diagnostic-options-out-of-date.m diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index d03ab0435a..552a161341 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -857,6 +857,9 @@ def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-on Group, Flags<[CC1Option]>, HelpText<"Don't verify input files for the modules if the module has been " "successfully validated or loaded during this build session">; +def fmodules_disable_diagnostic_validation : Flag<["-"], "fmodules-disable-diagnostic-validation">, + Group, Flags<[CC1Option]>, + HelpText<"Disable validation of the diagnostic options when loading the module">; def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">, Group, Flags<[CC1Option]>, HelpText<"Validate the system headers that a module depends on when loading the module">; diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 915dbf74b2..9727f5613a 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -172,6 +172,8 @@ public: /// Whether the module includes debug information (-gmodules). unsigned UseDebugInfo : 1; + unsigned ModulesValidateDiagnosticOptions : 1; + HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0), ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0), @@ -181,7 +183,7 @@ public: UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), ModulesValidateOncePerBuildSession(false), ModulesValidateSystemHeaders(false), - UseDebugInfo(false) {} + UseDebugInfo(false), ModulesValidateDiagnosticOptions(true) {} /// AddPath - Add the \p Path path to the specified \p Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index b931f92570..943765d212 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1153,7 +1153,7 @@ private: static ASTReadResult ReadOptionsBlock( llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities, bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener, - std::string &SuggestedPredefines); + std::string &SuggestedPredefines, bool ValidateDiagnosticOptions); ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities); ASTReadResult ReadExtensionBlock(ModuleFile &F); bool ParseLineTable(ModuleFile &F, const RecordData &Record); @@ -1516,7 +1516,8 @@ public: readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, - ASTReaderListener &Listener); + ASTReaderListener &Listener, + bool ValidateDiagnosticOptions); /// \brief Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 98eb4bb377..543cca7ff8 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1362,6 +1362,8 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); + Opts.ModulesValidateDiagnosticOptions = + !Args.hasArg(OPT_fmodules_disable_diagnostic_validation); Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps); Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd); Opts.ModuleCachePruneInterval = @@ -2457,7 +2459,8 @@ std::string CompilerInvocation::getModuleHash() const { hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardCXXIncludes, - hsOpts.UseLibcxx); + hsOpts.UseLibcxx, + hsOpts.ModulesValidateDiagnosticOptions); code = hash_combine(code, hsOpts.ResourceDir); // Extend the signature with the user build path. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 5267a3bdaf..babaa2de77 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -608,11 +608,15 @@ void DumpModuleInfoAction::ExecuteAction() { llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs(); Out << "Information for module file '" << getCurrentFile() << "':\n"; + Preprocessor &PP = getCompilerInstance().getPreprocessor(); DumpModuleInfoListener Listener(Out); + HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); ASTReader::readASTFileControlBlock( getCurrentFile(), getCompilerInstance().getFileManager(), getCompilerInstance().getPCHContainerReader(), - /*FindModuleFileExtensions=*/true, Listener); + /*FindModuleFileExtensions=*/true, Listener, + HSOpts.ModulesValidateDiagnosticOptions); } //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 27b7048f37..491a0febd5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2084,7 +2084,7 @@ static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) { ASTReader::ASTReadResult ASTReader::ReadOptionsBlock( BitstreamCursor &Stream, unsigned ClientLoadCapabilities, bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener, - std::string &SuggestedPredefines) { + std::string &SuggestedPredefines, bool ValidateDiagnosticOptions) { if (Stream.EnterSubBlock(OPTIONS_BLOCK_ID)) return Failure; @@ -2128,7 +2128,8 @@ ASTReader::ASTReadResult ASTReader::ReadOptionsBlock( case DIAGNOSTIC_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0; - if (!AllowCompatibleConfigurationMismatch && + if (ValidateDiagnosticOptions && + !AllowCompatibleConfigurationMismatch && ParseDiagnosticOptions(Record, Complain, Listener)) return OutOfDate; break; @@ -2255,10 +2256,13 @@ ASTReader::ReadControlBlock(ModuleFile &F, // FIXME: Allow this for files explicitly specified with -include-pch. bool AllowCompatibleConfigurationMismatch = F.Kind == MK_ExplicitModule; + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); Result = ReadOptionsBlock(Stream, ClientLoadCapabilities, AllowCompatibleConfigurationMismatch, - *Listener, SuggestedPredefines); + *Listener, SuggestedPredefines, + HSOpts.ModulesValidateDiagnosticOptions); if (Result == Failure) { Error("malformed block record in AST file"); return Result; @@ -4195,7 +4199,7 @@ bool ASTReader::readASTFileControlBlock( StringRef Filename, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, - ASTReaderListener &Listener) { + ASTReaderListener &Listener, bool ValidateDiagnosticOptions) { // Open the AST file. // FIXME: This allows use of the VFS; we do not allow use of the // VFS when actually loading a module. @@ -4235,7 +4239,8 @@ bool ASTReader::readASTFileControlBlock( std::string IgnoredSuggestedPredefines; if (ReadOptionsBlock(Stream, ARR_ConfigurationMismatch | ARR_OutOfDate, /*AllowCompatibleConfigurationMismatch*/ false, - Listener, IgnoredSuggestedPredefines) != Success) + Listener, IgnoredSuggestedPredefines, + ValidateDiagnosticOptions) != Success) return true; break; } @@ -4408,7 +4413,8 @@ bool ASTReader::isAcceptableASTFile( ExistingModuleCachePath, FileMgr); return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr, /*FindModuleFileExtensions=*/false, - validator); + validator, + /*ValidateDiagnosticOptions=*/true); } ASTReader::ASTReadResult diff --git a/test/Driver/modules.m b/test/Driver/modules.m index 0f2d4d5bb0..fd66478047 100644 --- a/test/Driver/modules.m +++ b/test/Driver/modules.m @@ -33,6 +33,12 @@ // RUN: %clang -fmodules-validate-system-headers -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS %s // MODULES_VALIDATE_SYSTEM_HEADERS: -fmodules-validate-system-headers +// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT %s +// MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT-NOT: -fmodules-disable-diagnostic-validation + +// RUN: %clang -fmodules-disable-diagnostic-validation -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION %s +// MODULES_DISABLE_DIAGNOSTIC_VALIDATION: -fmodules-disable-diagnostic-validation + // RUN: %clang -fmodules -fmodule-map-file=foo.map -fmodule-map-file=bar.map -### %s 2>&1 | FileCheck -check-prefix=CHECK-MODULE-MAP-FILES %s // CHECK-MODULE-MAP-FILES: "-fmodules" // CHECK-MODULE-MAP-FILES: "-fmodule-map-file=foo.map" diff --git a/test/Modules/Inputs/DiagOutOfDate.h b/test/Modules/Inputs/DiagOutOfDate.h new file mode 100644 index 0000000000..f86587a839 --- /dev/null +++ b/test/Modules/Inputs/DiagOutOfDate.h @@ -0,0 +1 @@ +const int a = 1; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 6846690c84..a683190e18 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -418,3 +418,7 @@ module Empty {} module MacroFabs1 { header "MacroFabs1.h" } + +module DiagOutOfDate { + header "DiagOutOfDate.h" +} diff --git a/test/Modules/Inputs/pch-import-module-out-of-date.pch b/test/Modules/Inputs/pch-import-module-out-of-date.pch new file mode 100644 index 0000000000..93a446cbcf --- /dev/null +++ b/test/Modules/Inputs/pch-import-module-out-of-date.pch @@ -0,0 +1 @@ +@import DiagOutOfDate; diff --git a/test/Modules/diagnostic-options-out-of-date.m b/test/Modules/diagnostic-options-out-of-date.m new file mode 100644 index 0000000000..ed9e8e1fe1 --- /dev/null +++ b/test/Modules/diagnostic-options-out-of-date.m @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// Build A.pcm +// RUN: %clang_cc1 -Werror -Wno-conversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs %s -fmodules-disable-diagnostic-validation +// Build pch that imports A.pcm +// RUN: %clang_cc1 -Werror -Wno-conversion -emit-pch -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -o %t.pch -I %S/Inputs -x objective-c-header %S/Inputs/pch-import-module-out-of-date.pch -fmodules-disable-diagnostic-validation +// Make sure that we don't rebuild A.pcm and overwrite the original A.pcm that the pch imports +// RUN: %clang_cc1 -Werror -Wconversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs %s -fmodules-disable-diagnostic-validation +// Make sure we don't error out when using the pch +// RUN: %clang_cc1 -Werror -Wno-conversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fsyntax-only -I %S/Inputs -include-pch %t.pch %s -verify -fmodules-disable-diagnostic-validation +// expected-no-diagnostics + +@import DiagOutOfDate; -- 2.40.0