diff --git a/clang/include/clang/Basic/ObjCRuntime.h b/clang/include/clang/Basic/ObjCRuntime.h --- a/clang/include/clang/Basic/ObjCRuntime.h +++ b/clang/include/clang/Basic/ObjCRuntime.h @@ -480,6 +480,9 @@ friend llvm::hash_code hash_value(const ObjCRuntime &OCR) { return llvm::hash_combine(OCR.getKind(), OCR.getVersion()); } + friend llvm::stable_hash_code stable_hash_value(const ObjCRuntime &OCR) { + return llvm::stable_hash_combine(OCR.getKind(), OCR.getVersion()); + } }; raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value); diff --git a/clang/include/clang/Basic/Sanitizers.h b/clang/include/clang/Basic/Sanitizers.h --- a/clang/include/clang/Basic/Sanitizers.h +++ b/clang/include/clang/Basic/Sanitizers.h @@ -77,6 +77,7 @@ } llvm::hash_code hash_value() const; + llvm::stable_hash_code stable_hash_value() const; constexpr explicit operator bool() const { return maskLoToHigh[0] || maskLoToHigh[1]; @@ -124,6 +125,7 @@ // Declaring in clang namespace so that it can be found by ADL. llvm::hash_code hash_value(const clang::SanitizerMask &Arg); +llvm::stable_hash_code stable_hash_value(const clang::SanitizerMask &Arg); // Define the set of sanitizer kinds, as well as the set of sanitizers each // sanitizer group expands into. diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -256,11 +256,22 @@ return llvm::hash_combine(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot); } +inline llvm::stable_hash_code +stable_hash_value(const HeaderSearchOptions::Entry &E) { + return llvm::stable_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); } +inline llvm::stable_hash_code +stable_hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) { + return llvm::stable_hash_combine(SHP.Prefix, SHP.IsSystemHeader); +} + } // namespace clang #endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H diff --git a/clang/include/clang/Serialization/ModuleFileExtension.h b/clang/include/clang/Serialization/ModuleFileExtension.h --- a/clang/include/clang/Serialization/ModuleFileExtension.h +++ b/clang/include/clang/Serialization/ModuleFileExtension.h @@ -17,7 +17,7 @@ namespace llvm { class BitstreamCursor; class BitstreamWriter; -class hash_code; +class stable_hash_code; class raw_ostream; } @@ -86,7 +86,7 @@ /// The default implementation of this function simply returns the /// hash code as given, so the presence/absence of this extension /// does not distinguish module files. - virtual llvm::hash_code hashExtension(llvm::hash_code c) const; + virtual llvm::stable_hash_code hashExtension(llvm::stable_hash_code c) const; /// Create a new module file extension writer, which will be /// responsible for writing the extension contents into a particular diff --git a/clang/lib/Basic/Sanitizers.cpp b/clang/lib/Basic/Sanitizers.cpp --- a/clang/lib/Basic/Sanitizers.cpp +++ b/clang/lib/Basic/Sanitizers.cpp @@ -56,9 +56,14 @@ return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]); } +llvm::stable_hash_code SanitizerMask::stable_hash_value() const { + return llvm::stable_hash_combine_range(&maskLoToHigh[0], + &maskLoToHigh[kNumElem]); +} + namespace clang { -llvm::hash_code hash_value(const clang::SanitizerMask &Arg) { - return Arg.hash_value(); +llvm::stable_hash_code stable_hash_value(const clang::SanitizerMask &Arg) { + return Arg.stable_hash_value(); } StringRef AsanDtorKindToString(llvm::AsanDtorKind kind) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4464,47 +4464,49 @@ std::string CompilerInvocation::getModuleHash() const { // Note: For QoI reasons, the things we use as a hash here should all be // dumped via the -module-info flag. - using llvm::hash_code; - using llvm::hash_value; - using llvm::hash_combine; - using llvm::hash_combine_range; + using llvm::stable_hash_code; + using llvm::stable_hash_combine; + using llvm::stable_hash_combine_range; + using llvm::stable_hash_value; // Start the signature with the compiler version. // FIXME: We'd rather use something more cryptographically sound than // CityHash, but this will do for now. - hash_code code = hash_value(getClangFullRepositoryVersion()); + stable_hash_code code = stable_hash_value(getClangFullRepositoryVersion()); // Also include the serialization version, in case LLVM_APPEND_VC_REV is off // and getClangFullRepositoryVersion() doesn't include git revision. - code = hash_combine(code, serialization::VERSION_MAJOR, - serialization::VERSION_MINOR); + code = stable_hash_combine(code, serialization::VERSION_MAJOR, + serialization::VERSION_MINOR); // Extend the signature with the language options -#define LANGOPT(Name, Bits, Default, Description) \ - code = hash_combine(code, LangOpts->Name); -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - code = hash_combine(code, static_cast(LangOpts->get##Name())); +#define LANGOPT(Name, Bits, Default, Description) \ + code = stable_hash_combine(code, LangOpts->Name); +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + code = \ + stable_hash_combine(code, static_cast(LangOpts->get##Name())); #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" for (StringRef Feature : LangOpts->ModuleFeatures) - code = hash_combine(code, Feature); + code = stable_hash_combine(code, Feature); - code = hash_combine(code, LangOpts->ObjCRuntime); + code = stable_hash_combine(code, LangOpts->ObjCRuntime); const auto &BCN = LangOpts->CommentOpts.BlockCommandNames; - code = hash_combine(code, hash_combine_range(BCN.begin(), BCN.end())); + code = stable_hash_combine(code, + stable_hash_combine_range(BCN.begin(), BCN.end())); // Extend the signature with the target options. - code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, - TargetOpts->TuneCPU, TargetOpts->ABI); + code = stable_hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, + TargetOpts->TuneCPU, TargetOpts->ABI); for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten) - code = hash_combine(code, FeatureAsWritten); + code = stable_hash_combine(code, FeatureAsWritten); // Extend the signature with preprocessor options. const PreprocessorOptions &ppOpts = getPreprocessorOpts(); const HeaderSearchOptions &hsOpts = getHeaderSearchOpts(); - code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord); + code = stable_hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord); for (const auto &I : getPreprocessorOpts().Macros) { // If we're supposed to ignore this macro for the purposes of modules, @@ -4517,40 +4519,37 @@ continue; } - code = hash_combine(code, I.first, I.second); + code = stable_hash_combine(code, I.first, I.second); } // Extend the signature with the sysroot and other header search options. - code = hash_combine(code, hsOpts.Sysroot, - hsOpts.ModuleFormat, - hsOpts.UseDebugInfo, - hsOpts.UseBuiltinIncludes, - hsOpts.UseStandardSystemIncludes, - hsOpts.UseStandardCXXIncludes, - hsOpts.UseLibcxx, - hsOpts.ModulesValidateDiagnosticOptions); - code = hash_combine(code, hsOpts.ResourceDir); + code = stable_hash_combine(code, hsOpts.Sysroot, hsOpts.ModuleFormat, + hsOpts.UseDebugInfo, hsOpts.UseBuiltinIncludes, + hsOpts.UseStandardSystemIncludes, + hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx, + hsOpts.ModulesValidateDiagnosticOptions); + code = stable_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); + stable_hash_code SHPC = stable_hash_combine_range( + hsOpts.SystemHeaderPrefixes.begin(), hsOpts.SystemHeaderPrefixes.end()); + stable_hash_code UEC = stable_hash_combine_range(hsOpts.UserEntries.begin(), + hsOpts.UserEntries.end()); + code = stable_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 +#define DIAGOPT(Name, Bits, Default) \ + code = stable_hash_combine(code, diagOpts.Name); +#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ + code = stable_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); + code = stable_hash_combine(code, hsOpts.ModuleUserBuildPath); // Extend the signature with the module file extensions. const FrontendOptions &frontendOpts = getFrontendOpts(); @@ -4562,14 +4561,14 @@ // affects the debug info in the PCM. if (getCodeGenOpts().DebugTypeExtRefs) for (const auto &KeyValue : getCodeGenOpts().DebugPrefixMap) - code = hash_combine(code, KeyValue.first, KeyValue.second); + code = stable_hash_combine(code, KeyValue.first, KeyValue.second); // Extend the signature with the enabled sanitizers, if at least one is // enabled. Sanitizers which cannot affect AST generation aren't hashed. SanitizerSet SanHash = LangOpts->Sanitize; SanHash.clear(getPPTransparentSanitizers()); if (!SanHash.empty()) - code = hash_combine(code, SanHash.Mask); + code = stable_hash_combine(code, SanHash.Mask); return llvm::APInt(64, code).toString(36, /*Signed=*/false); } diff --git a/clang/lib/Frontend/TestModuleFileExtension.h b/clang/lib/Frontend/TestModuleFileExtension.h --- a/clang/lib/Frontend/TestModuleFileExtension.h +++ b/clang/lib/Frontend/TestModuleFileExtension.h @@ -55,7 +55,8 @@ ModuleFileExtensionMetadata getExtensionMetadata() const override; - llvm::hash_code hashExtension(llvm::hash_code Code) const override; + llvm::stable_hash_code + hashExtension(llvm::stable_hash_code Code) const override; std::unique_ptr createExtensionWriter(ASTWriter &Writer) override; diff --git a/clang/lib/Frontend/TestModuleFileExtension.cpp b/clang/lib/Frontend/TestModuleFileExtension.cpp --- a/clang/lib/Frontend/TestModuleFileExtension.cpp +++ b/clang/lib/Frontend/TestModuleFileExtension.cpp @@ -93,13 +93,13 @@ return { BlockName, MajorVersion, MinorVersion, UserInfo }; } -llvm::hash_code TestModuleFileExtension::hashExtension( - llvm::hash_code Code) const { +llvm::stable_hash_code +TestModuleFileExtension::hashExtension(llvm::stable_hash_code Code) const { if (Hashed) { - Code = llvm::hash_combine(Code, BlockName); - Code = llvm::hash_combine(Code, MajorVersion); - Code = llvm::hash_combine(Code, MinorVersion); - Code = llvm::hash_combine(Code, UserInfo); + Code = llvm::stable_hash_combine(Code, BlockName); + Code = llvm::stable_hash_combine(Code, MajorVersion); + Code = llvm::stable_hash_combine(Code, MinorVersion); + Code = llvm::stable_hash_combine(Code, UserInfo); } return Code; diff --git a/clang/lib/Serialization/ModuleFileExtension.cpp b/clang/lib/Serialization/ModuleFileExtension.cpp --- a/clang/lib/Serialization/ModuleFileExtension.cpp +++ b/clang/lib/Serialization/ModuleFileExtension.cpp @@ -13,7 +13,8 @@ ModuleFileExtension::~ModuleFileExtension() { } -llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const { +llvm::stable_hash_code +ModuleFileExtension::hashExtension(llvm::stable_hash_code Code) const { return Code; } diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -860,7 +860,8 @@ return {}; }; - llvm::hash_code hashExtension(llvm::hash_code Code) const override { + llvm::stable_hash_code + hashExtension(llvm::stable_hash_code Code) const override { return {}; } diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h --- a/llvm/include/llvm/ADT/StringRef.h +++ b/llvm/include/llvm/ADT/StringRef.h @@ -925,6 +925,10 @@ LLVM_NODISCARD hash_code hash_value(StringRef S); + /// Compute a hash_code for a StringRef. + LLVM_NODISCARD + stable_hash_code stable_hash_value(StringRef S); + } // end namespace llvm #endif // LLVM_ADT_STRINGREF_H diff --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h --- a/llvm/include/llvm/Support/VersionTuple.h +++ b/llvm/include/llvm/Support/VersionTuple.h @@ -149,6 +149,10 @@ return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build); } + friend llvm::stable_hash_code stable_hash_value(const VersionTuple &VT) { + return llvm::stable_hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build); + } + /// Retrieve a string representation of the version number. std::string getAsString() const; diff --git a/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp --- a/llvm/lib/Support/StringRef.cpp +++ b/llvm/lib/Support/StringRef.cpp @@ -600,3 +600,7 @@ hash_code llvm::hash_value(StringRef S) { return hash_combine_range(S.begin(), S.end()); } + +stable_hash_code llvm::stable_hash_value(StringRef S) { + return stable_hash_combine_range(S.begin(), S.end()); +}