llvm.org GIT mirror llvm / 50a24fa
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@258651 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 4 years ago
2 changed file(s) with 26 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
10711071 if (!CleanupPad)
10721072 continue;
10731073 // Skip over any cleanups have unwind targets, they do not need this.
1074 if (getCleanupRetUnwindDest(CleanupPad) != nullptr)
1074 if (any_of(CleanupPad->users(),
1075 [](const User *U) { return isa(U); }))
10751076 continue;
10761077 // Walk the blocks within the cleanup which end in 'unreachable'.
10771078 // We will replace the unreachable instruction with a cleanupret;
6464 unreachable
6565 }
6666
67 ; CHECK-LABEL: @test2(
68 define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
69 entry:
70 invoke void @f()
71 to label %invoke.cont unwind label %ehcleanup
72
73 invoke.cont:
74 unreachable
75
76 ehcleanup:
77 %cp = cleanuppad within none []
78 br i1 %B, label %ret, label %if.then
79
80 if.then:
81 call void @exit(i32 1) [ "funclet"(token %cp) ]
82 unreachable
83
84 ret:
85 cleanupret from %cp unwind to caller
86 }
87
88 ; CHECK: call void @exit(i32 1) [ "funclet"(token %cp) ]
89 ; CHECK-NEXT: unreachable
90
6791 declare void @f()
6892 declare void @exit(i32) nounwind noreturn
6993