ahatanak created this revision.
ahatanak added reviewers: rsmith, rjmccall.
ahatanak added a project: clang.
Herald added subscribers: ributzka, dexonsmith, jkorous.

The temporary of the true operand shouldn't be destructed when the false 
operand is evaluated and throws.

rdar://problem/64829372


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82999

Files:
  clang/lib/CodeGen/CGDecl.cpp
  clang/test/CodeGenCXX/exceptions.cpp
  clang/test/CodeGenCXX/temporaries.cpp

Index: clang/test/CodeGenCXX/temporaries.cpp
===================================================================
--- clang/test/CodeGenCXX/temporaries.cpp
+++ clang/test/CodeGenCXX/temporaries.cpp
@@ -817,15 +817,19 @@
 
   // CHECK-LABEL: define {{.*}} @_ZN11Conditional1fEb(
   void f(bool b) {
+    // CHECK: store i1 false, i1* %{{.*}},
     // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]],
+    // CHECK: store i1 false, i1* %{{.*}},
     // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
     // CHECK: br i1
     //
     // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
+    // CHECK: store i1 true, i1* %{{.*}},
     // CHECK: store i1 true, i1* %[[CLEANUP_B]],
     // CHECK: br label
     //
     // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
+    // CHECK: store i1 true, i1* %{{.*}},
     // CHECK: store i1 true, i1* %[[CLEANUP_C]],
     // CHECK: br label
     A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
@@ -847,15 +851,19 @@
   struct D { A &&a; };
   // CHECK-LABEL: define {{.*}} @_ZN11Conditional10f_indirectEb(
   void f_indirect(bool b) {
+    // CHECK-CXX17: store i1 false, i1* %{{.*}},
     // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]],
+    // CHECK-CXX17: store i1 false, i1* %{{.*}},
     // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
     // CHECK: br i1
     //
     // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
+    // CHECK-CXX17: store i1 true, i1* %{{.*}},
     // CHECK: store i1 true, i1* %[[CLEANUP_B]],
     // CHECK: br label
     //
     // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
+    // CHECK-CXX17: store i1 true, i1* %{{.*}},
     // CHECK: store i1 true, i1* %[[CLEANUP_C]],
     // CHECK: br label
     D d = b ? D{B()} : D{C()};
Index: clang/test/CodeGenCXX/exceptions.cpp
===================================================================
--- clang/test/CodeGenCXX/exceptions.cpp
+++ clang/test/CodeGenCXX/exceptions.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -std=c++98 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s
 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s
 
+// CHECK: %[[STRUCT_TEST13_A:.*]] = type { i32, i32 }
+
 typedef __typeof(sizeof(0)) size_t;
 
 // Declare the reserved global placement new.
@@ -594,4 +596,45 @@
   // CHECK11:       call void @_ZN6test121AdlEPvS1_(i8* [[PTR]], i8* [[PTR]])
 }
 
+namespace test13 {
+
+struct A {
+  A();
+  ~A();
+  int a, b;
+};
+
+// CHECK: define void @_ZN6test134testEi(
+// CHECK: %[[REF_TMP:.*]] = alloca %[[STRUCT_TEST13_A]], align 4
+// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1
+// CHECK: %[[CLEANUP_COND1:.*]] = alloca i1, align 1
+// CHECK: %[[REF_TMP2:.*]] = alloca %[[STRUCT_TEST13_A]], align 4
+// CHECK: %[[CLEANUP_COND3:.*]] = alloca i1, align 1
+// CHECK: %[[CLEANUP_COND4:.*]] = alloca i1, align 1
+
+// CHECK: call void @_ZN6test131AC1Ev(%[[STRUCT_TEST13_A]]* %[[REF_TMP]])
+// CHECK: store i1 true, i1* %[[CLEANUP_COND]], align 1
+// CHECK: store i1 true, i1* %[[CLEANUP_COND1]], align 1
+// CHECK: br
+
+// CHECK: invoke void @_ZN6test131AC1Ev(%[[STRUCT_TEST13_A]]* %[[REF_TMP2]])
+
+// CHECK: store i1 true, i1* %[[CLEANUP_COND3]], align 1
+// CHECK: store i1 true, i1* %[[CLEANUP_COND4]], align 1
+// CHECK: br
+
+//   Check the flag before destructing the temporary.
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: %[[CLEANUP_IS_ACTIVE:.*]] = load i1, i1* %[[CLEANUP_COND]], align 1
+// CHECK: br i1 %[[CLEANUP_IS_ACTIVE]],
+
+// CHECK: void @_ZN6test131AD1Ev(%[[STRUCT_TEST13_A]]* %[[REF_TMP]])
+
+void test(int c) {
+  const A &s = c ? static_cast<const A &>(A()) : static_cast<const A &>(A());
+}
+
+}
+
 // CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind }
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -2095,7 +2095,7 @@
   // FIXME: When popping normal cleanups, we need to keep this EH cleanup
   // around in case a temporary's destructor throws an exception.
   if (cleanupKind & EHCleanup)
-    EHStack.pushCleanup<DestroyObject>(
+    pushFullExprCleanup<DestroyObject>(
         static_cast<CleanupKind>(cleanupKind & ~NormalCleanup), addr, type,
         destroyer, useEHCleanupForArray);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to