From 7fd0849bc3a931f645c352add2bbff91e04ba8b9 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 5 Nov 2012 19:45:09 +0000 Subject: [PATCH] Hash the various compiler version, target, preprocessor, and header-search options into the module hash. We're just using ADT/Hashing.hpp for this, which isn't as cryptographically strong as I'd like, but it'll do. If someone contributes (say) and MD4 implementation, we'd happily switch to that. llvm-svn: 167397 --- clang/lib/Frontend/CompilerInvocation.cpp | 65 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 59133da..c6ede1b 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -11,6 +11,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/Version.h" #include "clang/Basic/FileManager.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Options.h" @@ -20,6 +21,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/LangStandard.h" #include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -1511,54 +1513,49 @@ llvm::APInt ModuleSignature::getAsInteger() const { } std::string CompilerInvocation::getModuleHash() const { - ModuleSignature Signature; - + using llvm::hash_code; + using llvm::hash_value; + using llvm::hash_combine; + // Start the signature with the compiler version. - // FIXME: The full version string can be quite long. Omit it from the - // module hash for now to avoid failures where the path name becomes too - // long. An MD5 or similar checksum would work well here. - // Signature.add(getClangFullRepositoryVersion()); - + // FIXME: We'd rather use something more cryptographically sound that + // CityHash, but this will do for now. + hash_code code = hash_value(getClangFullRepositoryVersion()); + // Extend the signature with the language options #define LANGOPT(Name, Bits, Default, Description) \ - Signature.add(LangOpts->Name, Bits); + code = hash_combine(code, LangOpts->Name); #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - Signature.add(static_cast(LangOpts->get##Name()), Bits); + code = 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" - // Extend the signature with the target triple - // FIXME: Add target options. - llvm::Triple T(TargetOpts->Triple); - Signature.add((unsigned)T.getArch(), 5); - Signature.add((unsigned)T.getVendor(), 4); - Signature.add((unsigned)T.getOS(), 5); - Signature.add((unsigned)T.getEnvironment(), 4); + // Extend the signature with the target options. + code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, + TargetOpts->ABI, TargetOpts->CXXABI, + TargetOpts->LinkerVersion); + for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i) + code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]); // Extend the signature with preprocessor options. - Signature.add(getPreprocessorOpts().UsePredefines, 1); - Signature.add(getPreprocessorOpts().DetailedRecord, 1); - - // Hash the preprocessor defines. - // FIXME: This is terrible. Use an MD5 sum of the preprocessor defines. + const PreprocessorOptions &ppOpts = getPreprocessorOpts(); + code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord); + std::vector MacroDefs; for (std::vector >::const_iterator I = getPreprocessorOpts().Macros.begin(), IEnd = getPreprocessorOpts().Macros.end(); I != IEnd; ++I) { - if (!I->second) - MacroDefs.push_back(I->first); + code = hash_combine(code, I->first, I->second); } - llvm::array_pod_sort(MacroDefs.begin(), MacroDefs.end()); - - unsigned PPHashResult = 0; - for (unsigned I = 0, N = MacroDefs.size(); I != N; ++I) - PPHashResult = llvm::HashString(MacroDefs[I], PPHashResult); - Signature.add(PPHashResult, 32); - - // We've generated the signature. Treat it as one large APInt that we'll - // encode in base-36 and return. - Signature.flush(); - return Signature.getAsInteger().toString(36, /*Signed=*/false); + + // Extend the signature with the sysroot. + const HeaderSearchOptions &hsOpts = getHeaderSearchOpts(); + code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes, + hsOpts.UseStandardSystemIncludes, + hsOpts.UseStandardCXXIncludes, + hsOpts.UseLibcxx); + + return llvm::APInt(64, code).toString(36, /*Signed=*/false); } -- 2.7.4