From 72f6d678c8de9f3a770e8ae5fc4979abf3940668 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 1 Sep 2009 21:04:42 +0000 Subject: [PATCH] In CXXBaseOrMemberInitializer, don't confuse CtorTocall with AnonUnionMember. Fixes PR4826. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80721 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 49 ++++++++++++------------ lib/AST/DeclCXX.cpp | 8 ++-- lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +- test/CodeGenCXX/constructor-template.cpp | 18 +++++++++ 4 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 test/CodeGenCXX/constructor-template.cpp diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index a6d32476a7..4fcf51f107 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -819,28 +819,25 @@ class CXXBaseOrMemberInitializer { Stmt **Args; unsigned NumArgs; - union { - /// CtorToCall - For a base or member needing a constructor for their - /// initialization, this is the constructor to call. - CXXConstructorDecl *CtorToCall; - - /// AnonUnionMember - When 'BaseOrMember' is class's anonymous union - /// data member, this field holds the FieldDecl for the member of the - /// anonymous union being initialized. - /// @code - /// struct X { - /// X() : au_i1(123) {} - /// union { - /// int au_i1; - /// float au_f1; - /// }; - /// }; - /// @endcode - /// In above example, BaseOrMember holds the field decl. for anonymous union - /// and AnonUnionMember holds field decl for au_i1. - /// - FieldDecl *AnonUnionMember; - }; + /// \brief Stores either the constructor to call to initialize this base or + /// member (a CXXConstructorDecl pointer), or stores the anonymous union of + /// which the initialized value is a member. + /// + /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's + /// anonymous union data member, this field holds the FieldDecl for the + /// member of the anonymous union being initialized. + /// @code + /// struct X { + /// X() : au_i1(123) {} + /// union { + /// int au_i1; + /// float au_f1; + /// }; + /// }; + /// @endcode + /// In above example, BaseOrMember holds the field decl. for anonymous union + /// and AnonUnionMember holds field decl for au_i1. + llvm::PointerUnion CtorOrAnonUnion; /// IdLoc - Location of the id in ctor-initializer list. SourceLocation IdLoc; @@ -921,13 +918,15 @@ public: } FieldDecl *getAnonUnionMember() const { - return AnonUnionMember; + return CtorOrAnonUnion.dyn_cast(); } void setAnonUnionMember(FieldDecl *anonMember) { - AnonUnionMember = anonMember; + CtorOrAnonUnion = anonMember; } - const CXXConstructorDecl *getConstructor() const { return CtorToCall; } + const CXXConstructorDecl *getConstructor() const { + return CtorOrAnonUnion.dyn_cast(); + } SourceLocation getSourceLocation() const { return IdLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 206193ba81..adcd3f9aa9 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -401,7 +401,7 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, CXXConstructorDecl *C, SourceLocation L, SourceLocation R) - : Args(0), NumArgs(0), IdLoc(L), RParenLoc(R) { + : Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) { BaseOrMember = reinterpret_cast(BaseType.getTypePtr()); assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); BaseOrMember |= 0x01; @@ -413,14 +413,14 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } - CtorToCall = C; + CtorOrAnonUnion = C; } CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, CXXConstructorDecl *C, SourceLocation L, SourceLocation R) - : Args(0), NumArgs(0), IdLoc(L), RParenLoc(R) { + : Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) { BaseOrMember = reinterpret_cast(Member); assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer"); @@ -430,7 +430,7 @@ CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } - CtorToCall = C; + CtorOrAnonUnion = C; } CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0179160835..285cc62012 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1123,7 +1123,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, // Instantiate all the initializers. for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), - InitsEnd = Tmpl->init_end(); Inits != InitsEnd; ++Inits) { + InitsEnd = Tmpl->init_end(); + Inits != InitsEnd; ++Inits) { CXXBaseOrMemberInitializer *Init = *Inits; ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp new file mode 100644 index 0000000000..10577e9766 --- /dev/null +++ b/test/CodeGenCXX/constructor-template.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -emit-llvm -o - + +// PR4826 +struct A { + A() { + } +}; + +template +struct B { + B(T) {} + + A nodes; +}; + +int main() { + B *n = new B(4); +} -- 2.50.1