-
Notifications
You must be signed in to change notification settings - Fork 175
Open
Labels
bugSomething isn't workingSomething isn't working
Description
If I have a loop that constructs variables that require cleanup, the cleanup is missed if I use a break statement to exit the loop.
Reproducer:
struct S {
S();
~S();
};
void f() {
while (true) {
S s;
if (true)
break;
}
}
Results in this CIR:
cir.func dso_local @_Z1fv() attributes {ast = #cir.function.decl.ast} extra(#fn_attr1) {
cir.scope {
cir.while {
%0 = cir.const #true
cir.condition(%0)
} do {
cir.scope {
%0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init] ast #cir.var.decl.ast {alignment = 1 : i64}
cir.call @_ZN1SC1Ev(%0) : (!cir.ptr<!rec_S>) -> ()
cir.scope {
%1 = cir.const #true
cir.if %1 {
cir.break
}
}
cir.call @_ZN1SD1Ev(%0) : (!cir.ptr<!rec_S>) -> () extra(#fn_attr)
}
cir.yield
}
}
cir.return
}
That's wrong because the cir.break skips the cleanup. After FlattenCFG, it looks like this:
cir.func dso_local @_Z1fv() extra(#fn_attr1) {
%0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init] {alignment = 1 : i64}
cir.br ^bb1
^bb1: // pred: ^bb0
cir.br ^bb2
^bb2: // 2 preds: ^bb1, ^bb9
%1 = cir.const #true
cir.brcond %1 ^bb3, ^bb10
^bb3: // pred: ^bb2
cir.br ^bb4
^bb4: // pred: ^bb3
cir.call @_ZN1SC1Ev(%0) : (!cir.ptr<!rec_S>) -> ()
cir.br ^bb5
^bb5: // pred: ^bb4
%2 = cir.const #true
cir.brcond %2 ^bb6, ^bb7
^bb6: // pred: ^bb5
cir.br ^bb10
^bb7: // pred: ^bb5
cir.br ^bb8
^bb8: // pred: ^bb7
cir.call @_ZN1SD1Ev(%0) : (!cir.ptr<!rec_S>) -> () extra(#fn_attr)
cir.br ^bb9
^bb9: // pred: ^bb8
cir.br ^bb2
^bb10: // 2 preds: ^bb2, ^bb6
cir.br ^bb11
^bb11: // pred: ^bb10
cir.return
}
The break is handled in ^bb6 and results in the cleanup (^bb8) being skipped entirely.
https://godbolt.org/z/r1KnnK35T
This is probably related to #1123
bcardosolopes
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working