arames updated this revision to Diff 349141.
arames added a comment.

Fix detail namespace.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102943/new/

https://reviews.llvm.org/D102943

Files:
  clang/include/clang/Basic/ObjCRuntime.h
  clang/include/clang/Basic/Sanitizers.h
  clang/include/clang/Lex/HeaderSearchOptions.h
  clang/include/clang/Serialization/ModuleFileExtension.h
  clang/include/clang/Serialization/ModuleHash.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/TestModuleFileExtension.cpp
  clang/lib/Frontend/TestModuleFileExtension.h
  clang/lib/Serialization/ModuleFileExtension.cpp
  clang/unittests/Frontend/CompilerInvocationTest.cpp
  llvm/include/llvm/Support/VersionTuple.h

Index: llvm/include/llvm/Support/VersionTuple.h
===================================================================
--- llvm/include/llvm/Support/VersionTuple.h
+++ llvm/include/llvm/Support/VersionTuple.h
@@ -161,5 +161,10 @@
 /// Print a version number.
 raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
 
+template <typename HashT> void updateHash(HashT &Hash, const VersionTuple &V) {
+  Hash.update({V.getMajor(), V.getMinor().getValueOr(0),
+               V.getSubminor().getValueOr(0), V.getBuild().getValueOr(0)});
+}
+
 } // end namespace llvm
 #endif // LLVM_SUPPORT_VERSIONTUPLE_H
Index: clang/unittests/Frontend/CompilerInvocationTest.cpp
===================================================================
--- clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -860,9 +860,7 @@
     return {};
   };
 
-  llvm::hash_code hashExtension(llvm::hash_code Code) const override {
-    return {};
-  }
+  void hashExtension(ModuleHash &Hash) const override {}
 
   std::unique_ptr<ModuleFileExtensionWriter>
   createExtensionWriter(ASTWriter &Writer) override {
Index: clang/lib/Serialization/ModuleFileExtension.cpp
===================================================================
--- clang/lib/Serialization/ModuleFileExtension.cpp
+++ clang/lib/Serialization/ModuleFileExtension.cpp
@@ -13,10 +13,6 @@
 
 ModuleFileExtension::~ModuleFileExtension() { }
 
-llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const {
-  return Code;
-}
-
 ModuleFileExtensionWriter::~ModuleFileExtensionWriter() { }
 
 ModuleFileExtensionReader::~ModuleFileExtensionReader() { }
Index: clang/lib/Frontend/TestModuleFileExtension.h
===================================================================
--- clang/lib/Frontend/TestModuleFileExtension.h
+++ clang/lib/Frontend/TestModuleFileExtension.h
@@ -55,7 +55,7 @@
 
   ModuleFileExtensionMetadata getExtensionMetadata() const override;
 
-  llvm::hash_code hashExtension(llvm::hash_code Code) const override;
+  void hashExtension(ModuleHash &Hash) const override;
 
   std::unique_ptr<ModuleFileExtensionWriter>
   createExtensionWriter(ASTWriter &Writer) override;
Index: clang/lib/Frontend/TestModuleFileExtension.cpp
===================================================================
--- clang/lib/Frontend/TestModuleFileExtension.cpp
+++ clang/lib/Frontend/TestModuleFileExtension.cpp
@@ -93,16 +93,13 @@
   return { BlockName, MajorVersion, MinorVersion, UserInfo };
 }
 
-llvm::hash_code TestModuleFileExtension::hashExtension(
-                  llvm::hash_code Code) const {
+void TestModuleFileExtension::hashExtension(ModuleHash &Hash) 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);
+    Hash.update(BlockName);
+    Hash.update(MajorVersion);
+    Hash.update(MinorVersion);
+    Hash.update(UserInfo);
   }
-
-  return Code;
 }
 
 std::unique_ptr<ModuleFileExtensionWriter>
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -45,13 +45,13 @@
 #include "clang/Sema/CodeCompleteOptions.h"
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/ModuleFileExtension.h"
+#include "clang/Serialization/ModuleHash.h"
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
@@ -4474,47 +4474,43 @@
 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;
