diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/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( + pushFullExprCleanup( static_cast(cleanupKind & ~NormalCleanup), addr, type, destroyer, useEHCleanupForArray); diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp --- a/clang/test/CodeGenCXX/exceptions.cpp +++ b/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(A()) : static_cast(A()); +} + +} + // CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp --- a/clang/test/CodeGenCXX/temporaries.cpp +++ b/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(B()) : static_cast(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()};