diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-19 03:01:41 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-19 03:01:41 +0000 |
commit | 7abfbdbc97ad8e7f340789f751df1e32b10118b4 (patch) | |
tree | c98c3dd47e10bceea032ec5fb2b44306f109dacd /lib | |
parent | 29f1a6070ac35fcbea9241c843df7f3f7c5c3228 (diff) |
Switch more of Sema::CheckInitializerTypes over to
InitializationSequence. Specially, switch initialization of a C++
class type (either copy- or direct-initialization).
Also, make sure that we create an elidable copy-construction when
performing copy initialization of a C++ class variable. Fixes PR5826.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91750 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 123 | ||||
-rw-r--r-- | lib/Sema/SemaInit.h | 6 |
2 files changed, 48 insertions, 81 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 60de672c0a..6f11a87d11 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -222,79 +222,15 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType, // -- If the destination type is a (possibly cv-qualified) class // type: if (getLangOptions().CPlusPlus && DeclType->isRecordType()) { - QualType DeclTypeC = Context.getCanonicalType(DeclType); - QualType InitTypeC = Context.getCanonicalType(Init->getType()); - - // -- If the initialization is direct-initialization, or if it is - // copy-initialization where the cv-unqualified version of the - // source type is the same class as, or a derived class of, the - // class of the destination, constructors are considered. - if ((DeclTypeC.getLocalUnqualifiedType() - == InitTypeC.getLocalUnqualifiedType()) || - IsDerivedFrom(InitTypeC, DeclTypeC)) { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl()); - - // No need to make a CXXConstructExpr if both the ctor and dtor are - // trivial. - if (RD->hasTrivialConstructor() && RD->hasTrivialDestructor()) - return false; - - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - // FIXME: Poor location information - InitializationKind InitKind - = InitializationKind::CreateCopy(Init->getLocStart(), - SourceLocation()); - if (DirectInit) - InitKind = InitializationKind::CreateDirect(Init->getLocStart(), - SourceLocation(), - SourceLocation()); - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(DeclType, - MultiExprArg(*this, - (void **)&Init, 1), - InitLoc, Init->getSourceRange(), - InitEntity, InitKind, - ConstructorArgs); - if (!Constructor) - return true; - - OwningExprResult InitResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - DeclType, Constructor, - move_arg(ConstructorArgs)); - if (InitResult.isInvalid()) - return true; - - Init = InitResult.takeAs<Expr>(); - return false; - } + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + OwningExprResult CurInit = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&Init, 1), + &DeclType); + if (CurInit.isInvalid()) + return true; - // -- Otherwise (i.e., for the remaining copy-initialization - // cases), user-defined conversion sequences that can - // convert from the source type to the destination type or - // (when a conversion function is used) to a derived class - // thereof are enumerated as described in 13.3.1.4, and the - // best one is chosen through overload resolution - // (13.3). If the conversion cannot be done or is - // ambiguous, the initialization is ill-formed. The - // function selected is called with the initializer - // expression as its argument; if the function is a - // constructor, the call initializes a temporary of the - // destination type. - // FIXME: We're pretending to do copy elision here; return to this when we - // have ASTs for such things. - if (!PerformImplicitConversion(Init, DeclType, Sema::AA_Initializing)) - return false; - - if (InitEntity) - return Diag(InitLoc, diag::err_cannot_initialize_decl) - << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); - return Diag(InitLoc, diag::err_cannot_initialize_decl_noname) - << DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); + Init = CurInit.takeAs<Expr>(); + return false; } // C99 6.7.8p16. @@ -2014,6 +1950,26 @@ DeclarationName InitializedEntity::getName() const { return DeclarationName(); } +DeclaratorDecl *InitializedEntity::getDecl() const { + switch (getKind()) { + case EK_Variable: + case EK_Parameter: + case EK_Member: + return VariableOrMember; + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_ArrayOrVectorElement: + return 0; + } + + // Silence GCC warning + return 0; +} + //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// @@ -3051,25 +3007,32 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity, /// thrown), make the copy. static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, const InitializedEntity &Entity, + const InitializationKind &Kind, Sema::OwningExprResult CurInit) { SourceLocation Loc; - bool isReturn = false; switch (Entity.getKind()) { case InitializedEntity::EK_Result: if (Entity.getType().getType()->isReferenceType()) return move(CurInit); - isReturn = true; Loc = Entity.getReturnLoc(); break; case InitializedEntity::EK_Exception: - isReturn = false; Loc = Entity.getThrowLoc(); break; case InitializedEntity::EK_Variable: + if (Entity.getType().getType()->isReferenceType() || + Kind.getKind() != InitializationKind::IK_Copy) + return move(CurInit); + Loc = Entity.getDecl()->getLocation(); + break; + case InitializedEntity::EK_Parameter: + // FIXME: Do we need this initialization for a parameter? + return move(CurInit); + case InitializedEntity::EK_New: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_Base: @@ -3110,21 +3073,21 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, case OR_No_Viable_Function: S.Diag(Loc, diag::err_temp_copy_no_viable) - << isReturn << CurInitExpr->getType() + << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.PrintOverloadCandidates(CandidateSet, false); return S.ExprError(); case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) - << isReturn << CurInitExpr->getType() + << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.PrintOverloadCandidates(CandidateSet, true); return S.ExprError(); case OR_Deleted: S.Diag(Loc, diag::err_temp_copy_deleted) - << isReturn << CurInitExpr->getType() + << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) << Best->Function->isDeleted(); @@ -3364,7 +3327,7 @@ InitializationSequence::Perform(Sema &S, false)); if (!IsCopy) - CurInit = CopyIfRequiredForEntity(S, Entity, move(CurInit)); + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } @@ -3425,7 +3388,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); if (!Elidable) - CurInit = CopyIfRequiredForEntity(S, Entity, move(CurInit)); + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index c42badd3f8..1987ad0734 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -195,7 +195,11 @@ public: /// \brief Retrieve the name of the entity being initialized. DeclarationName getName() const; - + + /// \brief Retrieve the variable, parameter, or field being + /// initialized. + DeclaratorDecl *getDecl() const; + /// \brief Determine the location of the 'return' keyword when initializing /// the result of a function call. SourceLocation getReturnLoc() const { |