Skip to content

Commit d48d459

Browse files
[CIR][CodeGen] Fix extra Yieldop case during try-catch generation (#1370)
Currently, trying to generate CIR for the following code snippet `yield.cpp` fails. Using `bin/clang++ yield.cpp -Xclang -fclangir -Xclang -emit-cir -S -o -`: ``` struct S { S() {}; int a; }; void foo() { try { S s; } catch (...) { foo(); } } ``` The error: ``` loc("yield.cpp":6:6): error: 'cir.yield' op must be the last operation in the parent block ``` There is an extra YieldOp! The CIR dump before verification looks something like: ``` "cir.scope"() ({ %0 = "cir.alloca"() <{alignment = 4 : i64, allocaType = !cir.struct<struct "S" {!cir.int<s, 32>} #cir.record.decl.ast>, ast = #cir.var.decl.ast, init, name = "s"}> : () -> !cir.ptr<!cir.struct<struct "S" {!cir.int<s, 32>} #cir.record.decl.ast>> "cir.try"() <{catch_types = [#cir.all]}> ({ "cir.call"(%0) <{callee = @_ZN1SC1Ev, calling_conv = 1 : i32, exception, extra_attrs = #cir<extra({})>, side_effect = 1 : i32}> ({ "cir.yield"() : () -> () }) : (!cir.ptr<!cir.struct<struct "S" {!cir.int<s, 32>} #cir.record.decl.ast>>) -> () "cir.yield"() : () -> () }, { %1 = "cir.catch_param"() : () -> !cir.ptr<!cir.void> "cir.call"() <{ast = #cir.call.expr.ast, callee = @_Z3foov, calling_conv = 1 : i32, exception, extra_attrs = #cir<extra({})>, side_effect = 1 : i32}> ({ "cir.yield"() : () -> () "cir.yield"() : () -> () <--- **DUPLICATE** }) : () -> () "cir.yield"() : () -> () }) : () -> () "cir.yield"() : () -> () }, { }) : () -> () ``` This PR adds a check for an already existing terminator before creating a YieldOp during the cleanup.
1 parent de13703 commit d48d459

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,8 @@ struct CallEndCatch final : EHScopeStack::Cleanup {
718718
// here. For CIR, just let it pass since the cleanup is going
719719
// to be emitted on a later pass when lowering the catch region.
720720
// CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
721-
CGF.getBuilder().create<cir::YieldOp>(*CGF.currSrcLoc);
721+
if (!CGF.getBuilder().getBlock()->mightHaveTerminator())
722+
CGF.getBuilder().create<cir::YieldOp>(*CGF.currSrcLoc);
722723
}
723724
};
724725
} // namespace

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

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,26 +82,49 @@ unsigned long long tc3() {
8282
return z;
8383
}
8484

85-
// CIR: cir.func @_Z3tc4v()
85+
// CHECK: cir.func @_Z3tc4v()
8686
unsigned long long tc4() {
8787
int x = 50, y = 3;
8888
unsigned long long z;
8989

90-
// CIR-NOT: cir.try
90+
// CHECK-NOT: cir.try
9191
try {
9292
int a = 4;
9393
a++;
9494

95-
// CIR: cir.scope {
96-
// CIR: cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
97-
// CIR-NOT: cir.alloca !cir.ptr<!cir.eh.info>
98-
// CIR: cir.const #cir.int<4> : !s32i
99-
// CIR: cir.unary(inc,
100-
// CIR: cir.store %11, %8 : !s32i, !cir.ptr<!s32i>
95+
// CHECK: cir.scope {
96+
// CHECK: cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
97+
// CHECK-NOT: cir.alloca !cir.ptr<!cir.eh.info>
98+
// CHECK: cir.const #cir.int<4> : !s32i
99+
// CHECK: cir.unary(inc,
100+
// CHECK: cir.store %11, %8 : !s32i, !cir.ptr<!s32i>
101101
} catch (int idx) {
102102
z = 98;
103103
idx++;
104104
}
105105

106106
return z;
107-
}
107+
}
108+
109+
struct S {
110+
S() {};
111+
int a;
112+
};
113+
114+
// CHECK: cir.func @_Z3tc5v()
115+
void tc5() {
116+
try {
117+
S s;
118+
} catch (...) {
119+
tc5();
120+
}
121+
}
122+
123+
// CHECK: cir.try {
124+
// CHECK: cir.call exception @_ZN1SC2Ev({{.*}}) : (!cir.ptr<!ty_S>) -> ()
125+
// CHECK: cir.yield
126+
// CHECK: } catch [type #cir.all {
127+
// CHECK: {{.*}} = cir.catch_param -> !cir.ptr<!void>
128+
// CHECK: cir.call exception @_Z3tc5v() : () -> ()
129+
// CHECK: cir.yield
130+
// CHECK: }]

0 commit comments

Comments
 (0)