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
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 60de672..6f11a87 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -222,79 +222,15 @@
// -- 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());
+ 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;
- // -- 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;
- }
-
- // -- 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 @@
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 @@
/// 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 @@
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 @@
false));
if (!IsCopy)
- CurInit = CopyIfRequiredForEntity(S, Entity, move(CurInit));
+ CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
break;
}
@@ -3425,7 +3388,7 @@
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 c42badd..1987ad0 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -195,7 +195,11 @@
/// \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 {