]> granicus.if.org Git - clang/commitdiff
Reset the lifetime-managed flag between emission of the agg conditional
authorJohn McCall <rjmccall@apple.com>
Wed, 17 Nov 2010 00:07:33 +0000 (00:07 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 17 Nov 2010 00:07:33 +0000 (00:07 +0000)
branches.  Fixes PR8623.

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

lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGValue.h
test/CodeGenCXX/temporaries.cpp

index 00cfb21447228dfd85bc7144176602f3335be9a9..308520aadd4c660bbd2a2205f8bebee91cc61c71 100644 (file)
@@ -394,8 +394,8 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
   CGF.BeginConditionalBranch();
   CGF.EmitBlock(LHSBlock);
 
-  // Handle the GNU extension for missing LHS.
-  assert(E->getLHS() && "Must have LHS for aggregate value");
+  // Save whether the destination's lifetime is externally managed.
+  bool DestLifetimeManaged = Dest.isLifetimeExternallyManaged();
 
   Visit(E->getLHS());
   CGF.EndConditionalBranch();
@@ -404,6 +404,12 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
   CGF.BeginConditionalBranch();
   CGF.EmitBlock(RHSBlock);
 
+  // If the result of an agg expression is unused, then the emission
+  // of the LHS might need to create a destination slot.  That's fine
+  // with us, and we can safely emit the RHS into the same slot, but
+  // we shouldn't claim that its lifetime is externally managed.
+  Dest.setLifetimeExternallyManaged(DestLifetimeManaged);
+
   Visit(E->getRHS());
   CGF.EndConditionalBranch();
   CGF.EmitBranch(ContBlock);
index a000b223311ea31f74a45f01285dfe2aeeb56eb4..bb98c3cb2372375e832210ea874c8ed7d1a7c164 100644 (file)
@@ -379,8 +379,8 @@ public:
   bool isLifetimeExternallyManaged() const {
     return LifetimeFlag;
   }
-  void setLifetimeExternallyManaged() {
-    LifetimeFlag = true;
+  void setLifetimeExternallyManaged(bool Managed = true) {
+    LifetimeFlag = Managed;
   }
 
   bool isVolatile() const {
index 3bf1dbd9f4431d1c535e98b3b5a5cfff2ee9896d..74b11fdb8e917e07fb6491d9a1817c6438ab48e0 100644 (file)
@@ -493,3 +493,35 @@ namespace Elision {
     A(*x).foo();
   }
 }
+
+namespace PR8623 {
+  struct A { A(int); ~A(); };
+
+  // CHECK: define void @_ZN6PR86233fooEb(
+  void foo(bool b) {
+    // CHECK:      [[TMP:%.*]] = alloca [[A:%.*]], align 1
+    // CHECK-NEXT: [[LCONS:%.*]] = alloca i1
+    // CHECK-NEXT: [[RCONS:%.*]] = alloca i1
+    // CHECK-NEXT: store i1 false, i1* [[RCONS]]
+    // CHECK-NEXT: store i1 false, i1* [[LCONS]]
+    // CHECK:      br i1
+    // CHECK:      call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2)
+    // CHECK-NEXT: store i1 true, i1* [[LCONS]]
+    // CHECK-NEXT: br label
+    // CHECK:      call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3)
+    // CHECK-NEXT: store i1 true, i1* [[RCONS]]
+    // CHECK-NEXT: br label
+    // CHECK:      load i1* [[RCONS]]
+    // CHECK-NEXT: br i1
+    // CHECK:      call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
+    // CHECK-NEXT: store i1 false, i1* [[RCONS]]
+    // CHECK-NEXT: br label
+    // CHECK:      load i1* [[LCONS]]
+    // CHECK-NEXT: br i1
+    // CHECK:      call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
+    // CHECK-NEXT: store i1 false, i1* [[LCONS]]
+    // CHECK-NEXT: br label
+    // CHECK:      ret void
+    b ? A(2) : A(3);
+  }
+}