+  ModuleHash Hash;
 
   // 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());
+  Hash.update(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);
+  Hash.update({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<unsigned>(LangOpts->get##Name()));
+#define LANGOPT(Name, Bits, Default, Description) Hash.update(LangOpts->Name);
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)                   \
+  Hash.update(static_cast<unsigned>(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);
+    Hash.update(Feature);
 
-  code = hash_combine(code, LangOpts->ObjCRuntime);
+  Hash.update(LangOpts->ObjCRuntime);
   const auto &BCN = LangOpts->CommentOpts.BlockCommandNames;
-  code = hash_combine(code, hash_combine_range(BCN.begin(), BCN.end()));
+  Hash.updateRange(BCN.begin(), BCN.end());
 
   // Extend the signature with the target options.
-  code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
-                      TargetOpts->TuneCPU, TargetOpts->ABI);
+  Hash.update(TargetOpts->Triple);
+  Hash.update(TargetOpts->CPU);
+  Hash.update(TargetOpts->TuneCPU);
+  Hash.update(TargetOpts->ABI);
   for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten)
-    code = hash_combine(code, FeatureAsWritten);
+    Hash.update(FeatureAsWritten);
 
   // Extend the signature with preprocessor options.
   const PreprocessorOptions &ppOpts = getPreprocessorOpts();
   const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
-  code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
+  Hash.update(ppOpts.UsePredefines);
+  Hash.update(ppOpts.DetailedRecord);
 
   for (const auto &I : getPreprocessorOpts().Macros) {
     // If we're supposed to ignore this macro for the purposes of modules,
@@ -4527,61 +4523,61 @@
         continue;
     }
 
-    code = hash_combine(code, I.first, I.second);
+    Hash.update(I.first);
+    Hash.update(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);
+  Hash.update(hsOpts.Sysroot);
+  Hash.update(hsOpts.ModuleFormat);
+  Hash.update(hsOpts.UseDebugInfo);
+  Hash.update(hsOpts.UseBuiltinIncludes);
+  Hash.update(hsOpts.UseStandardSystemIncludes);
+  Hash.update(hsOpts.UseStandardCXXIncludes);
+  Hash.update(hsOpts.UseLibcxx);
+  Hash.update(hsOpts.ModulesValidateDiagnosticOptions);
+  Hash.update(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);
+    Hash.update(hsOpts.SystemHeaderPrefixes.size());
+    Hash.updateRange(hsOpts.SystemHeaderPrefixes.begin(),
+                     hsOpts.SystemHeaderPrefixes.end());
+    Hash.update(hsOpts.UserEntries.size());
+    Hash.updateRange(hsOpts.UserEntries.begin(), hsOpts.UserEntries.end());
 
     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) Hash.update(diagOpts.Name);
+#define ENUM_DIAGOPT(Name, Type, Bits, Default)                                \
+  Hash.update(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);
+  Hash.update(hsOpts.ModuleUserBuildPath);
 
   // Extend the signature with the module file extensions.
   const FrontendOptions &frontendOpts = getFrontendOpts();
-  for (const auto &ext : frontendOpts.ModuleFileExtensions) {
-    code = ext->hashExtension(code);
-  }
+  for (const auto &ext : frontendOpts.ModuleFileExtensions)
+    ext->hashExtension(Hash);
 
   // When compiling with -gmodules, also hash -fdebug-prefix-map as it
   // affects the debug info in the PCM.
   if (getCodeGenOpts().DebugTypeExtRefs)
