]> granicus.if.org Git - clang/commitdiff
Modules: add command line option fmodules-disable-diagnostic-validation
authorManman Ren <manman.ren@gmail.com>
Tue, 26 Jul 2016 17:12:17 +0000 (17:12 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 26 Jul 2016 17:12:17 +0000 (17:12 +0000)
With PCH+Module, sometimes compiler gives a hard error:
Module file ‘<some-file path>.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
include/clang/Lex/HeaderSearchOptions.h
include/clang/Serialization/ASTReader.h
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/FrontendActions.cpp
lib/Serialization/ASTReader.cpp
test/Driver/modules.m
test/Modules/Inputs/DiagOutOfDate.h [new file with mode: 0644]
test/Modules/Inputs/module.map
test/Modules/Inputs/pch-import-module-out-of-date.pch [new file with mode: 0644]
test/Modules/diagnostic-options-out-of-date.m [new file with mode: 0644]

index d03ab0435a6ef8fc38ffa71d9ac55e50511dffb2..552a161341e8ee974f107fde69b5f8399faafca5 100644 (file)
@@ -857,6 +857,9 @@ def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-on
   Group<i_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<i_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<i_Group>, Flags<[CC1Option]>,
   HelpText<"Validate the system headers that a module depends on when loading the module">;
index 915dbf74b2a4d1051a95ee0eb74705714b31ac78..9727f5613aa0743ae51d2531260c0a0081c1aee8 100644 (file)
@@ -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,
index b931f9257055ad4587d7c08d1887fd517a3c01e2..943765d212c3cf2baaae8a0e7a9b0586460754df 100644 (file)
@@ -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.
index 98eb4bb3776d87356e4653bef410f42c33bb1b60..543cca7ff8cf5d9359480ac6a884b8041bc8dd42 100644 (file)
@@ -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.
index 5267a3bdaf0f78a7d76cbfbda83b5a0ec6ed2173..babaa2de7797ea67dddfd0f4733286ddd7df5f0e 100644 (file)
@@ -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);
 }
 
 //===----------------------------------------------------------------------===//
index 27b7048f375bb31197107ff79db313dcdcccc9c8..491a0febd50c72149303edf99bb67fd113311448 100644 (file)
@@ -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
index 0f2d4d5bb0b424d5fbc01b9ff80c71d63a5707a9..fd66478047225772dacdf927b32862ece1229cb3 100644 (file)
 // 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 (file)
index 0000000..f86587a
--- /dev/null
@@ -0,0 +1 @@
+const int a = 1;
index 6846690c849868f42c6096589f5b4a695812a7be..a683190e18251dcdfdad13804271c79690bc2987 100644 (file)
@@ -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 (file)
index 0000000..93a446c
--- /dev/null
@@ -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 (file)
index 0000000..ed9e8e1
--- /dev/null
@@ -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;