diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 30 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Initialization.h | 7 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 69 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 7 |
7 files changed, 118 insertions, 17 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 1656a7e9737..45108c37e08 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1148,13 +1148,16 @@ public: /// @endcode class CXXCtorInitializer { /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being - /// initialized. - llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> + /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target + /// constructor (CXXConstructorDecl*) being initialized. + llvm::PointerUnion4<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *, + CXXConstructorDecl *> Initializee; /// \brief The source location for the field name or, for a base initializer - /// pack expansion, the location of the ellipsis. + /// pack expansion, the location of the ellipsis. In the case of a delegating + /// constructor, it will still include the type's source location as the + /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; /// \brief The argument used to initialize the base or member, which may @@ -1199,11 +1202,17 @@ public: SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new delegating Initializer. + explicit + CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, @@ -1227,6 +1236,12 @@ public: return Initializee.is<IndirectFieldDecl*>(); } + /// isDelegatingInitializer - Returns true when this initializer is creating + /// a delegating constructor. + bool isDelegatingInitializer() const { + return Initializee.is<CXXConstructorDecl *>(); + } + /// \brief Determine whether this initializer is a pack expansion. bool isPackExpansion() const { return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); @@ -1284,6 +1299,13 @@ public: return 0; } + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingInitializer()) + return Initializee.get<CXXConstructorDecl*>(); + else + return 0; + } + SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a9fb2da0017..4b3b335519f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -798,8 +798,8 @@ def err_ident_in_pseudo_dtor_not_a_type : Error< def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " - "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of " - "type %3">; + "base class|a constructor delegation|a vector element}0 of type %1 with an " + "%select{rvalue|lvalue}2 of type %3">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind " "to lvalue of type %1">; @@ -969,6 +969,8 @@ def err_delegation_0x_only : Error< "delegating constructors are permitted only in C++0x">; def err_delegation_unimplemented : Error< "delegating constructors are not fully implemented">; +def err_delegating_initializer_alone : Error< + "an initializer for a delegating constructor must appear alone">; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index bdf0d8e7b60..7ccd27201cf 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -64,6 +64,8 @@ public: EK_Temporary, /// \brief The entity being initialized is a base member subobject. EK_Base, + /// \brief The initialization is being done by a delegating constructor. + EK_Delegation, /// \brief The entity being initialized is an element of a vector. /// or vector. EK_VectorElement, @@ -210,6 +212,11 @@ public: static InitializedEntity InitializeBase(ASTContext &Context, CXXBaseSpecifier *Base, bool IsInheritedVirtualBase); + + /// \brief Create the initialization entity for a delegated constructor. + static InitializedEntity InitializeDelegation(QualType Type) { + return InitializedEntity(EK_Delegation, SourceLocation(), Type); + } /// \brief Create the initialization entity for a member subobject. static InitializedEntity InitializeMember(FieldDecl *Member, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a93739892cf..7a1a9f6b093 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2818,10 +2818,10 @@ public: MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation BaseLoc, SourceLocation RParenLoc, SourceLocation LParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc); + CXXRecordDecl *ClassDecl); bool SetCtorInitializers(CXXConstructorDecl *Constructor, CXXCtorInitializer **Initializers, diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 46768c12d87..1b849a58ad2 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1033,6 +1033,16 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, } CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, + SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, + SourceLocation R) + : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(0) +{ +} + +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, @@ -1076,7 +1086,7 @@ const Type *CXXCtorInitializer::getBaseClass() const { } SourceLocation CXXCtorInitializer::getSourceLocation() const { - if (isAnyMemberInitializer()) + if (isAnyMemberInitializer() || isDelegatingInitializer()) return getMemberLocation(); return getBaseClassLoc().getLocalSourceRange().getBegin(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index f483262a8cf..457ae859413 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -21,6 +21,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" @@ -1476,17 +1477,61 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation NameLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc) { + CXXRecordDecl *ClassDecl) { SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) return Diag(Loc, diag::err_delegation_0x_only) << TInfo->getTypeLoc().getLocalSourceRange(); - return Diag(Loc, diag::err_delegation_unimplemented) - << TInfo->getTypeLoc().getLocalSourceRange(); + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + + ExprResult DelegationInit = + InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (DelegationInit.isInvalid()) + return true; + + CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); + CXXConstructorDecl *Constructor = ConExpr->getConstructor(); + assert(Constructor && "Delegating constructor with no target?"); + + CheckImplicitConversions(DelegationInit.get(), LParenLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + if (DelegationInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + ExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, + NumArgs, RParenLoc)); + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, + Constructor, Init.takeAs<Expr>(), + RParenLoc); + } + + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor, + DelegationInit.takeAs<Expr>(), + RParenLoc); } MemInitResult @@ -1538,9 +1583,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, - LParenLoc, RParenLoc, ClassDecl, - EllipsisLoc); + return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc, + LParenLoc, RParenLoc, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -2340,10 +2384,19 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, if (CheckRedundantInit(*this, Init, Members[Field]) || CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; - } else { + } else if (Init->isBaseInitializer()) { void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); if (CheckRedundantInit(*this, Init, Members[Key])) HadError = true; + } else { + assert(Init->isDelegatingInitializer()); + // This must be the only initializer + if (i != 0 || NumMemInits > 1) { + Diag(MemInits[0]->getSourceLocation(), + diag::err_delegating_initializer_alone) + << MemInits[0]->getSourceRange(); + HadError = true; + } } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5882da0eab4..358e5fb5015 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1998,6 +1998,7 @@ DeclarationName InitializedEntity::getName() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegation: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2020,6 +2021,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegation: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2042,6 +2044,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegation: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -3289,6 +3292,7 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegation: return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: @@ -3325,6 +3329,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegation: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: @@ -3346,6 +3351,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Result: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegation: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: return false; @@ -3430,6 +3436,7 @@ static ExprResult CopyObject(Sema &S, case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegation: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: Loc = CurInitExpr->getLocStart(); |