-    for (const auto &KeyValue : getCodeGenOpts().DebugPrefixMap)
-      code = hash_combine(code, KeyValue.first, KeyValue.second);
+    for (const auto &KeyValue : getCodeGenOpts().DebugPrefixMap) {
+      Hash.update(KeyValue.first);
+      Hash.update(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);
+    Hash.update(SanHash.Mask);
 
-  return llvm::APInt(64, code).toString(36, /*Signed=*/false);
+  return llvm::APInt(64, Hash.getValue()).toString(36, /*Signed=*/false);
 }
 
 void CompilerInvocation::generateCC1CommandLine(
Index: clang/include/clang/Serialization/ModuleHash.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/ModuleHash.h
@@ -0,0 +1,123 @@
+//===-- ModuleHash.h - Module Hash ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULEHASH_H
+#define LLVM_CLANG_SERIALIZATION_MODULEHASH_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MD5.h"
+#include <string>
+
+namespace module_hash {
+namespace detail {
+/// Wrapper interface around a hash type.
+/// The only methods expected from the hash type are:
+/// * a default constructor
+/// * void update(llvm::ArrayRef<uint8_t>)
+///
+/// Various types are forwarded to the canonical version of
+/// `HashValueT::update(llvm::ArrayRef<uint8_t>)`. Types requiring particular
+/// hashing behavior can specify it in a similar way to `llvm::hash_code`, by
+/// declaring
+///
+/// ```
+/// template <typename HashT>
+/// void updateHash(HashT &Hash, const ValueType &Value) {
+///   Hash.update(Value.member1);
+///   Hash.update(Value.member2);
+/// }
+/// ```
+template <typename HashValueT> class Hash {
+private:
+  template <typename T, typename E = void> struct update_impl {
+    update_impl(Hash &H, T Value) { updateHash(H, Value); }
+  };
+
+public:
+  HashValueT HashValue;
+
+  template <typename T> void update(T Value) { update_impl<T>(*this, Value); }
+
+  template <typename InputIteratorT>
+  void updateRange(InputIteratorT first, InputIteratorT last) {
+    for (auto It = first; It != last; ++It)
+      update(*It);
+  }
+
+private:
+  template <typename T>
+  struct is_hashable_data
+      : std::integral_constant<bool, llvm::is_integral_or_enum<T>::value ||
+                                         std::is_pointer<T>::value> {};
+
+public:
+  template <typename T>
+  typename std::enable_if<is_hashable_data<T>::value>::type
+  update(const std::initializer_list<T> &Value) {
+    update(llvm::ArrayRef<T>(Value.begin(), Value.size()));
+  }
+
+private:
+  // `void HashValueT::update(llvm::ArrayRef<uint8_t>)` is the canonical
+  // expected method to update the hash.
+  template <> struct update_impl<llvm::ArrayRef<uint8_t>> {
+    update_impl(Hash &H, llvm::ArrayRef<uint8_t> Value) {
+      H.HashValue.update(Value);
+    }
+  };
+
+  // Plain hashable data is forwarded to `llvm::ArrayRef<uint8_t>`.
+  template <typename T>
+  struct update_impl<T,
+                     typename std::enable_if<is_hashable_data<T>::value>::type>
+      : update_impl<llvm::ArrayRef<uint8_t>> {
+    update_impl(Hash &H, T value)
+        : update_impl<llvm::ArrayRef<uint8_t>>(
+              H, llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(&value),
+                                         sizeof(value))) {}
+  };
+
+  // Forward `llvm::ArrayRef<T>` to `llvm::ArrayRef<uint8_t>`.
+  template <typename T>
+  struct update_impl<llvm::ArrayRef<T>> : update_impl<llvm::ArrayRef<uint8_t>> {
+    update_impl(Hash &H, llvm::ArrayRef<T> Value)
+        : update_impl<llvm::ArrayRef<uint8_t>>(
+              H, llvm::ArrayRef<uint8_t>(
+                     reinterpret_cast<const uint8_t *>(Value.data()),
+                     Value.size() * sizeof(T))) {}
+  };
+
+  // Forward `llvm::StringRef` to `llvm::ArrayRef<uint8_t>`.
+  template <>
+  struct update_impl<llvm::StringRef> : update_impl<llvm::ArrayRef<uint8_t>> {
+    update_impl(Hash &H, llvm::StringRef Value)
+        : update_impl<llvm::ArrayRef<uint8_t>>(
+              H, llvm::ArrayRef<uint8_t>(
+                     reinterpret_cast<const uint8_t *>(Value.data()),
+                     Value.size())) {}
+  };
+
+  // Forward `std::string` to `llvm::StringRef`.
+  template <> struct update_impl<std::string> : update_impl<llvm::StringRef> {
+    update_impl(Hash &H, std::string Value)
+        : update_impl<llvm::StringRef>(H, Value) {}
+  };
+};
+} // namespace detail
+} // namespace module_hash
+
+struct ModuleHash : public module_hash::detail::Hash<llvm::MD5> {
+  uint64_t getValue() {
+    llvm::MD5::MD5Result HashResult;
+    HashValue.final(HashResult);
+    return HashResult.low();
+  }
+};
+
+#endif // LLVM_CLANG_FRONTEND_MODULEHASH_H
Index: clang/include/clang/Serialization/ModuleFileExtension.h
===================================================================
--- clang/include/clang/Serialization/ModuleFileExtension.h
+++ clang/include/clang/Serialization/ModuleFileExtension.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
 #define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
 
