Skip to content
This repository was archived by the owner on Feb 21, 2026. It is now read-only.

[CIR] Breaking from a loop misses cleanups#1951

Description

@andykaylor

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions