summaryrefslogtreecommitdiffstats
path: root/clang/lib/Frontend
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-08-03 17:30:10 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-08-03 17:30:10 +0000
commit839bbacfb2e1b862f0297d8e24c60da4f9e77319 (patch)
tree2337040efc3f51784556a34ae7d0cdbd05e88af0 /clang/lib/Frontend
parenta6430cfe4830787f366e6b46744d8327d659968c (diff)
downloadbcm5719-llvm-839bbacfb2e1b862f0297d8e24c60da4f9e77319.tar.gz
bcm5719-llvm-839bbacfb2e1b862f0297d8e24c60da4f9e77319.zip
Apart from storing/retrieving the previous redeclaration from PCH, also store/retrieve the most recent
redeclaration. That way we are sure that the full redeclarations chain is loaded. When using chained PCHs, first declarations point to the most recent redeclarations in the same PCH. To address this use a REDECLS_UPDATE_LATEST record block to keep track of which first declarations need to point to a most recent redeclaration in another PCH. llvm-svn: 110125
Diffstat (limited to 'clang/lib/Frontend')
-rw-r--r--clang/lib/Frontend/PCHReader.cpp16
-rw-r--r--clang/lib/Frontend/PCHReaderDecl.cpp91
-rw-r--r--clang/lib/Frontend/PCHWriter.cpp13
-rw-r--r--clang/lib/Frontend/PCHWriterDecl.cpp42
4 files changed, 144 insertions, 18 deletions
diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp
index b415f8dea54..35909a05556 100644
--- a/clang/lib/Frontend/PCHReader.cpp
+++ b/clang/lib/Frontend/PCHReader.cpp
@@ -1557,6 +1557,18 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
break;
}
+ case pch::REDECLS_UPDATE_LATEST: {
+ assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
+ for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
+ pch::DeclID First = Record[i], Latest = Record[i+1];
+ assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
+ Latest > FirstLatestDeclIDs[First]) &&
+ "The new latest is supposed to come after the previous latest");
+ FirstLatestDeclIDs[First] = Latest;
+ }
+ break;
+ }
+
case pch::LANGUAGE_OPTIONS:
if (ParseLanguageOptions(Record) && !DisableValidation)
return IgnorePCH;
@@ -2868,7 +2880,7 @@ Decl *PCHReader::GetExternalDecl(uint32_t ID) {
TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() {
if (!DeclsLoaded[0]) {
- ReadDeclRecord(0);
+ ReadDeclRecord(0, 0);
if (DeserializationListener)
DeserializationListener->DeclRead(1, DeclsLoaded[0]);
}
@@ -2887,7 +2899,7 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) {
unsigned Index = ID - 1;
if (!DeclsLoaded[Index]) {
- ReadDeclRecord(Index);
+ ReadDeclRecord(Index, ID);
if (DeserializationListener)
DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
}
diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp
index e9428cc0b4b..21beb42e93e 100644
--- a/clang/lib/Frontend/PCHReaderDecl.cpp
+++ b/clang/lib/Frontend/PCHReaderDecl.cpp
@@ -31,6 +31,7 @@ namespace clang {
class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
PCHReader &Reader;
llvm::BitstreamCursor &Cursor;
+ const pch::DeclID ThisDeclID;
const PCHReader::RecordData &Record;
unsigned &Idx;
pch::TypeID TypeIDForTypeDecl;
@@ -39,9 +40,10 @@ namespace clang {
public:
PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
- const PCHReader::RecordData &Record, unsigned &Idx)
- : Reader(Reader), Cursor(Cursor), Record(Record), Idx(Idx),
- TypeIDForTypeDecl(0) { }
+ pch::DeclID thisDeclID, const PCHReader::RecordData &Record,
+ unsigned &Idx)
+ : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
+ Idx(Idx), TypeIDForTypeDecl(0) { }
void Visit(Decl *D);
@@ -93,6 +95,7 @@ namespace clang {
void VisitBlockDecl(BlockDecl *BD);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
@@ -178,8 +181,7 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
VisitTypeDecl(TD);
TD->IdentifierNamespace = Record[Idx++];
- TD->setPreviousDeclaration(
- cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++])));
+ VisitRedeclarable(TD);
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
TD->setDefinition(Record[Idx++]);
TD->setEmbeddedInDeclarator(Record[Idx++]);
@@ -305,10 +307,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// FunctionDecl's body is handled last at PCHReaderDecl::Visit,
// after everything else is read.
- // Avoid side effects and invariant checking of FunctionDecl's
- // setPreviousDeclaration.
- FD->redeclarable_base::setPreviousDeclaration(
- cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+ VisitRedeclarable(FD);
FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]);
FD->setInlineSpecified(Record[Idx++]);
@@ -550,8 +549,7 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
VD->setDeclaredInCondition(Record[Idx++]);
VD->setExceptionVariable(Record[Idx++]);
VD->setNRVOVariable(Record[Idx++]);
- VD->setPreviousDeclaration(
- cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ VisitRedeclarable(VD);
if (Record[Idx++])
VD->setInit(Reader.ReadExpr(Cursor));
@@ -918,6 +916,25 @@ void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
RedeclarableTemplateDecl *LatestDecl =
cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+
+ // This decl is a first one and the latest declaration that it points to is
+ // in the same PCH. However, if this actually needs to point to a
+ // redeclaration in another chained PCH, we need to update it by checking
+ // the FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
+ PCHReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ assert((LatestDecl->getLocation().isInvalid() ||
+ NewLatest->getLocation().isInvalid() ||
+ Reader.SourceMgr.isBeforeInTranslationUnit(
+ LatestDecl->getLocation(),
+ NewLatest->getLocation())) &&
+ "The new latest is supposed to come after the previous latest");
+ LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
+ }
+
assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
D->getCommonPtr()->Latest = LatestDecl;
}
@@ -1072,6 +1089,54 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) {
return std::make_pair(LexicalOffset, VisibleOffset);
}
+template <typename T>
+void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
+ enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ RedeclKind Kind = (RedeclKind)Record[Idx++];
+ switch (Kind) {
+ default:
+ assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed up"
+ " reading");
+ case NoRedeclaration:
+ break;
+ case PointsToPrevious:
+ D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
+ cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+ break;
+ case PointsToLatest:
+ D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
+ cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+ break;
+ }
+
+ assert(!(Kind == PointsToPrevious &&
+ Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
+ Reader.FirstLatestDeclIDs.end()) &&
+ "This decl is not first, it should not be in the map");
+ if (Kind == PointsToPrevious)
+ return;
+
+ // This decl is a first one and the latest declaration that it points to is in
+ // the same PCH. However, if this actually needs to point to a redeclaration
+ // in another chained PCH, we need to update it by checking the
+ // FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
+ "Invalid ThisDeclID ?");
+ PCHReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ assert((D->getMostRecentDeclaration()->getLocation().isInvalid() ||
+ NewLatest->getLocation().isInvalid() ||
+ Reader.SourceMgr.isBeforeInTranslationUnit(
+ D->getMostRecentDeclaration()->getLocation(),
+ NewLatest->getLocation())) &&
+ "The new latest is supposed to come after the previous latest");
+ D->RedeclLink
+ = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
+ }
+}
+
//===----------------------------------------------------------------------===//
// Attribute Reading
//===----------------------------------------------------------------------===//
@@ -1304,7 +1369,7 @@ PCHReader::RecordLocation PCHReader::DeclCursorForIndex(unsigned Index) {
}
/// \brief Read the declaration at the given offset from the PCH file.
-Decl *PCHReader::ReadDeclRecord(unsigned Index) {
+Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) {
RecordLocation Loc = DeclCursorForIndex(Index);
llvm::BitstreamCursor &DeclsCursor = *Loc.first;
// Keep track of where we are in the stream, then jump back there
@@ -1320,7 +1385,7 @@ Decl *PCHReader::ReadDeclRecord(unsigned Index) {
RecordData Record;
unsigned Code = DeclsCursor.ReadCode();
unsigned Idx = 0;
- PCHDeclReader Reader(*this, DeclsCursor, Record, Idx);
+ PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx);
Decl *D = 0;
switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp
index 75592a41c85..776a40940d7 100644
--- a/clang/lib/Frontend/PCHWriter.cpp
+++ b/clang/lib/Frontend/PCHWriter.cpp
@@ -2410,6 +2410,19 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteIdentifierTable(PP);
WriteTypeDeclOffsets();
+ /// Build a record containing first declarations from a chained PCH and the
+ /// most recent declarations in this PCH that they point to.
+ RecordData FirstLatestDeclIDs;
+ for (FirstLatestDeclMap::iterator
+ I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) {
+ assert(I->first->getPCHLevel() > I->second->getPCHLevel() &&
+ "Expected first & second to be in different PCHs");
+ AddDeclRef(I->first, FirstLatestDeclIDs);
+ AddDeclRef(I->second, FirstLatestDeclIDs);
+ }
+ if (!FirstLatestDeclIDs.empty())
+ Stream.EmitRecord(pch::REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
+
// Write the record containing external, unnamed definitions.
if (!ExternalDefinitions.empty())
Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp
index 28a82cd23f5..9e9835adb42 100644
--- a/clang/lib/Frontend/PCHWriterDecl.cpp
+++ b/clang/lib/Frontend/PCHWriterDecl.cpp
@@ -92,6 +92,7 @@ namespace clang {
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
uint64_t VisibleOffset);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
// FIXME: Put in the same order is DeclNodes.td?
@@ -163,7 +164,7 @@ void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
VisitTypeDecl(D);
Record.push_back(D->getIdentifierNamespace());
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
Record.push_back(D->isDefinition());
Record.push_back(D->isEmbeddedInDeclarator());
@@ -279,7 +280,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
// FunctionDecl's body is handled last at PCHWriterDecl::Visit,
// after everything else is written.
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isInlineSpecified());
@@ -500,7 +501,7 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->isDeclaredInCondition());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back(D->getInit() ? 1 : 0);
if (D->getInit())
Writer.AddStmt(D->getInit());
@@ -854,6 +855,18 @@ void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
Record.push_back(D->isMemberSpecialization());
Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
+ } else {
+ RedeclarableTemplateDecl *First = D->getFirstDeclaration();
+ assert(First != D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during PCH reading.
+ if (First->getMostRecentDeclaration() == D &&
+ First->getPCHLevel() > D->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = D;
+ }
}
}
@@ -1016,6 +1029,29 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
Record.push_back(VisibleOffset);
}
+template <typename T>
+void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
+ enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ if (D->RedeclLink.getNext() == D) {
+ Record.push_back(NoRedeclaration);
+ } else {
+ Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious
+ : PointsToLatest);
+ Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
+ }
+
+ T *First = D->getFirstDeclaration();
+ T *ThisDecl = static_cast<T*>(D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during PCH reading.
+ if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
+ First->getPCHLevel() > ThisDecl->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = ThisDecl;
+ }
+}
//===----------------------------------------------------------------------===//
// PCHWriter Implementation
OpenPOWER on IntegriCloud