+#include "clang/Serialization/ModuleHash.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/Support/ExtensibleRTTI.h"
 #include <memory>
@@ -74,19 +75,19 @@
   virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0;
 
   /// Hash information about the presence of this extension into the
-  /// module hash code.
+  /// module hash.
   ///
-  /// The module hash code is used to distinguish different variants
+  /// The module hash is used to distinguish different variants
   /// of a module that are incompatible. If the presence, absence, or
   /// version of the module file extension should force the creation
   /// of a separate set of module files, override this method to
   /// combine that distinguishing information into the module hash
   /// code.
   ///
-  /// 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;
+  /// The default implementation of this function does not update the hash in
+  /// any way. So the presence/absence of this extension does not distinguish
+  /// module files.
+  virtual void hashExtension(ModuleHash &Hash) const {}
 
   /// Create a new module file extension writer, which will be
   /// responsible for writing the extension contents into a particular
Index: clang/include/clang/Lex/HeaderSearchOptions.h
===================================================================
--- clang/include/clang/Lex/HeaderSearchOptions.h
+++ clang/include/clang/Lex/HeaderSearchOptions.h
@@ -256,11 +256,25 @@
   return llvm::hash_combine(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
 }
 
+template <typename HashT>
+void updateHash(HashT &Hash, const HeaderSearchOptions::Entry &E) {
+  Hash.update(E.Path);
+  Hash.update(E.Group);
+  Hash.update(E.IsFramework);
+  Hash.update(E.IgnoreSysRoot);
+}
+
 inline llvm::hash_code
 hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
   return llvm::hash_combine(SHP.Prefix, SHP.IsSystemHeader);
 }
 
+template <typename HashT>
+void updateHash(HashT &Hash,
+                const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
+  Hash.update(SHP.Prefix);
+  Hash.update(SHP.IsSystemHeader);
+}
 } // namespace clang
 
 #endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
Index: clang/include/clang/Basic/Sanitizers.h
===================================================================
--- clang/include/clang/Basic/Sanitizers.h
+++ clang/include/clang/Basic/Sanitizers.h
@@ -78,6 +78,10 @@
 
   llvm::hash_code hash_value() const;
 
+  template <typename HashT> void updateHash(HashT &Hash) const {
+    Hash.updateRange(&maskLoToHigh[0], &maskLoToHigh[0] + kNumElem);
+  }
+
   constexpr explicit operator bool() const {
     return maskLoToHigh[0] || maskLoToHigh[1];
   }
@@ -124,6 +128,10 @@
 
 // Declaring in clang namespace so that it can be found by ADL.
 llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
+template <typename HashT>
+void updateHash(HashT &Hash, const clang::SanitizerMask &Arg) {
+  Arg.updateHash(Hash);
+}
 
 // Define the set of sanitizer kinds, as well as the set of sanitizers each
 // sanitizer group expands into.
Index: clang/include/clang/Basic/ObjCRuntime.h
===================================================================
--- clang/include/clang/Basic/ObjCRuntime.h
+++ clang/include/clang/Basic/ObjCRuntime.h
@@ -484,6 +484,10 @@
 
 raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
 
+template <typename HashT> void updateHash(HashT &Hash, const ObjCRuntime &OCR) {
+  Hash.update(OCR.getKind());
+  Hash.update(OCR.getVersion());
+}
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_OBJCRUNTIME_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to