]> granicus.if.org Git - clang/commitdiff
Eliminate a hang while loading a sequence of redeclarable entities. In
authorDouglas Gregor <dgregor@apple.com>
Wed, 26 Oct 2011 17:53:41 +0000 (17:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 26 Oct 2011 17:53:41 +0000 (17:53 +0000)
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

lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/Index/Inputs/redeclarations.h [new file with mode: 0644]
test/Index/redeclarations.cpp [new file with mode: 0644]

index a15dc424e793096710c0eb97a702566746a1adfa..f64aa20a22f52bad83bee7cbbd5038ef20dd957a 100644 (file)
@@ -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) !=
index 2925f49292e7e1eac6e32d111794d1800e5b7153..f61386792680bf50810f0273703b194932f94754 100644 (file)
@@ -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 (file)
index 0000000..7f0d7ae
--- /dev/null
@@ -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 (file)
index 0000000..453d02c
--- /dev/null
@@ -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]