diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 6f9eee74d539..1d153eefd4ac 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -736,6 +736,10 @@ class CXXBaseOrMemberInitializer { Expr **Args; unsigned NumArgs; + /// CtorToCall - For a base or mamber needing a constructor for their + /// initialization, this is the constructor to call. + CXXConstructorDecl *CtorToCall; + /// IdLoc - Location of the id in ctor-initializer list. SourceLocation IdLoc; @@ -743,11 +747,13 @@ public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, + CXXConstructorDecl *C, SourceLocation L); /// CXXBaseOrMemberInitializer - Creates a new member initializer. explicit CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, + CXXConstructorDecl *C, SourceLocation L); /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer. @@ -805,6 +811,8 @@ public: return 0; } + CXXConstructorDecl *getConstructor() const { return CtorToCall; } + SourceLocation getSourceLocation() const { return IdLoc; } /// begin() - Retrieve an iterator to the first initializer argument. diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index eb66c17bf806..0f2230116cc0 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -380,6 +380,7 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, + CXXConstructorDecl *C, SourceLocation L) : Args(0), NumArgs(0), IdLoc(L) { BaseOrMember = reinterpret_cast(BaseType.getTypePtr()); @@ -392,10 +393,12 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } + CtorToCall = C; } CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, + CXXConstructorDecl *C, SourceLocation L) : Args(0), NumArgs(0), IdLoc(L) { BaseOrMember = reinterpret_cast(Member); @@ -407,6 +410,7 @@ CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } + CtorToCall = C; } CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { @@ -587,9 +591,14 @@ CXXConstructorDecl::setBaseOrMemberInitializers( if (AllBaseFields[Key]) AllToInit.push_back(AllBaseFields[Key]); else { + CXXRecordDecl *VBaseDecl = + cast(VBase->getType()->getAsRecordType()->getDecl()); + assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); + // FIXME. Issue error if default ctor is missing. CXXBaseOrMemberInitializer *Member = - new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, - SourceLocation()); + new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, + VBaseDecl->getDefaultConstructor(C), + SourceLocation()); AllToInit.push_back(Member); } } @@ -605,8 +614,13 @@ CXXConstructorDecl::setBaseOrMemberInitializers( if (AllBaseFields[Key]) AllToInit.push_back(AllBaseFields[Key]); else { + CXXRecordDecl *BaseDecl = + cast(Base->getType()->getAsRecordType()->getDecl()); + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + // FIXME. Issue error if default ctor is missing. CXXBaseOrMemberInitializer *Member = new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, + BaseDecl->getDefaultConstructor(C), SourceLocation()); AllToInit.push_back(Member); } @@ -625,8 +639,15 @@ CXXConstructorDecl::setBaseOrMemberInitializers( FieldType = AT->getElementType(); if (FieldType->getAsRecordType()) { + CXXConstructorDecl *Ctor = 0; + if (CXXRecordDecl *FieldClassDecl = + dyn_cast(FieldType->getAsRecordType()->getDecl())) + Ctor = FieldClassDecl->getDefaultConstructor(C); + // FIXME. Issue error if default ctor is missing. CXXBaseOrMemberInitializer *Member = - new (C) CXXBaseOrMemberInitializer((*Field), 0, 0, SourceLocation()); + new (C) CXXBaseOrMemberInitializer((*Field), 0, 0, + Ctor, + SourceLocation()); AllToInit.push_back(Member); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3bb16572e9e1..c12878c7603c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -717,9 +717,17 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, // FIXME: Handle members of an anonymous union. if (Member) { + CXXConstructorDecl *C = 0; + QualType FieldType = Member->getType(); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (!FieldType->isDependentType() && FieldType->getAsRecordType()) + C = PerformInitializationByConstructor( + FieldType, (Expr **)Args, NumArgs, IdLoc, + SourceRange(IdLoc, RParenLoc), Member->getDeclName(), IK_Direct); // FIXME: Perform direct initialization of the member. return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args, - NumArgs, IdLoc); + NumArgs, C, IdLoc); } } // It didn't name a member, so see if it names a class. @@ -789,10 +797,17 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, return Diag(IdLoc, diag::err_not_direct_base_or_virtual) << BaseType << ClassDecl->getNameAsCString() << SourceRange(IdLoc, RParenLoc); - - - return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, - NumArgs, IdLoc); + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(BaseType)); + CXXConstructorDecl *C = 0; + if (!BaseType->isDependentType()) + C = PerformInitializationByConstructor(BaseType, (Expr **)Args, NumArgs, IdLoc, + SourceRange(IdLoc, RParenLoc), Name, + IK_Direct); + + return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, + NumArgs, C, IdLoc); } static void *GetKeyForTopLevelField(FieldDecl *Field) { diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp index 206d5d2ae77c..66a5f57e1c1e 100644 --- a/clang/test/SemaCXX/constructor-initializer.cpp +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -2,6 +2,7 @@ class A { int m; A() : A::m(17) { } // expected-error {{member initializer 'm' does not name a non-static data member or base class}} + A(int); }; class B : public A {