From 58763ac57eae700db403d6c99b4fcb87cf323409 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Wed, 14 May 2025 17:40:54 +0300 Subject: [PATCH] [CIR][CodeGen] Emit dtor properly for objects in TernaryOp --- clang/lib/CIR/CodeGen/CIRGenException.cpp | 2 + clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 2 + clang/test/CIR/CodeGen/dtors.cpp | 55 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 022607dc3dd6..461c7f5428ef 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -803,6 +803,8 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si, "one per call: expected empty region at this point"); dispatchBlock = builder.createBlock(&callWithExceptionCtx.getCleanup()); builder.createYield(callWithExceptionCtx.getLoc()); + } else if (currLexScope && currLexScope->isTernary()) { + break; } else { // Usually coming from general cir.scope cleanups that aren't // tried to a specific throwing call. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 72eeb3ff34cb..5ebba2078d93 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2678,6 +2678,7 @@ mlir::Value ScalarExprEmitter::VisitBinLAnd(const clang::BinaryOperator *E) { auto res = b.create(Loc, Builder.getFalseAttr()); b.create(Loc, res.getRes()); }); + LexScope.ForceCleanup(); B.create(Loc, res.getResult()); }, /*falseBuilder*/ @@ -2773,6 +2774,7 @@ mlir::Value ScalarExprEmitter::VisitBinLOr(const clang::BinaryOperator *E) { auto res = b.create(Loc, Builder.getFalseAttr()); b.create(Loc, res.getRes()); }); + LexScope.ForceCleanup(); B.create(Loc, res.getResult()); }); diff --git a/clang/test/CIR/CodeGen/dtors.cpp b/clang/test/CIR/CodeGen/dtors.cpp index 49f341eeffce..0466b9881822 100644 --- a/clang/test/CIR/CodeGen/dtors.cpp +++ b/clang/test/CIR/CodeGen/dtors.cpp @@ -50,6 +50,61 @@ class B : public A // CHECK: cir.return // CHECK: } +struct X { + int a; + X(int a) : a(a) {} + ~X() {} +}; + +bool foo(const X &) { return false; } +bool bar() { return foo(1) || foo(2); } + +// CHECK: cir.func @_Z3barv() +// CHECK: %[[V0:.*]] = cir.alloca !cir.bool, !cir.ptr, ["__retval"] {alignment = 1 : i64} +// CHECK: cir.scope { +// CHECK: %[[V2:.*]] = cir.alloca !rec_X, !cir.ptr, ["ref.tmp0"] {alignment = 4 : i64} +// CHECK: %[[V3:.*]] = cir.const #cir.int<1> : !s32i +// CHECK: cir.call @_ZN1XC2Ei(%[[V2]], %[[V3]]) : (!cir.ptr, !s32i) -> () +// CHECK: %[[V4:.*]] = cir.call @_Z3fooRK1X(%[[V2]]) : (!cir.ptr) -> !cir.bool +// CHECK: %[[V5:.*]] = cir.ternary(%[[V4]], true { +// CHECK: %[[V6:.*]] = cir.const #true +// CHECK: cir.yield %[[V6]] : !cir.bool +// CHECK: }, false { +// CHECK: %[[V6:.*]] = cir.alloca !rec_X, !cir.ptr, ["ref.tmp1"] {alignment = 4 : i64} +// CHECK: %[[V7:.*]] = cir.const #cir.int<2> : !s32i +// CHECK: cir.call @_ZN1XC2Ei(%[[V6]], %[[V7]]) : (!cir.ptr, !s32i) -> () +// CHECK: %[[V8:.*]] = cir.call @_Z3fooRK1X(%[[V6]]) : (!cir.ptr) -> !cir.bool +// CHECK: %[[V9:.*]] = cir.ternary(%[[V8]], true { +// CHECK: %[[V10:.*]] = cir.const #true +// CHECK: cir.yield %[[V10]] : !cir.bool +// CHECK: }, false { +// CHECK: %[[V10:.*]] = cir.const #false +// CHECK: cir.yield %[[V10]] : !cir.bool +// CHECK: }) : (!cir.bool) -> !cir.bool +// CHECK: cir.call @_ZN1XD2Ev(%[[V6]]) : (!cir.ptr) -> () +// CHECK: cir.yield %[[V9]] : !cir.bool +// CHECK: }) : (!cir.bool) -> !cir.bool +// CHECK: cir.store %[[V5]], %[[V0]] : !cir.bool, !cir.ptr +// CHECK: cir.call @_ZN1XD2Ev(%[[V2]]) : (!cir.ptr) -> () +// CHECK: } +// CHECK: %[[V1:.*]] = cir.load %[[V0]] : !cir.ptr, !cir.bool +// CHECK: cir.return %[[V1]] : !cir.bool +// CHECK: } + +bool bar2() { return foo(1) && foo(2); } + +// CHECK: cir.func @_Z4bar2v() +// CHECK: cir.alloca !rec_X, !cir.ptr +// CHECK: {{.*}} = cir.ternary({{.*}}, true { +// CHECK: cir.alloca !rec_X, !cir.ptr +// CHECK: cir.call @_ZN1XD2Ev +// CHECK: cir.yield +// CHECK: }, false { +// CHECK: {{.*}} = cir.const #false +// CHECK: cir.yield +// CHECK: }) : (!cir.bool) -> !cir.bool +// CHECK: cir.call @_ZN1XD2Ev + // @B::~B() #1 definition call into base @A::~A() // CHECK: cir.func linkonce_odr @_ZN1BD2Ev{{.*}}{ // CHECK: cir.call @_ZN1AD2Ev(