BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
calculateExplicitCXXStateNumbers(FuncInfo, *CleanupBlock, ParentState);
// Anything unwinding through CleanupEndPadInst is in ParentState.
+ FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
for (const BasicBlock *PredBlock : predecessors(&BB))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, ParentState);
!isa<CleanupEndPadInst>(VisitingHead)) {
// Mark this as a funclet head as a member of itself.
FuncletBlocks[Visiting].insert(Visiting);
- // Queue exits with the parent color.
+ // Queue exits (i.e. successors of rets/endpads) with the parent color.
+ // Skip any exits that are catchendpads, since the parent color must then
+ // represent one of the catches chained to that catchendpad, but the
+ // catchendpad should get the color of the common parent of all its
+ // chained catches (i.e. the grandparent color of the current pad).
+ // We don't need to worry abou catchendpads going unvisited, since the
+ // catches chained to them must have unwind edges to them by which we will
+ // visit them.
for (User *U : VisitingHead->users()) {
if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
for (BasicBlock *Succ : successors(Exit->getParent()))
- if (BlockColors[Succ].insert(Color).second)
- Worklist.push_back({Succ, Color});
+ if (!isa<CatchEndPadInst>(*Succ->getFirstNonPHI()))
+ if (BlockColors[Succ].insert(Color).second)
+ Worklist.push_back({Succ, Color});
}
}
// Handle CatchPad specially since its successors need different colors.
unreachable
}
+define void @test14() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ invoke void @f()
+ to label %exit unwind label %catch1.pad
+catch1.pad:
+ %catch1 = catchpad [i32 1]
+ to label %catch1.body unwind label %catch2.pad
+catch1.body:
+ invoke void @h(i32 1)
+ to label %catch1.body2 unwind label %catch.end
+catch1.body2:
+ invoke void @f()
+ to label %catch1.ret unwind label %cleanup1.pad
+cleanup1.pad:
+ %cleanup1 = cleanuppad []
+ call void @f()
+ cleanupret %cleanup1 unwind label %catch.end
+catch1.ret:
+ catchret %catch1 to label %exit
+catch2.pad:
+ %catch2 = catchpad [i32 2]
+ to label %catch2.body unwind label %catch.end
+catch2.body:
+ invoke void @h(i32 2)
+ to label %catch2.body2 unwind label %catch.end
+catch2.body2:
+ invoke void @f()
+ to label %catch2.ret unwind label %cleanup2.pad
+cleanup2.pad:
+ %cleanup2 = cleanuppad []
+ call void @f()
+ cleanupret %cleanup2 unwind label %catch.end
+catch2.ret:
+ catchret %catch2 to label %exit
+catch.end:
+ catchendpad unwind to caller
+exit:
+ ret void
+}
+; Make sure we don't clone the catchendpad even though the
+; cleanupendpads targeting it would naively imply that it
+; should get their respective parent colors (catch1 and catch2),
+; as well as its properly getting the root function color. The
+; references from the invokes ensure that if we did make clones
+; for each catch, they'd be reachable, as those invokes would get
+; rewritten
+; CHECK-LABEL: define void @test14()
+; CHECK-NOT: catchendpad
+; CHECK: invoke void @h(i32 1)
+; CHECK-NEXT: unwind label %catch.end
+; CHECK-NOT: catchendpad
+; CHECK: invoke void @h(i32 2)
+; CHECK-NEXT: unwind label %catch.end
+; CHECK-NOT: catchendpad
+; CHECK: catch.end:
+; CHECK-NEXT: catchendpad
+; CHECK-NOT: catchendpad
+
+;; Debug info (from test12)
+
; Make sure the DISubprogram doesn't get cloned
; CHECK-LABEL: !llvm.module.flags
; CHECK-NOT: !DISubprogram