diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-06 18:12:47 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-06 18:12:47 +0000 |
commit | ed3802e5da6e7d41975b1cb3d7ae3a3b9e855d10 (patch) | |
tree | 71690b8e28318bae5160be0f3b7f2cd765638e61 /lib/Serialization/ASTWriter.cpp | |
parent | 36592b1fa381a978b1b6d4b97c66fb274915fe50 (diff) |
[PCH] For HeaderFileInfoTrait, hash the key using size & time of the file.
Previously the hash would be the filename portion of the path, which could be
different for a filename with different case or a symbolic link with a different
name completely.
This did not actually create any issue so far because by validating all headers
in the PCH we created uniqued FileEntries based on inodes, so an #include of
a symbolic link (refering to a file from the PCH) would end up with a FileEntry
with filename same as the one recorded in the PCH.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176566 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index acb0459177..31af7626a8 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -42,6 +42,7 @@ #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/FileSystem.h" @@ -1372,32 +1373,38 @@ namespace { HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) { } - typedef const char *key_type; - typedef key_type key_type_ref; + struct key_type { + const FileEntry *FE; + const char *Filename; + }; + typedef const key_type &key_type_ref; typedef HeaderFileInfo data_type; typedef const data_type &data_type_ref; - static unsigned ComputeHash(const char *path) { - // The hash is based only on the filename portion of the key, so that the - // reader can match based on filenames when symlinking or excess path - // elements ("foo/../", "../") change the form of the name. However, - // complete path is still the key. - return llvm::HashString(llvm::sys::path::filename(path)); + static unsigned ComputeHash(key_type_ref key) { + // The hash is based only on size/time of the file, so that the reader can + // match even when symlinking or excess path elements ("foo/../", "../") + // change the form of the name. However, complete path is still the key. + return llvm::hash_combine(key.FE->getSize(), + key.FE->getModificationTime()); } std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, const char *path, - data_type_ref Data) { - unsigned StrLen = strlen(path); - clang::io::Emit16(Out, StrLen); + EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { + unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8; + clang::io::Emit16(Out, KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; clang::io::Emit8(Out, DataLen); - return std::make_pair(StrLen + 1, DataLen); + return std::make_pair(KeyLen, DataLen); } - void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { - Out.write(path, KeyLen); + void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { + clang::io::Emit64(Out, key.FE->getSize()); + KeyLen -= 8; + clang::io::Emit64(Out, key.FE->getModificationTime()); + KeyLen -= 8; + Out.write(key.Filename, KeyLen); } void EmitData(raw_ostream &Out, key_type_ref, @@ -1479,7 +1486,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { SavedStrings.push_back(Filename); } - Generator.insert(Filename, HFI, GeneratorTrait); + HeaderFileInfoTrait::key_type key = { File, Filename }; + Generator.insert(key, HFI, GeneratorTrait); ++NumHeaderSearchEntries; } |