]> granicus.if.org Git - clang/commitdiff
Only make a call to a copy constructor elidable if in fact we are
authorDouglas Gregor <dgregor@apple.com>
Sat, 10 Mar 2012 06:53:13 +0000 (06:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 10 Mar 2012 06:53:13 +0000 (06:53 +0000)
doing a copy. Fixes PR12139.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152485 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/copy-constructor-elim-2.cpp

index 21a394f71543e9af30526af045b8b632f59f3b37..e84f66b963677c91395eba9d5216653a7fe69faf 100644 (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
 Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                             CXXConstructorDecl *Constructor,
@@ -8897,7 +8916,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
   //       can be omitted by constructing the temporary object
   //       directly into the target of the omitted copy/move
   if (ConstructKind == CXXConstructExpr::CK_Complete &&
-      Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) {
+      Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
     Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
     Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent());
   }
index a4a688f737d76fdebb757326d254b79e64fb068c..9480cbfdbb3a355f9f09ad68ca69181c887afae7 100644 (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;
+  }
+}
+