Browse Source

[Implicit Modules] Add -cc1 option -fmodules-strict-context-hash which includes search paths and diagnostics.

Differential Revision: https://reviews.llvm.org/D68528

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@375322 91177308-0d34-0410-b5e6-96231b3b80d8
Michael J. Spencer 5 năm trước cách đây
mục cha
commit
56ddb2a69c

+ 10 - 0
docs/Modules.rst

@@ -225,6 +225,16 @@ Command-line parameters
 ``-fprebuilt-module-path=<directory>``
 ``-fprebuilt-module-path=<directory>``
   Specify the path to the prebuilt modules. If specified, we will look for modules in this directory for a given top-level module name. We don't need a module map for loading prebuilt modules in this directory and the compiler will not try to rebuild these modules. This can be specified multiple times.
   Specify the path to the prebuilt modules. If specified, we will look for modules in this directory for a given top-level module name. We don't need a module map for loading prebuilt modules in this directory and the compiler will not try to rebuild these modules. This can be specified multiple times.
 
 
+-cc1 Options
+^^^^^^^^^^^^
+
+``-fmodules-strict-context-hash``
+  Enables hashing of all compiler options that could impact the semantics of a
+  module in an implicit build. This includes things such as header search paths
+  and diagnostics. Using this option may lead to an excessive number of modules
+  being built if the command line arguments are not homogeneous across your
+  build.
+
 Module Semantics
 Module Semantics
 ================
 ================
 
 

+ 3 - 0
include/clang/Driver/CC1Options.td

@@ -815,6 +815,9 @@ def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
   HelpText<"Disable the module hash">;
   HelpText<"Disable the module hash">;
 def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">,
 def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">,
   HelpText<"Enable hashing the content of a module file">;
   HelpText<"Enable hashing the content of a module file">;
+def fmodules_strict_context_hash : Flag<["-"], "fmodules-strict-context-hash">,
+  HelpText<"Enable hashing of all compiler options that could impact the "
+           "semantics of a module in an implicit build">;
 def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
 def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
   HelpText<"Add directory to the C SYSTEM include search path">;
   HelpText<"Add directory to the C SYSTEM include search path">;
 def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,
 def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,

+ 19 - 1
include/clang/Lex/HeaderSearchOptions.h

@@ -11,6 +11,7 @@
 
 
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringRef.h"
 #include <cstdint>
 #include <cstdint>
@@ -206,6 +207,13 @@ public:
 
 
   unsigned ModulesHashContent : 1;
   unsigned ModulesHashContent : 1;
 
 
+  /// Whether we should include all things that could impact the module in the
+  /// hash.
+  ///
+  /// This includes things like the full header search path, and enabled
+  /// diagnostics.
+  unsigned ModulesStrictContextHash : 1;
+
   HeaderSearchOptions(StringRef _Sysroot = "/")
   HeaderSearchOptions(StringRef _Sysroot = "/")
       : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
       : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
         ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
         ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
@@ -214,7 +222,8 @@ public:
         ModulesValidateOncePerBuildSession(false),
         ModulesValidateOncePerBuildSession(false),
         ModulesValidateSystemHeaders(false),
         ModulesValidateSystemHeaders(false),
         ValidateASTInputFilesContent(false), UseDebugInfo(false),
         ValidateASTInputFilesContent(false), UseDebugInfo(false),
-        ModulesValidateDiagnosticOptions(true), ModulesHashContent(false) {}
+        ModulesValidateDiagnosticOptions(true), ModulesHashContent(false),
+        ModulesStrictContextHash(false) {}
 
 
   /// AddPath - Add the \p Path path to the specified \p Group list.
   /// AddPath - Add the \p Path path to the specified \p Group list.
   void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
   void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
@@ -238,6 +247,15 @@ public:
   }
   }
 };
 };
 
 
+inline llvm::hash_code hash_value(const HeaderSearchOptions::Entry &E) {
+  return llvm::hash_combine(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
+}
+
+inline llvm::hash_code
+hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
+  return llvm::hash_combine(SHP.Prefix, SHP.IsSystemHeader);
+}
+
 } // namespace clang
 } // namespace clang
 
 
 #endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
 #endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H

+ 20 - 0
lib/Frontend/CompilerInvocation.cpp

@@ -2067,6 +2067,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
     Opts.AddPrebuiltModulePath(A->getValue());
     Opts.AddPrebuiltModulePath(A->getValue());
   Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
   Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
   Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
   Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
