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