Only make a call to a copy constructor elidable if in fact we are

doing a copy. Fixes PR12139.

llvm-svn: 152485
This commit is contained in:
Douglas Gregor 2012-03-10 06:53:13 +00:00
parent eace54fcb4
commit d2f7007e09
2 changed files with 42 additions and 1 deletions

View File

@ -8876,6 +8876,25 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
} }
} }
/// \brief Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
case 0:
return false;
default:
if (!Args.get()[1]->isDefaultArgument())
return false;
// fall through
case 1:
return !Args.get()[0]->isDefaultArgument();
}
return false;
}
ExprResult ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, CXXConstructorDecl *Constructor,
@ -8897,7 +8916,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
// can be omitted by constructing the temporary object // can be omitted by constructing the temporary object
// directly into the target of the omitted copy/move // directly into the target of the omitted copy/move
if (ConstructKind == CXXConstructExpr::CK_Complete && if (ConstructKind == CXXConstructExpr::CK_Complete &&
Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) { Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent());
} }

View File

@ -53,3 +53,25 @@ void f() {
} }
} }
namespace PR12139 {
struct A {
A() : value(1) { }
A(A const &, int value = 2) : value(value) { }
int value;
static A makeA() { A a; a.value = 2; return a; }
};
// CHECK: define i32 @_ZN7PR121394testEv
int test() {
// CHECK: call void @_ZN7PR121391A5makeAEv
// CHECK-NEXT: call void @_ZN7PR121391AC1ERKS0_i
A a(A::makeA(), 3);
// CHECK-NEXT: getelementptr inbounds
// CHECK-NEXT: load
// CHECK-NEXT: ret i32
return a.value;
}
}