diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-10-26 17:53:41 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-10-26 17:53:41 +0000 |
| commit | 3e30010d99b1b9c550d022239095cae9cf715934 (patch) | |
| tree | ba00c39cde1cccd825673026b2aa702b6efc17c4 | |
| parent | 3b1d4f678522905d3b8c596da49db78fd48b28f1 (diff) | |
| download | bcm5719-llvm-3e30010d99b1b9c550d022239095cae9cf715934.tar.gz bcm5719-llvm-3e30010d99b1b9c550d022239095cae9cf715934.zip | |
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.
llvm-svn: 143037
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 20 | ||||
| -rw-r--r-- | clang/test/Index/Inputs/redeclarations.h | 21 | ||||
| -rw-r--r-- | clang/test/Index/redeclarations.cpp | 21 |
4 files changed, 80 insertions, 17 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a15dc424e79..f64aa20a22f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 2925f49292e..f6138679268 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/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/clang/test/Index/Inputs/redeclarations.h b/clang/test/Index/Inputs/redeclarations.h new file mode 100644 index 00000000000..7f0d7aebb86 --- /dev/null +++ b/clang/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/clang/test/Index/redeclarations.cpp b/clang/test/Index/redeclarations.cpp new file mode 100644 index 00000000000..453d02c272f --- /dev/null +++ b/clang/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] |

