]> granicus.if.org Git - clang/commitdiff
When we manage to re-use an expression during tree transformation (=
authorDouglas Gregor <dgregor@apple.com>
Sat, 10 Dec 2011 00:23:21 +0000 (00:23 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 10 Dec 2011 00:23:21 +0000 (00:23 +0000)
template instantiation), and that expression might produce a
temporary, invoke MaybeBindToTemporary. Otherwise, we forget to
destroy objects, release objects, etc. Fixes <rdar://problem/10531073>.

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

lib/Sema/TreeTransform.h
test/CodeGenCXX/instantiate-temporaries.cpp [new file with mode: 0644]
test/CodeGenObjCXX/arc.mm

index 3dc8136b78723785f11e0ded7d56fe1d57ba8ace..a30a0d036af6fd7354aac439bf79ae5e1361ef54 100644 (file)
@@ -6204,7 +6204,7 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
   if (!getDerived().AlwaysRebuild() &&
       Callee.get() == E->getCallee() &&
       !ArgChanged)
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);;
 
   // FIXME: Wrong source location information for the '('.
   SourceLocation FakeLParenLoc
@@ -6417,7 +6417,7 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
   if (!getDerived().AlwaysRebuild() &&
       OldT == NewT &&
       Init.get() == E->getInitializer())
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);
 
   // Note: the expression type doesn't necessarily match the
   // type-as-written, but that's okay, because it should always be
@@ -6612,7 +6612,7 @@ TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
 
   if (!getDerived().AlwaysRebuild() &&
       SubStmt.get() == E->getSubStmt())
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);
 
   return getDerived().RebuildStmtExpr(E->getLParenLoc(),
                                       SubStmt.get(),
@@ -6724,7 +6724,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
       Callee.get() == E->getCallee() &&
       First.get() == E->getArg(0) &&
       (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);
 
   return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
                                                  E->getOperatorLoc(),
@@ -6762,7 +6762,7 @@ TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
   if (!getDerived().AlwaysRebuild() &&
       Callee.get() == E->getCallee() &&
       !ArgChanged)
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);
 
   // FIXME: Wrong source location information for the '('.
   SourceLocation FakeLParenLoc
@@ -7966,7 +7966,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
     // If nothing changed, just retain the existing message send.
     if (!getDerived().AlwaysRebuild() &&
         ReceiverTypeInfo == E->getClassReceiverTypeInfo() && !ArgChanged)
-      return SemaRef.Owned(E);
+      return SemaRef.MaybeBindToTemporary(E);
 
     // Build a new class message send.
     SmallVector<SourceLocation, 16> SelLocs;
@@ -7991,7 +7991,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
   // If nothing changed, just retain the existing message send.
   if (!getDerived().AlwaysRebuild() &&
       Receiver.get() == E->getInstanceReceiver() && !ArgChanged)
-    return SemaRef.Owned(E);
+    return SemaRef.MaybeBindToTemporary(E);
   
   // Build a new instance message send.
   SmallVector<SourceLocation, 16> SelLocs;
@@ -8129,7 +8129,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
                                                oldBlock->param_begin(),
                                                oldBlock->param_size(),
                                                0, paramTypes, &params))
-    return true;
+    return ExprError();
 
   const FunctionType *exprFunctionType = E->getFunctionType();
   QualType exprResultType = exprFunctionType->getResultType();
diff --git a/test/CodeGenCXX/instantiate-temporaries.cpp b/test/CodeGenCXX/instantiate-temporaries.cpp
new file mode 100644 (file)
index 0000000..36d1071
--- /dev/null
@@ -0,0 +1,37 @@
+// RUN: %clang-cc1 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s
+
+struct X {
+  X();
+  ~X();
+};
+
+struct Y {
+  X get();
+};
+
+struct X2 {
+  X x;
+};
+
+template<typename T>
+void call() {
+  Y().get();
+}
+
+// CHECK: define weak_odr void @_Z4callIiEvv
+// CHECK: call void @_ZN1Y3getEv
+// CHECK-NEXT: call void @_ZN1XD1Ev
+// CHECK-NEXT: ret void
+template void call<int>();  
+
+template<typename T>
+void compound_literal() {
+  (X2){};
+}
+
+// CHECK: define weak_odr void @_Z16compound_literalIiEvv
+// CHECK: call void @_ZN1XC1Ev
+// CHECK-NEXT: call void @_ZN2X2D1Ev
+// CHECK-NEXT: ret void
+template void compound_literal<int>();  
+
index 8f3aa711d65d8c7179e51e04d5187f3cf173d144..6c6b8617ca1c931acabc9ced076f55ee40964067 100644 (file)
@@ -209,3 +209,18 @@ template void test37<Test37>(Test37 *a);
 // This bitcast is for the final release.
 // CHECK-LP64:      [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
 // CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]])
+
+template<typename T>
+void send_release() {
+  [Test37 array];
+}
+
+// CHECK: define weak_odr void @_Z12send_releaseIiEvv(
+// CHECK: call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @objc_release
+// CHECK-NEXT: ret void
+template void send_release<int>();