summaryrefslogtreecommitdiffstats
path: root/clang/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-02-20 23:58:07 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-02-20 23:58:07 +0000
commit969fdfddd2bccc939bf0c77d2c381231e5dc3b78 (patch)
tree963c89d30fba05d8c4ec3de05cb904a108faea32 /clang/lib/Basic/SourceManager.cpp
parent519561f418c77dcf46fd6d96d25d884fa07fd7da (diff)
downloadbcm5719-llvm-969fdfddd2bccc939bf0c77d2c381231e5dc3b78.tar.gz
bcm5719-llvm-969fdfddd2bccc939bf0c77d2c381231e5dc3b78.zip
[PCH] Recover gracefully if the ASTReader detects that a file is different
from the one stored in the PCH/AST, while trying to load a SLocEntry. We verify that all files of the PCH did not change before loading it but this is not enough because: - The AST may have been 1) kept around, 2) to do queries on it. - We may have 1) verified the PCH and 2) started parsing. Between 1) and 2) files may change and we are going to have crashes because the rest of clang cannot deal with the ASTReader failing to read a SLocEntry. Handle this by recovering gracefully in such a case, by initializing the SLocEntry with the info from the PCH/AST as well as reporting failure by the ASTReader. rdar://10888929 llvm-svn: 151004
Diffstat (limited to 'clang/lib/Basic/SourceManager.cpp')
-rw-r--r--clang/lib/Basic/SourceManager.cpp35
1 files changed, 34 insertions, 1 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index 61f4e866524..a2540bc18af 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -370,7 +370,8 @@ LineTableInfo &SourceManager::getLineTable() {
SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr)
: Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true),
ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
- NumBinaryProbes(0), FakeBufferForRecovery(0) {
+ NumBinaryProbes(0), FakeBufferForRecovery(0),
+ FakeContentCacheForRecovery(0) {
clearIDTables();
Diag.setSourceManager(this);
}
@@ -396,6 +397,7 @@ SourceManager::~SourceManager() {
}
delete FakeBufferForRecovery;
+ delete FakeContentCacheForRecovery;
for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator
I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) {
@@ -469,6 +471,25 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
return Entry;
}
+const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
+ bool *Invalid) const {
+ assert(!SLocEntryLoaded[Index]);
+ if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
+ if (Invalid)
+ *Invalid = true;
+ // If the file of the SLocEntry changed we could still have loaded it.
+ if (!SLocEntryLoaded[Index]) {
+ // Try to recover; create a SLocEntry so the rest of clang can handle it.
+ LoadedSLocEntryTable[Index] = SLocEntry::get(0,
+ FileInfo::get(SourceLocation(),
+ getFakeContentCacheForRecovery(),
+ SrcMgr::C_User));
+ }
+ }
+
+ return LoadedSLocEntryTable[Index];
+}
+
std::pair<int, unsigned>
SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
unsigned TotalSize) {
@@ -491,6 +512,18 @@ const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
return FakeBufferForRecovery;
}
+/// \brief As part of recovering from missing or changed content, produce a
+/// fake content cache.
+const SrcMgr::ContentCache *
+SourceManager::getFakeContentCacheForRecovery() const {
+ if (!FakeContentCacheForRecovery) {
+ FakeContentCacheForRecovery = new ContentCache();
+ FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
+ /*DoNotFree=*/true);
+ }
+ return FakeContentCacheForRecovery;
+}
+
//===----------------------------------------------------------------------===//
// Methods to create new FileID's and macro expansions.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud