Skip to content

Commit e028ab7

Browse files
bruteforceboylanza
authored andcommitted
[CIR][Transforms] Fix flattening for TryOp with empty catch region (llvm#1646)
Currently, the following code snippet crashes during flattening, before lowering to llvm: ``` struct S { int a, b; }; void foo() { try { S s{1, 2}; } catch (...) { } } ``` Command to reproduce: ``` clang tmp.cpp -Xclang -fclangir -Xclang -emit-cir-flat -S -o - ``` The crash happens when flattening a TryOp with an empty catch region and [building catchers](https://github.com/llvm/clangir/blob/791c327da623e4cb1c193422f4b7a555f572b70a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp#L423). Something like: ``` "cir.try"() ({ }, { }) : () -> () ``` the crash happens at [`tryOp.isCatchAllOnly()`](https://github.com/llvm/clangir/blob/791c327da623e4cb1c193422f4b7a555f572b70a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp#L441C39-L441C61) to be specific, because the catch types attribute list is empty. The fix is simple - adding a check for an empty/non-existent catch region before building the catch clauses. This PR adds this fix and one test. **Side-note:** This enables `push_back` for `std::vector` to be lowered to llvm, for example: ``` #include <vector> void foo() { std::vector<int> v; v.push_back(1); } ```
1 parent 854eb91 commit e028ab7

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,10 @@ class CIRTryOpFlattening : public mlir::OpRewritePattern<cir::TryOp> {
435435
if (auto tryBodyYield = dyn_cast<cir::YieldOp>(afterBody->getTerminator()))
436436
rewriter.replaceOpWithNewOp<cir::BrOp>(tryBodyYield, afterTry);
437437

438+
mlir::ArrayAttr catches = tryOp.getCatchTypesAttr();
439+
if (!catches || catches.empty())
440+
return;
441+
438442
// Start the landing pad by getting the inflight exception information.
439443
mlir::Block *nextDispatcher =
440444
buildLandingPads(tryOp, rewriter, beforeCatch, afterTry, callsToRewrite,

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir
22
// RUN: FileCheck --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -mconstructor-aliases -fclangir -emit-cir-flat %s -o %t.cir.flat
4+
// RUN: FileCheck --check-prefix=FLAT --input-file=%t.cir.flat %s
35

46
double division(int a, int b);
57

@@ -168,3 +170,38 @@ void tc7() {
168170
// CHECK: cir.return
169171
// CHECK: }
170172
// CHECK: }
173+
174+
struct S2 {
175+
int a, b;
176+
};
177+
178+
void tc8() {
179+
try {
180+
S2 s{1, 2};
181+
} catch (...) {
182+
}
183+
}
184+
185+
// CHECK: cir.scope {
186+
// CHECK: %[[V0:.*]] = cir.alloca !rec_S2, !cir.ptr<!rec_S2>, ["s"] {alignment = 4 : i64}
187+
// CHECK: cir.try {
188+
// CHECK: %[[V1:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s32i}> : !rec_S2
189+
// CHECK: cir.store align(4) %[[V1]], %[[V0]] : !rec_S2, !cir.ptr<!rec_S2>
190+
// CHECK: cir.yield
191+
// CHECK: }
192+
// CHECK: }
193+
194+
// FLAT: cir.func @_Z3tc8v()
195+
// FLAT: %[[V0:.*]] = cir.alloca !rec_S2, !cir.ptr<!rec_S2>, ["s"] {alignment = 4 : i64}
196+
// FLAT: cir.br ^bb[[#B1:]]
197+
// FLAT: ^bb[[#B1]]:
198+
// FLAT: cir.br ^bb[[#B2:]]
199+
// FLAT: ^bb[[#B2]]:
200+
// FLAT: %[[V1:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s32i}> : !rec_S2
201+
// FLAT: cir.store align(4) %[[V1]], %[[V0]] : !rec_S2, !cir.ptr<!rec_S2>
202+
// FLAT: cir.br ^bb[[#B3:]]
203+
// FLAT: ^bb[[#B3]]:
204+
// FLAT: cir.br ^bb[[#B4:]]
205+
// FLAT: ^bb[[#B4]]:
206+
// FLAT: cir.return
207+
// FLAT: }

0 commit comments

Comments
 (0)