1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 12:02:58 +02:00
llvm-mirror/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll
David Majnemer 1fad37bd8d [WinEH] Don't miscompile cleanups which conditionally unwind to caller
A cleanup can have paths which unwind or end up in unreachable.
If there is an unreachable path *and* a path which unwinds to caller,
we would mistakenly inject an unwind path to a catchswitch on the
unreachable path.  This results in a verifier assertion firing because
the cleanup unwinds to two different places: to the caller and to the
catchswitch.

This occured because we used getCleanupRetUnwindDest to determine if the
cleanuppad had no cleanuprets.
This is incorrect, getCleanupRetUnwindDest returns null for cleanuprets
which unwind to caller.

llvm-svn: 258651
2016-01-23 23:54:33 +00:00

96 lines
2.5 KiB
LLVM

; RUN: opt -S -winehprepare < %s | FileCheck %s
target triple = "x86_64-pc-windows-msvc"
; CHECK-LABEL: @test1(
define void @test1(i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @f()
to label %try.cont unwind label %cleanup.bb
; CHECK: entry:
; CHECK: [[catchswitch_entry:.*]]:
; CHECK-NEXT: %[[cs0:.*]] = catchswitch within none [label %[[catchpad:.*]]] unwind to caller
; CHECK: [[catchpad]]:
; CHECK-NEXT: %[[cp0:.*]] = catchpad within %[[cs0]] [i8* null, i32 64, i8* null]
; CHECK-NEXT: unreachable
try.cont:
invoke void @f()
to label %exit unwind label %catchswitch.bb
cleanup.bb:
%cleanup = cleanuppad within none []
br i1 %b, label %left, label %right
left:
call void @exit(i32 0) [ "funclet"(token %cleanup) ]
unreachable
right:
call void @exit(i32 1) [ "funclet"(token %cleanup) ]
unreachable
catchswitch.bb:
%cs = catchswitch within none [label %catchpad.bb] unwind to caller
; CHECK: catchpad.bb:
; CHECK-NEXT: %catch = catchpad within %cs [i8* null, i32 64, i8* null]
; CHECK: [[catchswitch_catch:.*]]:
; CHECK-NEXT: %[[cs1:.*]] = catchswitch within %catch [label %[[catchpad_catch:.*]]] unwind to caller
; CHECK: [[catchpad_catch]]:
; CHECK-NEXT: %[[cp1:.*]] = catchpad within %[[cs1]] [i8* null, i32 64, i8* null]
; CHECK-NEXT: unreachable
; CHECK: nested.cleanup.bb:
; CHECK-NEXT: %nested.cleanup = cleanuppad within %catch []
; CHECK-NEXT: call void @exit(i32 2) [ "funclet"(token %nested.cleanup) ]
; CHECK-NEXT: cleanupret from %nested.cleanup unwind label %[[catchswitch_catch]]
catchpad.bb:
%catch = catchpad within %cs [i8* null, i32 64, i8* null]
invoke void @f() [ "funclet"(token %catch) ]
to label %unreachable unwind label %nested.cleanup.bb
nested.cleanup.bb:
%nested.cleanup = cleanuppad within %catch []
call void @exit(i32 2) [ "funclet"(token %nested.cleanup) ]
unreachable
unreachable:
unreachable
exit:
unreachable
}
; CHECK-LABEL: @test2(
define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @f()
to label %invoke.cont unwind label %ehcleanup
invoke.cont:
unreachable
ehcleanup:
%cp = cleanuppad within none []
br i1 %B, label %ret, label %if.then
if.then:
call void @exit(i32 1) [ "funclet"(token %cp) ]
unreachable
ret:
cleanupret from %cp unwind to caller
}
; CHECK: call void @exit(i32 1) [ "funclet"(token %cp) ]
; CHECK-NEXT: unreachable
declare void @f()
declare void @exit(i32) nounwind noreturn
declare i32 @__CxxFrameHandler3(...)