diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2013-12-20 00:16:25 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2013-12-20 00:16:25 +0000 |
commit | 4765252dcb47cdb52b6078a46955e5bae2ecb64d (patch) | |
tree | 5b61ff9d2ecda33bcb3030dd0347b748b39f49f2 /clang/lib/Frontend/ASTUnit.cpp | |
parent | 86409e1cde6a329427d146a21e93104b7c278986 (diff) | |
download | bcm5719-llvm-4765252dcb47cdb52b6078a46955e5bae2ecb64d.tar.gz bcm5719-llvm-4765252dcb47cdb52b6078a46955e5bae2ecb64d.zip |
ASTUnit::getMainBufferWithPrecompiledPreamble: use MD5 hash of the remapped
files to tell if they were changed since the last time we have computed the
preamble
We used to check only the buffer size, so if the new remapped buffer has the
same size as the previous one, we would think that the buffer did not change,
and we did not rebuild the preambule, which sometimes caused us to crash.
llvm-svn: 197755
Diffstat (limited to 'clang/lib/Frontend/ASTUnit.cpp')
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 9862e2d87df..350ed73068f 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1359,6 +1359,36 @@ static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old, return Result; } +ASTUnit::PreambleFileHash +ASTUnit::PreambleFileHash::createForFile(off_t Size, time_t ModTime) { + PreambleFileHash Result; + Result.Size = Size; + Result.ModTime = ModTime; + memset(Result.MD5, 0, sizeof(Result.MD5[0]) * sizeof(Result.MD5)); + return Result; +} + +ASTUnit::PreambleFileHash ASTUnit::PreambleFileHash::createForMemoryBuffer( + const llvm::MemoryBuffer *Buffer) { + PreambleFileHash Result; + Result.Size = Buffer->getBufferSize(); + Result.ModTime = 0; + + llvm::MD5 MD5Ctx; + MD5Ctx.update(Buffer->getBuffer().data()); + MD5Ctx.final(Result.MD5); + + return Result; +} + +namespace clang { +bool operator==(const ASTUnit::PreambleFileHash &LHS, + const ASTUnit::PreambleFileHash &RHS) { + return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime && + memcmp(LHS.MD5, RHS.MD5, sizeof(LHS.MD5[0]) * sizeof(LHS.MD5)) == 0; +} +} // namespace clang + /// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing /// the source file. /// @@ -1428,7 +1458,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // First, make a record of those files that have been overridden via // remapping or unsaved_files. - llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles; + llvm::StringMap<PreambleFileHash> OverriddenFiles; for (PreprocessorOptions::remapped_file_iterator R = PreprocessorOpts.remapped_file_begin(), REnd = PreprocessorOpts.remapped_file_end(); @@ -1442,7 +1472,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( break; } - OverriddenFiles[R->first] = std::make_pair( + OverriddenFiles[R->first] = PreambleFileHash::createForFile( Status.getSize(), Status.getLastModificationTime().toEpochTime()); } for (PreprocessorOptions::remapped_file_buffer_iterator @@ -1452,16 +1482,16 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( ++R) { // FIXME: Should we actually compare the contents of file->buffer // remappings? - OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(), - 0); + OverriddenFiles[R->first] = + PreambleFileHash::createForMemoryBuffer(R->second); } // Check whether anything has changed. - for (llvm::StringMap<std::pair<off_t, time_t> >::iterator + for (llvm::StringMap<PreambleFileHash>::iterator F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end(); !AnyFileChanged && F != FEnd; ++F) { - llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden + llvm::StringMap<PreambleFileHash>::iterator Overridden = OverriddenFiles.find(F->first()); if (Overridden != OverriddenFiles.end()) { // This file was remapped; check whether the newly-mapped file @@ -1476,9 +1506,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( if (FileMgr->getNoncachedStatValue(F->first(), Status)) { // If we can't stat the file, assume that something horrible happened. AnyFileChanged = true; - } else if (Status.getSize() != uint64_t(F->second.first) || + } else if (Status.getSize() != uint64_t(F->second.Size) || Status.getLastModificationTime().toEpochTime() != - uint64_t(F->second.second)) + uint64_t(F->second.ModTime)) AnyFileChanged = true; } @@ -1678,11 +1708,20 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( F != FEnd; ++F) { const FileEntry *File = F->second->OrigEntry; - if (!File || F->second->getRawBuffer() == MainFileBuffer) + if (!File) continue; - - FilesInPreamble[File->getName()] - = std::make_pair(F->second->getSize(), File->getModificationTime()); + const llvm::MemoryBuffer *Buffer = F->second->getRawBuffer(); + if (Buffer == MainFileBuffer) + continue; + + if (time_t ModTime = File->getModificationTime()) { + FilesInPreamble[File->getName()] = PreambleFileHash::createForFile( + F->second->getSize(), ModTime); + } else { + assert(F->second->getSize() == Buffer->getBufferSize()); + FilesInPreamble[File->getName()] = + PreambleFileHash::createForMemoryBuffer(Buffer); + } } PreambleRebuildCounter = 1; |