+  Opts.ModulesStrictContextHash = Args.hasArg(OPT_fmodules_strict_context_hash);
   Opts.ModulesValidateDiagnosticOptions =
   Opts.ModulesValidateDiagnosticOptions =
       !Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
       !Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
   Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
   Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
@@ -3546,6 +3547,7 @@ std::string CompilerInvocation::getModuleHash() const {
   using llvm::hash_code;
   using llvm::hash_code;
   using llvm::hash_value;
   using llvm::hash_value;
   using llvm::hash_combine;
   using llvm::hash_combine;
+  using llvm::hash_combine_range;
 
 
   // Start the signature with the compiler version.
   // Start the signature with the compiler version.
   // FIXME: We'd rather use something more cryptographically sound than
   // FIXME: We'd rather use something more cryptographically sound than
@@ -3600,6 +3602,24 @@ std::string CompilerInvocation::getModuleHash() const {
                       hsOpts.ModulesValidateDiagnosticOptions);
                       hsOpts.ModulesValidateDiagnosticOptions);
   code = hash_combine(code, hsOpts.ResourceDir);
   code = hash_combine(code, hsOpts.ResourceDir);
 
 
+  if (hsOpts.ModulesStrictContextHash) {
+    hash_code SHPC = hash_combine_range(hsOpts.SystemHeaderPrefixes.begin(),
+                                        hsOpts.SystemHeaderPrefixes.end());
+    hash_code UEC = hash_combine_range(hsOpts.UserEntries.begin(),
+                                       hsOpts.UserEntries.end());
+    code = hash_combine(code, hsOpts.SystemHeaderPrefixes.size(), SHPC,
+                        hsOpts.UserEntries.size(), UEC);
+
+    const DiagnosticOptions &diagOpts = getDiagnosticOpts();
+    #define DIAGOPT(Name, Bits, Default) \
+      code = hash_combine(code, diagOpts.Name);
+    #define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+      code = hash_combine(code, diagOpts.get##Name());
+    #include "clang/Basic/DiagnosticOptions.def"
+    #undef DIAGOPT
+    #undef ENUM_DIAGOPT
+  }
+
   // Extend the signature with the user build path.
   // Extend the signature with the user build path.
   code = hash_combine(code, hsOpts.ModuleUserBuildPath);
   code = hash_combine(code, hsOpts.ModuleUserBuildPath);
 
 

+ 33 - 0
test/Modules/context-hash.c

@@ -0,0 +1,33 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -internal-isystem \
+// RUN:   %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps \
+// RUN:   -fmodules-cache-path=%t %s -Rmodule-build 2> %t1
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -internal-isystem \
+// RUN:   %S/Inputs/System/usr/include -internal-isystem %S -fmodules \
+// RUN:   -fimplicit-module-maps -fmodules-cache-path=%t %s -Rmodule-build 2> \
+// RUN:   %t2
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -internal-isystem \
+// RUN:   %S/Inputs/System/usr/include -internal-isystem %S -fmodules \
+// RUN:   -fimplicit-module-maps -fmodules-cache-path=%t %s \
+// RUN:   -fmodules-strict-context-hash -Rmodule-build 2> %t3
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -Weverything -internal-isystem \
+// RUN:   %S/Inputs/System/usr/include -fmodules -fmodules-strict-context-hash \
+// RUN:   -fimplicit-module-maps -fmodules-cache-path=%t %s -Rmodule-build 2> \
+// RUN:   %t4
+// RUN: echo %t | cat - %t1 %t2 %t3 %t4 | FileCheck %s
+
+// This test verifies that only strict hashing includes search paths and
+// diagnostics in the module context hash.
+
+#include <stdio.h>
+
+// CHECK: [[PREFIX:(.*[/\\])+[a-zA-Z0-9.-]+]]
+// CHECK: building module 'cstd' as '[[PREFIX]]{{[/\\]}}[[CONTEXT_HASH:[A-Z0-9]+]]{{[/\\]}}cstd-[[AST_HASH:[A-Z0-9]+]].pcm'
+// CHECK: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}}cstd-[[AST_HASH]].pcm'
+// CHECK-NOT: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}}
+// CHECK: cstd-[[AST_HASH]].pcm'
+// CHECK-NOT: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}}
+// CHECK: cstd-[[AST_HASH]].pcm'