]> granicus.if.org Git - clang/commitdiff
Fix two bugs with temporaries:
authorAnders Carlsson <andersca@mac.com>
Fri, 13 Nov 2009 04:34:45 +0000 (04:34 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 13 Nov 2009 04:34:45 +0000 (04:34 +0000)
1. For

A f() {
return A();
}

we were incorrectly calling the A destructor on the returned object.

2. For

void f(A);
void g() {
A a;
f(a);
}

we were incorrectly not calling the copy constructor.

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

lib/CodeGen/CGCXX.cpp
lib/Sema/SemaExpr.cpp
test/CodeGenCXX/temporaries.cpp

index 3e9951f83b4a70b0d09d0244d21927c63383093d..9651c1ae83ad8078a71c2014eeabe5b7f0d5fdf3 100644 (file)
@@ -671,8 +671,13 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
   // Code gen optimization to eliminate copy constructor and return
   // its first argument instead.
   if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
-    CXXConstructExpr::const_arg_iterator i = E->arg_begin();
-    EmitAggExpr((*i), Dest, false);
+    const Expr *Arg = E->getArg(0);
+    
+    if (const CXXBindTemporaryExpr *BindExpr = 
+          dyn_cast<CXXBindTemporaryExpr>(Arg))
+      Arg = BindExpr->getSubExpr();
+
+    EmitAggExpr(Arg, Dest, false);
     return;
   }
   if (Array) {
index 1288f566757962b12f0b378178552e50a99cff08..3663f0923d5c9f3826a8319f2518949a8590be88 100644 (file)
@@ -2652,6 +2652,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
       // Pass the argument.
       if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
         return true;
+      
+      Arg = MaybeBindToTemporary(Arg).takeAs<Expr>();
     } else {
       ParmVarDecl *Param = FDecl->getParamDecl(i);
 
index 87ca9ca7d421425331db7b7eb0ca0ff8af34c644..4f65e462d426e66628344b00527f85029dc6db92 100644 (file)
@@ -162,6 +162,29 @@ C::C()
   
   // CHECK: call void @_ZN6PR50771BD1Ev
 }
+}
+
+A f8() {
+  // CHECK: call void @_ZN1AC1Ev
+  // CHECK-NOT: call void @_ZN1AD1Ev
+  return A();
+  // CHECK: ret void
+}
 
+struct H {
+  H();
+  ~H();
+  H(const H&);
+};
 
+void f9(H h) {
+  // CHECK: call void @_ZN1HC1Ev
+  // CHECK: call void @_Z2f91H
+  // CHECK: call void @_ZN1HD1Ev
+  f9(H());
+  
+  // CHECK: call void @_ZN1HC1ERKS_
+  // CHECK: call void @_Z2f91H
+  // CHECK: call void @_ZN1HD1Ev
+  f9(h);
 }