From 8e9e9ef5348bce1a8f0741a5684fac3de9701c28 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 29 Jul 2009 23:36:44 +0000 Subject: [PATCH] Make tag declarations redeclarable. This change has three purposes: 1) Allow the Index library (and any other interested client) to walk the set of declarations for a given tag (enum, union, class, whatever). At the moment, this information is not readily available. 2) Reduce our dependence on TagDecl::TypeForDecl being mapped down to a TagType (for which getDecl() will return the tag definition, if one exists). This property won't exist for class template partial specializations. 3) Make the canonical declaration of a TagDecl actually canonical, e.g., so that it does not change when the tag is defined. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77523 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 27 ++++++++++++++---- include/clang/AST/DeclCXX.h | 1 + include/clang/AST/DeclTemplate.h | 12 +++++--- lib/AST/Decl.cpp | 48 ++++++++++++++++++-------------- lib/AST/DeclCXX.cpp | 8 ++++-- lib/AST/DeclTemplate.cpp | 11 +++++--- lib/Frontend/PCHReaderDecl.cpp | 2 ++ lib/Frontend/PCHWriterDecl.cpp | 1 + 8 files changed, 73 insertions(+), 37 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 3214b653b9..9ce589ba80 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1178,7 +1178,8 @@ public: class TypedefDecl; /// TagDecl - Represents the declaration of a struct/union/class/enum. -class TagDecl : public TypeDecl, public DeclContext { +class TagDecl + : public TypeDecl, public DeclContext, public Redeclarable { public: enum TagKind { TK_struct, @@ -1205,15 +1206,28 @@ private: protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, SourceLocation TKL = SourceLocation()) + IdentifierInfo *Id, TagDecl *PrevDecl, + SourceLocation TKL = SourceLocation()) : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0), TagKeywordLoc(TKL) { assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); TagDeclKind = TK; IsDefinition = false; + setPreviousDeclaration(PrevDecl); } + + typedef Redeclarable redeclarable_base; + virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: - + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -1307,8 +1321,8 @@ class EnumDecl : public TagDecl { EnumDecl *InstantiatedFrom; EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, SourceLocation TKL) - : TagDecl(Enum, TK_enum, DC, L, Id, TKL), InstantiatedFrom(0) { + IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) + : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); } public: @@ -1380,7 +1394,8 @@ class RecordDecl : public TagDecl { protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, SourceLocation TKL); + SourceLocation L, IdentifierInfo *Id, + RecordDecl *PrevDecl, SourceLocation TKL); virtual ~RecordDecl(); public: diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 8ad8aede60..3da7230ab0 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -376,6 +376,7 @@ class CXXRecordDecl : public RecordDecl { protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl, SourceLocation TKL = SourceLocation()); ~CXXRecordDecl(); diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 17c8bc877d..7cf8bfdecf 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -883,7 +883,8 @@ protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder); + TemplateArgumentListBuilder &Builder, + ClassTemplateSpecializationDecl *PrevDecl); public: static ClassTemplateSpecializationDecl * @@ -954,9 +955,12 @@ class ClassTemplatePartialSpecializationDecl DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder) - : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, - DC, L, SpecializedTemplate, Builder), + TemplateArgumentListBuilder &Builder, + ClassTemplatePartialSpecializationDecl *PrevDecl) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + DC, L, SpecializedTemplate, Builder, + PrevDecl), TemplateParams(Params) { } public: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a15e13568d..240922afd8 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -184,7 +184,7 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, EnumDecl *PrevDecl) { - EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, TKL); + EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL); C.getTypeDeclType(Enum, PrevDecl); return Enum; } @@ -662,33 +662,38 @@ SourceRange TagDecl::getSourceRange() const { } TagDecl* TagDecl::getCanonicalDecl() { - Type *T = getTypeForDecl(); - if (T == 0) - T = getASTContext().getTagDeclType(this).getTypePtr(); - - return cast(cast(T->getCanonicalTypeInternal())->getDecl()); + return getFirstDeclaration(); } void TagDecl::startDefinition() { - TagType *TagT = const_cast(TypeForDecl->getAs()); - TagT->decl.setPointer(this); - TagT->getAs()->decl.setInt(1); + if (TagType *TagT = const_cast(TypeForDecl->getAs())) { + TagT->decl.setPointer(this); + TagT->decl.setInt(1); + } } void TagDecl::completeDefinition() { - assert((!TypeForDecl || - TypeForDecl->getAs()->decl.getPointer() == this) && - "Attempt to redefine a tag definition?"); IsDefinition = true; - TagType *TagT = const_cast(TypeForDecl->getAs()); - TagT->decl.setPointer(this); - TagT->decl.setInt(0); + if (TagType *TagT = const_cast(TypeForDecl->getAs())) { + assert(TagT->decl.getPointer() == this && + "Attempt to redefine a tag definition?"); + TagT->decl.setInt(0); + } } TagDecl* TagDecl::getDefinition(ASTContext& C) const { - QualType T = C.getTypeDeclType(const_cast(this)); - TagDecl* D = cast(T->getAs()->getDecl()); - return D->isDefinition() ? D : 0; + if (isDefinition()) + return const_cast(this); + + if (TagType *TagT = const_cast(TypeForDecl->getAs())) + return TagT->getDecl()->isDefinition()? TagT->getDecl() : 0; + + for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); + R != REnd; ++R) + if (R->isDefinition()) + return *R; + + return 0; } //===----------------------------------------------------------------------===// @@ -696,8 +701,9 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const { //===----------------------------------------------------------------------===// RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, SourceLocation TKL) - : TagDecl(DK, TK, DC, L, Id, TKL) { + IdentifierInfo *Id, RecordDecl *PrevDecl, + SourceLocation TKL) + : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) { HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; @@ -708,7 +714,7 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, RecordDecl* PrevDecl) { - RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, TKL); + RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL); C.getTypeDeclType(R, PrevDecl); return R; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 57897b0460..11c7e6dfc2 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -25,8 +25,9 @@ using namespace clang; CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl, SourceLocation TKL) - : RecordDecl(K, TK, DC, L, Id, TKL), + : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL), UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false), @@ -41,7 +42,10 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation TKL, CXXRecordDecl* PrevDecl, bool DelayTypeCreation) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id, TKL); + CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id, + PrevDecl, TKL); + + // FIXME: DelayTypeCreation seems like such a hack if (!DelayTypeCreation) C.getTypeDeclType(R, PrevDecl); return R; diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 686b78d023..4677d17dc9 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -369,13 +369,15 @@ ClassTemplateSpecializationDecl:: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder) + TemplateArgumentListBuilder &Builder, + ClassTemplateSpecializationDecl *PrevDecl) : CXXRecordDecl(DK, SpecializedTemplate->getTemplatedDecl()->getTagKind(), DC, L, // FIXME: Should we use DeclarationName for the name of // class template specializations? - SpecializedTemplate->getIdentifier()), + SpecializedTemplate->getIdentifier(), + PrevDecl), SpecializedTemplate(SpecializedTemplate), TemplateArgs(Context, Builder, /*TakeArgs=*/true), SpecializationKind(TSK_Undeclared) { @@ -392,7 +394,8 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, ClassTemplateSpecialization, DC, L, SpecializedTemplate, - Builder); + Builder, + PrevDecl); Context.getTypeDeclType(Result, PrevDecl); return Result; } @@ -411,7 +414,7 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, = new (Context)ClassTemplatePartialSpecializationDecl(Context, DC, L, Params, SpecializedTemplate, - Builder); + Builder, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Context.getTypeDeclType(Result, PrevDecl); return Result; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 99a1a16835..65da7dc451 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -112,6 +112,8 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { void PCHDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); + TD->setPreviousDeclaration( + cast_or_null(Reader.GetDecl(Record[Idx++]))); TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setDefinition(Record[Idx++]); TD->setTypedefForAnonDecl( diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 4239798ac8..fd7ea421dd 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -109,6 +109,7 @@ void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void PCHDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); + Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isDefinition()); Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); -- 2.40.0