Skip to content

Commit 9f6742f

Browse files
[CIR][CodeGen] Fix crash during exception cleanup (#1566)
Currently, the following code snippet fails with a crash during CodeGen ``` class C { public: ~C(); void operator=(C); }; void d() { C a, b; a = b; } ``` with error: ``` mlir::Block* clang::CIRGen::CIRGenFunction::getEHResumeBlock(bool, cir::TryOp): Assertion `tryOp && "expected available cir.try"' failed. ``` in CIRGenCleanup [these lines](https://github.com/llvm/clangir/blob/204c03efbe898c9f64e477937d869767fdfb1310/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp#L615C1-L617C6) don't check if there is a TryOp when at the end of the scope chain before [getEHResumeBlock](https://github.com/llvm/clangir/blob/204c03efbe898c9f64e477937d869767fdfb1310/clang/lib/CIR/CodeGen/CIRGenException.cpp#L764) is called causing the crash, because it contains an assertion. This PR fixes this and adds a simple test for a case like this.
1 parent 4c4a762 commit 9f6742f

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenCleanup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,10 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
613613
// Emit the EH cleanup if required.
614614
if (RequiresEHCleanup) {
615615
cir::TryOp tryOp = ehEntry->getParentOp()->getParentOfType<cir::TryOp>();
616+
617+
if (EHParent == EHStack.stable_end() && !tryOp)
618+
return;
619+
616620
auto *nextAction = getEHDispatchBlock(EHParent, tryOp);
617621
(void)nextAction;
618622

clang/test/CIR/CodeGen/try-catch-dtors.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,37 @@ void bar() {
339339
// CIR: cir.store %[[V3]], %[[V1]] : !s32i, !cir.ptr<!s32i>
340340
// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr<!ty_A>) -> () extra(#fn_attr)
341341
// CIR: cir.return
342+
343+
class C {
344+
public:
345+
~C();
346+
void operator=(C);
347+
};
348+
349+
void d() {
350+
C a, b;
351+
a = b;
352+
}
353+
354+
// CIR: %[[V0:.*]] = cir.alloca !ty_C, !cir.ptr<!ty_C>, ["a"] {alignment = 1 : i64}
355+
// CIR: %[[V1:.*]] = cir.alloca !ty_C, !cir.ptr<!ty_C>, ["b"] {alignment = 1 : i64}
356+
// CIR: cir.scope {
357+
// CIR: %[[V2:.*]] = cir.alloca !ty_C, !cir.ptr<!ty_C>, ["agg.tmp0"] {alignment = 1 : i64}
358+
// CIR: cir.call @_ZN1CC2ERKS_(%[[V2]], %[[V1]]) : (!cir.ptr<!ty_C>, !cir.ptr<!ty_C>) -> () extra(#fn_attr)
359+
// CIR: %[[V3:.*]] = cir.load %[[V2]] : !cir.ptr<!ty_C>, !ty_C
360+
// CIR: cir.try synthetic cleanup {
361+
// CIR: cir.call exception @_ZN1CaSES_(%[[V0]], %[[V3]]) : (!cir.ptr<!ty_C>, !ty_C) -> () cleanup {
362+
// CIR: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
363+
// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
364+
// CIR: cir.yield
365+
// CIR: }
366+
// CIR: cir.yield
367+
// CIR: } catch [#cir.unwind {
368+
// CIR: cir.resume
369+
// CIR: }]
370+
// CIR: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
371+
// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
372+
// CIR: }
373+
// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
374+
// CIR: cir.call @_ZN1CD1Ev(%[[V0]]) : (!cir.ptr<!ty_C>) -> () extra(#fn_attr)
375+
// CIR: cir.return

0 commit comments

Comments
 (0)