diff options
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 35 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 20 | ||||
-rw-r--r-- | test/Index/Inputs/redeclarations.h | 21 | ||||
-rw-r--r-- | test/Index/redeclarations.cpp | 21 |
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] |