aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-10-26 17:53:41 +0000
committerDouglas Gregor <dgregor@apple.com>2011-10-26 17:53:41 +0000
commitd488b3a046c09f88bc3cbd79bb4df84e43a238bc (patch)
treeb1fd3605f2f8dbcf71ea75ff860c3421b2cfdf2d
parent3ab057f7b9e5f98210eabd53165d74282b5a6bdb (diff)
Eliminate a hang while loading a sequence of redeclarable entities. In
essence, the redeclaration chain for a class could end up in an inconsistent state while deserializing multiple declarations in that chain, where the circular linked list was not, in fact, circular. Since only two redeclarations of the same entity will get loaded when we're in this state, restore circularity when both have been loaded. Fixes <rdar://problem/10324940> / PR11195. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143037 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp35
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp20
-rw-r--r--test/Index/Inputs/redeclarations.h21
-rw-r--r--test/Index/redeclarations.cpp21
4 files changed, 80 insertions, 17 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index a15dc424e7..f64aa20a22 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -278,8 +278,8 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
}
void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
- VisitTypeDecl(TD);
VisitRedeclarable(TD);
+ VisitTypeDecl(TD);
TD->IdentifierNamespace = Record[Idx++];
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
TD->setCompleteDefinition(Record[Idx++]);
@@ -340,8 +340,8 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
}
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
- VisitDeclaratorDecl(FD);
VisitRedeclarable(FD);
+ VisitDeclaratorDecl(FD);
ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
FD->IdentifierNamespace = Record[Idx++];
@@ -712,8 +712,8 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
}
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
- VisitDeclaratorDecl(VD);
VisitRedeclarable(VD);
+ VisitDeclaratorDecl(VD);
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++];
VD->VarDeclBits.ThreadSpecified = Record[Idx++];
@@ -1329,18 +1329,37 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// We temporarily set the first (canonical) declaration as the previous one
// which is the one that matters and mark the real previous DeclID to be
// loaded & attached later on.
- D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
- cast_or_null<T>(Reader.GetDecl(FirstDeclID)));
+ T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
+ D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
if (PreviousDeclID != FirstDeclID)
Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
PreviousDeclID));
+
+ // If the first declaration in the chain is in an inconsistent
+ // state where it thinks that it is the only declaration, fix its
+ // redeclaration link now to point at this declaration, so that we have a
+ // proper redeclaration chain.
+ if (FirstDecl->RedeclLink.getPointer() == FirstDecl) {
+ FirstDecl->RedeclLink
+ = typename Redeclarable<T>::LatestDeclLink(static_cast<T*>(D));
+ }
break;
}
- case PointsToLatest:
- D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
- ReadDeclAs<T>(Record, Idx));
+ case PointsToLatest: {
+ T *LatestDecl = ReadDeclAs<T>(Record, Idx);
+ D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(LatestDecl);
+
+ // If the latest declaration in the chain is in an inconsistent
+ // state where it thinks that it is the only declaration, fix its
+ // redeclaration link now to point at this declaration, so that we have a
+ // proper redeclaration chain.
+ if (LatestDecl->RedeclLink.getPointer() == LatestDecl) {
+ LatestDecl->RedeclLink
+ = typename Redeclarable<T>::PreviousDeclLink(static_cast<T*>(D));
+ }
break;
}
+ }
assert(!(Kind == PointsToPrevious &&
Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 2925f49292..f613867926 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -198,8 +198,8 @@ void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
}
void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
- VisitTypeDecl(D);
VisitRedeclarable(D);
+ VisitTypeDecl(D);
Record.push_back(D->getIdentifierNamespace());
Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
Record.push_back(D->isCompleteDefinition());
@@ -289,8 +289,8 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
}
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
- VisitDeclaratorDecl(D);
VisitRedeclarable(D);
+ VisitDeclaratorDecl(D);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Record.push_back(D->getIdentifierNamespace());
@@ -651,8 +651,8 @@ void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
}
void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
- VisitDeclaratorDecl(D);
VisitRedeclarable(D);
+ VisitDeclaratorDecl(D);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isThreadSpecified());
@@ -1336,6 +1336,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// Abbreviation for DECL_ENUM
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM));
+ // Redeclarable
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1353,8 +1355,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
- // Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// TagDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind
@@ -1382,6 +1382,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// Abbreviation for DECL_RECORD
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD));
+ // Redeclarable
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1399,8 +1401,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
- // Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// TagDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind
@@ -1422,6 +1422,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// Abbreviation for DECL_PARM_VAR
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
+ // Redeclarable
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1442,7 +1444,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
- Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten
Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
@@ -1495,6 +1496,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
// Abbreviation for DECL_VAR
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR));
+ // Redeclarable
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1515,7 +1518,6 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
- Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClassAsWritten
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isThreadSpecified
diff --git a/test/Index/Inputs/redeclarations.h b/test/Index/Inputs/redeclarations.h
new file mode 100644
index 0000000000..7f0d7aebb8
--- /dev/null
+++ b/test/Index/Inputs/redeclarations.h
@@ -0,0 +1,21 @@
+class X
+{
+ friend class A;
+};
+
+
+template <typename T1, typename T2>
+class B
+{
+};
+
+template <class T>
+struct C
+{
+};
+
+class D
+{
+ B<D, class A> x;
+ friend struct C<A>;
+};
diff --git a/test/Index/redeclarations.cpp b/test/Index/redeclarations.cpp
new file mode 100644
index 0000000000..453d02c272
--- /dev/null
+++ b/test/Index/redeclarations.cpp
@@ -0,0 +1,21 @@
+#include "redeclarations.h"
+
+class A
+{
+};
+
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 2 all -I%S/Inputs %s | FileCheck %s
+
+// CHECK: redeclarations.h:1:7: ClassDecl=X:1:7 (Definition) Extent=[1:1 - 4:2]
+// CHECK: redeclarations.h:8:7: ClassTemplate=B:8:7 (Definition) Extent=[7:1 - 10:2]
+// CHECK: redeclarations.h:7:20: TemplateTypeParameter=T1:7:20 (Definition) Extent=[7:11 - 7:22]
+// CHECK: redeclarations.h:7:33: TemplateTypeParameter=T2:7:33 (Definition) Extent=[7:24 - 7:35]
+// CHECK: redeclarations.h:13:8: ClassTemplate=C:13:8 (Definition) Extent=[12:1 - 15:2]
+// CHECK: redeclarations.h:12:17: TemplateTypeParameter=T:12:17 (Definition) Extent=[12:11 - 12:18]
+// CHECK: redeclarations.h:17:7: ClassDecl=D:17:7 (Definition) Extent=[17:1 - 21:2]
+// CHECK: redeclarations.h:19:16: ClassDecl=A:19:16 Extent=[19:10 - 19:17]
+// CHECK: redeclarations.h:19:19: FieldDecl=x:19:19 (Definition) Extent=[19:5 - 19:20]
+// CHECK: redeclarations.h:19:5: TemplateRef=B:8:7 Extent=[19:5 - 19:6]
+// CHECK: redeclarations.h:19:7: TypeRef=class D:17:7 Extent=[19:7 - 19:8]
+// CHECK: redeclarations.h:19:16: TypeRef=class A:3:7 Extent=[19:16 - 19:17]
+// CHECK: redeclarations.cpp:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 5:2]