Skip to content

Normal cleanup is incorrect for objects created in a loop condition expression #1755

@andykaylor

Description

@andykaylor

If I create an object that requires cleanup in the condition of a for-loop, the cleanup is created in the wrong scope.

#include <iostream>

struct Struk {
  Struk(int i) : i(i) { std::cout << "Struk(" << i << ")\n"; }
  ~Struk() { std::cout << "~Struk()\n"; }
  operator bool() { return i < 10; }

private:
  int i;
};

int main() {
  for (int i = 0; Struk a{i}; ++i) {

  }
}

When compiled with -fno-exceptions is represented as:

cir.func dso_local @main() -> !s32i {
  %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
  cir.scope {
    %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
    %3 = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["a", init] {alignment = 4 : i64}
    %4 = cir.const #cir.int<0> : !s32i
    cir.store align(4) %4, %2 : !s32i, !cir.ptr<!s32i>
    cir.for : cond {
      %5 = cir.load align(4) %2 : !cir.ptr<!s32i>, !s32i
      cir.call @_ZN5StrukC2Ei(%3, %5) : (!cir.ptr<!rec_Struk>, !s32i) -> ()
      %6 = cir.call @_ZN5StrukcvbEv(%3) : (!cir.ptr<!rec_Struk>) -> !cir.bool
      cir.condition(%6)
    } body {
      cir.yield
    } step {
      %5 = cir.load align(4) %2 : !cir.ptr<!s32i>, !s32i
      %6 = cir.unary(inc, %5) nsw : !s32i, !s32i
      cir.store align(4) %6, %2 : !s32i, !cir.ptr<!s32i>
      cir.yield
    }
    cir.call @_ZN5StrukD2Ev(%3) : (!cir.ptr<!rec_Struk>) -> ()
  }
  %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i
  cir.return %1 : !s32i
}

The Struk constructor is correctly called each time the condition is evaluated, but the destructor is only called once, at the end of the loop.

https://godbolt.org/z/sbW7hEjGa

An equivalent problem also occurs for a variable declared in the condition of a while loop.

https://godbolt.org/z/Pjeandq5h

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions