diff options
author | John McCall <rjmccall@apple.com> | 2012-06-15 05:27:05 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-06-15 05:27:05 +0000 |
commit | d8d00be632593eae7495b50fa869b69ff793dce2 (patch) | |
tree | fcdbf89b8867075a5a24455dca23499bc0ed2202 /clang/test/CodeGenCXX/exceptions.cpp | |
parent | e6799ddae83082a494f968cab205ef8754f82e64 (diff) | |
download | bcm5719-llvm-d8d00be632593eae7495b50fa869b69ff793dce2.tar.gz bcm5719-llvm-d8d00be632593eae7495b50fa869b69ff793dce2.zip |
It turns out that implementing the rethrow-on-fallthrough
semantics of a ctor/dtor function-try-block catch handler
by pushing a normal cleanup is not just overkill but actually
actively wrong when the handler contains an explicit return
(which is only legal in a dtor). Just emit the rethrow as
ordinary code at the fallthrough point. Fixes PR13102.
llvm-svn: 158488
Diffstat (limited to 'clang/test/CodeGenCXX/exceptions.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/exceptions.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp index 079c1e5e725..8c20c9e9ce2 100644 --- a/clang/test/CodeGenCXX/exceptions.cpp +++ b/clang/test/CodeGenCXX/exceptions.cpp @@ -414,3 +414,39 @@ namespace test9 { // CHECK: [[TEST9_NEW:%.*]] = call noalias i8* @_Znam // CHECK: call void @_ZdaPv(i8* [[TEST9_NEW]]) } + +// In a destructor with a function-try-block, a return statement in a +// catch handler behaves differently from running off the end of the +// catch handler. PR13102. +namespace test10 { + extern void cleanup(); + extern bool suppress; + + struct A { ~A(); }; + A::~A() try { cleanup(); } catch (...) { return; } + // CHECK: define void @_ZN6test101AD1Ev( + // CHECK: invoke void @_ZN6test107cleanupEv() + // CHECK-NOT: rethrow + // CHECK: ret void + + struct B { ~B(); }; + B::~B() try { cleanup(); } catch (...) {} + // CHECK: define void @_ZN6test101BD1Ev( + // CHECK: invoke void @_ZN6test107cleanupEv() + // CHECK: call i8* @__cxa_begin_catch + // CHECK-NEXT: invoke void @__cxa_rethrow() + // CHECK: unreachable + + struct C { ~C(); }; + C::~C() try { cleanup(); } catch (...) { if (suppress) return; } + // CHECK: define void @_ZN6test101CD1Ev( + // CHECK: invoke void @_ZN6test107cleanupEv() + // CHECK: call i8* @__cxa_begin_catch + // CHECK-NEXT: load i8* @_ZN6test108suppressE, align 1 + // CHECK-NEXT: trunc + // CHECK-NEXT: br i1 + // CHECK: call void @__cxa_end_catch() + // CHECK-NEXT: br label + // CHECK: invoke void @__cxa_rethrow() + // CHECK: unreachable +} |