aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-12-19 19:00:47 +0000
committerDouglas Gregor <dgregor@apple.com>2011-12-19 19:00:47 +0000
commitfc529f7fcafe7da0b8a32621e13685891e8ce52a (patch)
treef2ddd830e7bbfe26fc1a5e900ef5755849433a71 /lib
parentf63b0a5f5445830a845895ee16f3affeaffd2e9d (diff)
Once we have fully deserialized a redeclaration chain for something
with a definition pointer (e.g., C++ and Objective-C classes), zip through the redeclaration chain to make sure that all of the declarations point to the definition data. As part of this, realized again why the first redeclaration of an entity in a file is important, and brought back that idea. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146886 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Serialization/ASTReader.cpp23
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp38
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp8
3 files changed, 54 insertions, 15 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fc49e88a50..2b417522bc 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -6095,6 +6095,29 @@ void ASTReader::finishPendingActions() {
}
PendingChainedObjCCategories.clear();
}
+
+ // If we deserialized any C++ or Objective-C class definitions, make sure
+ // that all redeclarations point to the definitions. Note that this can only
+ // happen now, after the redeclaration chains have been fully wired.
+ for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
+ DEnd = PendingDefinitions.end();
+ D != DEnd; ++D) {
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+ for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+ REnd = RD->redecls_end();
+ R != REnd; ++R)
+ cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+
+ continue;
+ }
+
+ ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(*D);
+ for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+ REnd = ID->redecls_end();
+ R != REnd; ++R)
+ R->Data = ID->Data;
+ }
+ PendingDefinitions.clear();
}
void ASTReader::FinishedDeserializing() {
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 35cd8478d5..bd6a5a5e06 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -630,6 +630,9 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
// pending references were linked.
Reader.PendingForwardRefs.erase(ID);
#endif
+
+ // Note that we have deserialized a definition.
+ Reader.PendingDefinitions.insert(ID);
}
} else if (Def) {
if (Def->Data) {
@@ -1030,6 +1033,9 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
Reader.PendingForwardRefs.erase(D);
#endif
}
+
+ // Note that we have deserialized a definition.
+ Reader.PendingDefinitions.insert(D);
} else if (DefinitionDecl) {
if (DefinitionDecl->DefinitionData) {
D->DefinitionData = DefinitionDecl->DefinitionData;
@@ -1162,7 +1168,7 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
// can be used while this is still initializing.
- enum RedeclKind { FirstDeclaration, PointsToPrevious };
+ enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
// Determine the first declaration ID.
@@ -1190,7 +1196,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
}
break;
}
-
+
+ case FirstInFile:
case PointsToPrevious: {
FirstDeclID = ReadDeclID(Record, Idx);
DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1204,9 +1211,13 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// loaded and attached later on.
D->CommonOrPrev = FirstDecl;
- // Make a note that we need to wire up this declaration to its
- // previous declaration, later.
- Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+ if (Kind == PointsToPrevious) {
+ // Make a note that we need to wire up this declaration to its
+ // previous declaration, later. We don't need to do this for the first
+ // declaration in any given module file, because those will be wired
+ // together later.
+ Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+ }
break;
}
}
@@ -1412,7 +1423,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
template <typename T>
void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
- enum RedeclKind { FirstDeclaration = 0, PointsToPrevious };
+ enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
DeclID FirstDeclID;
@@ -1420,7 +1431,8 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
case FirstDeclaration:
FirstDeclID = ThisDeclID;
break;
-
+
+ case FirstInFile:
case PointsToPrevious: {
FirstDeclID = ReadDeclID(Record, Idx);
DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1433,10 +1445,14 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// loaded & attached later on.
D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
- // Make a note that we need to wire up this declaration to its
- // previous declaration, later.
- Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
- PrevDeclID));
+ if (Kind == PointsToPrevious) {
+ // Make a note that we need to wire up this declaration to its
+ // previous declaration, later. We don't need to do this for the first
+ // declaration in any given module file, because those will be wired
+ // together later.
+ Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
+ PrevDeclID));
+ }
break;
}
}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index cb1c6f0476..7ae601810b 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -1051,7 +1051,7 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
- enum { FirstDeclaration, PointsToPrevious };
+ enum { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
RedeclarableTemplateDecl *First = 0;
if (!Prev) {
@@ -1063,7 +1063,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
Record.push_back(D->isMemberSpecialization());
} else {
First = D->getFirstDeclaration();
- Record.push_back(PointsToPrevious);
+ Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
Writer.AddDeclRef(First, Record);
Writer.AddDeclRef(Prev, Record);
}
@@ -1276,14 +1276,14 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
- enum { FirstDeclaration = 0, PointsToPrevious };
+ enum { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
T *Prev = D->getPreviousDeclaration();
T *First = D->getFirstDeclaration();
if (!Prev) {
Record.push_back(FirstDeclaration);
} else {
- Record.push_back(PointsToPrevious);
+ Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
Writer.AddDeclRef(First, Record);
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
}