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

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

llvm-svn: 375322
This commit is contained in:
Michael J. Spencer 2019-10-19 01:36:37 +00:00
parent 1aae510893
commit 14a3f77ba1
5 changed files with 85 additions and 1 deletions

View File

@ -225,6 +225,16 @@ Command-line parameters
``-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.
-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
================

View File

@ -815,6 +815,9 @@ def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
HelpText<"Disable the module hash">;
def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">,
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>">,
HelpText<"Add directory to the C SYSTEM include search path">;
def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,

View File

@ -11,6 +11,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include <cstdint>
@ -206,6 +207,13 @@ public:
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 = "/")
: Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
@ -214,7 +222,8 @@ public:
ModulesValidateOncePerBuildSession(false),
ModulesValidateSystemHeaders(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.
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
#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H

View File

@ -2067,6 +2067,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
Opts.ModulesStrictContextHash = Args.hasArg(OPT_fmodules_strict_context_hash);
Opts.ModulesValidateDiagnosticOptions =
!Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
@ -3546,6 +3547,7 @@ std::string CompilerInvocation::getModuleHash() const {
using llvm::hash_code;
using llvm::hash_value;
using llvm::hash_combine;
using llvm::hash_combine_range;
// Start the signature with the compiler version.
// FIXME: We'd rather use something more cryptographically sound than
@ -3600,6 +3602,24 @@ std::string CompilerInvocation::getModuleHash() const {
hsOpts.ModulesValidateDiagnosticOptions);
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.
code = hash_combine(code, hsOpts.ModuleUserBuildPath);

View File

@ -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'