From: Douglas Gregor Date: Tue, 1 Nov 2011 01:16:03 +0000 (+0000) Subject: Rework the AST for the initializer of a delegating constructor, so X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=76852c218a207ef43583515cb835b6e855353a0f;p=clang Rework the AST for the initializer of a delegating constructor, so that it retains source location information for the type. Aside from general goodness (being able to walk the types described in that information), we now have a proper representation for dependent delegating constructors. Fixes PR10457 (for real). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143410 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 7e60773e44..4d2e71713f 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1445,11 +1445,10 @@ public: /// }; /// @endcode class CXXCtorInitializer { - /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target - /// constructor (CXXConstructorDecl*) being initialized. - llvm::PointerUnion4 + /// \brief Either the base class name/delegating constructor type (stored as + /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field + /// (IndirectFieldDecl*) being initialized. + llvm::PointerUnion3 Initializee; /// \brief The source location for the field name or, for a base initializer @@ -1470,6 +1469,10 @@ class CXXCtorInitializer { /// RParenLoc - Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; + /// \brief If the initializee is a type, whether that type makes this + /// a delegating initialization. + bool IsDelegating : 1; + /// IsVirtual - If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. bool IsVirtual : 1; @@ -1483,7 +1486,7 @@ class CXXCtorInitializer { /// original sources, counting from 0; otherwise, if IsWritten is false, /// it stores the number of array index variables stored after this /// object in memory. - unsigned SourceOrderOrNumArrayIndices : 14; + unsigned SourceOrderOrNumArrayIndices : 13; CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, @@ -1510,8 +1513,8 @@ public: /// CXXCtorInitializer - Creates a new delegating Initializer. explicit - CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, - CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, + SourceLocation L, Expr *Init, SourceLocation R); /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. @@ -1522,7 +1525,9 @@ public: /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. - bool isBaseInitializer() const { return Initializee.is(); } + bool isBaseInitializer() const { + return Initializee.is() && !IsDelegating; + } /// isMemberInitializer - Returns true when this initializer is /// initializing a non-static data member. @@ -1546,7 +1551,7 @@ public: /// isDelegatingInitializer - Returns true when this initializer is creating /// a delegating constructor. bool isDelegatingInitializer() const { - return Initializee.is(); + return Initializee.is() && IsDelegating; } /// \brief Determine whether this initializer is a pack expansion. @@ -1576,8 +1581,9 @@ public: return IsVirtual; } - /// \brief Returns the declarator information for a base class initializer. - TypeSourceInfo *getBaseClassInfo() const { + /// \brief Returns the declarator information for a base class or delegating + /// initializer. + TypeSourceInfo *getTypeSourceInfo() const { return Initializee.dyn_cast(); } @@ -1606,13 +1612,6 @@ public: return 0; } - CXXConstructorDecl *getTargetConstructor() const { - if (isDelegatingInitializer()) - return Initializee.get(); - else - return 0; - } - SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } @@ -1821,11 +1820,7 @@ public: /// getTargetConstructor - When this constructor delegates to /// another, retrieve the target - CXXConstructorDecl *getTargetConstructor() const { - assert(isDelegatingConstructor() && - "A non-delegating constructor has no target"); - return CtorInitializers[0]->getTargetConstructor(); - } + CXXConstructorDecl *getTargetConstructor() const; /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 2a97d3c565..9b65063d35 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -667,7 +667,9 @@ bool RecursiveASTVisitor::TraverseTemplateArguments( template bool RecursiveASTVisitor::TraverseConstructorInitializer( CXXCtorInitializer *Init) { - // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()? + if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); + if (Init->isWritten()) TRY_TO(TraverseStmt(Init->getInit())); return true; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 967c02e0b7..9720295613 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3518,7 +3518,6 @@ public: MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, const MultiInitializer &Args, - SourceLocation BaseLoc, CXXRecordDecl *ClassDecl); bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 576d0d5148..b8c20e4b06 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" @@ -1299,8 +1300,8 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation R, SourceLocation EllipsisLoc) : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), - SourceOrderOrNumArrayIndices(0) + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), + IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1310,7 +1311,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1321,17 +1322,17 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - SourceLocation D, SourceLocation L, - CXXConstructorDecl *Target, Expr *Init, + TypeSourceInfo *TInfo, + SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1380,13 +1381,16 @@ const Type *CXXCtorInitializer::getBaseClass() const { } SourceLocation CXXCtorInitializer::getSourceLocation() const { - if (isAnyMemberInitializer() || isDelegatingInitializer()) + if (isAnyMemberInitializer()) return getMemberLocation(); if (isInClassMemberInitializer()) return getAnyMember()->getLocation(); - return getBaseClassLoc().getLocalSourceRange().getBegin(); + if (TypeSourceInfo *TSInfo = Initializee.get()) + return TSInfo->getTypeLoc().getLocalSourceRange().getBegin(); + + return SourceLocation(); } SourceRange CXXCtorInitializer::getSourceRange() const { @@ -1421,6 +1425,15 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isConstexpr); } +CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { + assert(isDelegatingConstructor() && "Not a delegating constructor!"); + Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); + if (CXXConstructExpr *Construct = dyn_cast(E)) + return Construct->getConstructor(); + + return 0; +} + bool CXXConstructorDecl::isDefaultConstructor() const { // C++ [class.ctor]p5: // A default constructor for a class X is a constructor of class diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 42d7b2f48f..c43db52132 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2125,13 +2125,12 @@ Sema::BuildMemberInitializer(ValueDecl *Member, MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, const MultiInitializer &Args, - SourceLocation NameLoc, CXXRecordDecl *ClassDecl) { - SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); + SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) - return Diag(Loc, diag::err_delegating_ctor) + return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); - Diag(Loc, diag::warn_cxx98_compat_delegating_ctor); + Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); // Initialize the object. InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( @@ -2158,9 +2157,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, if (DelegationInit.isInvalid()) return true; - assert(!CurContext->isDependentContext()); - return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(), - Constructor, + return new (Context) CXXCtorInitializer(Context, TInfo, Args.getStartLoc(), DelegationInit.takeAs(), Args.getEndLoc()); } @@ -2210,7 +2207,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl); + return BuildDelegatingInitializer(BaseTInfo, Args, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -3000,12 +2997,12 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (PrevInit->isAnyMemberInitializer()) D << 0 << PrevInit->getAnyMember()->getDeclName(); else - D << 1 << PrevInit->getBaseClassInfo()->getType(); + D << 1 << PrevInit->getTypeSourceInfo()->getType(); if (Init->isAnyMemberInitializer()) D << 0 << Init->getAnyMember()->getDeclName(); else - D << 1 << Init->getBaseClassInfo()->getType(); + D << 1 << Init->getTypeSourceInfo()->getType(); // Move back to the initializer's location in the ideal list. for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index a4808f88d2..bb6f2d347f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2744,7 +2744,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, if (Init->isPackExpansion()) { // This is a pack expansion. We should expand it now. - TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); + TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc(); SmallVector Unexpanded; collectUnexpandedParameterPacks(BaseTL, Unexpanded); bool ShouldExpand = false; @@ -2774,7 +2774,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } // Instantiate the base type. - TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(), TemplateArgs, Init->getSourceLocation(), New->getDeclName()); @@ -2809,20 +2809,25 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } MemInitResult NewInit; - if (Init->isBaseInitializer()) { - TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); - if (!BaseTInfo) { + if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { + TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!TInfo) { AnyErrors = true; New->setInvalidDecl(); continue; } MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit, - New->getParent(), EllipsisLoc); + + if (Init->isBaseInitializer()) + NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, MultiInit, + New->getParent(), EllipsisLoc); + else + NewInit = BuildDelegatingInitializer(TInfo, MultiInit, + cast(CurContext->getParent())); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast_or_null(FindInstantiatedDecl( Init->getMemberLocation(), diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4554f05256..153b0e0dfe 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -5152,21 +5152,20 @@ ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *BaseClassInfo = 0; + TypeSourceInfo *TInfo = 0; bool IsBaseVirtual = false; FieldDecl *Member = 0; IndirectFieldDecl *IndirectMember = 0; - CXXConstructorDecl *Target = 0; CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; switch (Type) { - case CTOR_INITIALIZER_BASE: - BaseClassInfo = GetTypeSourceInfo(F, Record, Idx); + case CTOR_INITIALIZER_BASE: + TInfo = GetTypeSourceInfo(F, Record, Idx); IsBaseVirtual = Record[Idx++]; break; - - case CTOR_INITIALIZER_DELEGATING: - Target = ReadDeclAs(F, Record, Idx); + + case CTOR_INITIALIZER_DELEGATING: + TInfo = GetTypeSourceInfo(F, Record, Idx); break; case CTOR_INITIALIZER_MEMBER: @@ -5196,12 +5195,12 @@ ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, CXXCtorInitializer *BOMInit; if (Type == CTOR_INITIALIZER_BASE) { - BOMInit = new (Context) CXXCtorInitializer(Context, BaseClassInfo, IsBaseVirtual, + BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, RParenLoc, MemberOrEllipsisLoc); } else if (Type == CTOR_INITIALIZER_DELEGATING) { - BOMInit = new (Context) CXXCtorInitializer(Context, MemberOrEllipsisLoc, LParenLoc, - Target, Init, RParenLoc); + BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, + Init, RParenLoc); } else if (IsWritten) { if (Member) BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 9716447dfa..deaec02271 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3881,11 +3881,11 @@ void ASTWriter::AddCXXCtorInitializers( if (Init->isBaseInitializer()) { Record.push_back(CTOR_INITIALIZER_BASE); - AddTypeSourceInfo(Init->getBaseClassInfo(), Record); + AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); Record.push_back(Init->isBaseVirtual()); } else if (Init->isDelegatingInitializer()) { Record.push_back(CTOR_INITIALIZER_DELEGATING); - AddDeclRef(Init->getTargetConstructor(), Record); + AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); } else if (Init->isMemberInitializer()){ Record.push_back(CTOR_INITIALIZER_MEMBER); AddDeclRef(Init->getMember(), Record); diff --git a/test/SemaTemplate/delegating-constructors.cpp b/test/SemaTemplate/delegating-constructors.cpp index d82343402b..e177b50375 100644 --- a/test/SemaTemplate/delegating-constructors.cpp +++ b/test/SemaTemplate/delegating-constructors.cpp @@ -15,4 +15,17 @@ namespace PR10457 { void f() { string s("hello"); } + + struct Foo { + Foo(int) { } + + + template + Foo(T, int i) : Foo(i) { } +}; + + void test_Foo() + { + Foo f(1, 1); + } } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f028aa6124..efc216b39f 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -828,8 +828,8 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { if (Visit(MakeCursorMemberRef(Init->getAnyMember(), Init->getMemberLocation(), TU))) return true; - } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) { - if (Visit(BaseInfo->getTypeLoc())) + } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) { + if (Visit(TInfo->getTypeLoc())) return true; }