<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/88478>88478</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [coroutines] clang fails to run trivial ABI destructors for an "aborted" function call
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          jacobsa
      </td>
    </tr>
</table>

<pre>
    Here's a small program containing a coroutine (`Foo`) that starts to evaluate a function call expression but then destroys itself before actually making the function call:

```c++
#include <coroutine>
#include <cstdlib>
#include <iostream>

struct DestroySelfTag {};

// An eager coroutine result type that supports awaiting DestroySelf to
// cause the promise to destroy the coroutine frame.
struct MyTask {
 struct promise_type {
    MyTask get_return_object() { return {}; }
 std::suspend_never initial_suspend() { return {}; }
 std::suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception();
    void return_void();

    auto await_transform(DestroySelfTag) {
      struct Awaiter {
        bool await_ready() { return false; }
        void await_suspend(const std::coroutine_handle<> h) { h.destroy(); }

        int await_resume() {
          // We should never resume; we destroyed ourselves just after
          // suspending.
          std::abort();
        }
 };

      return Awaiter{};
    }
  };
};

// A trivial ABI type that lets us know when it's created and destroyed.
struct HasDestructor {
  HasDestructor() { std::cout << "created:   " << this << "\n"; }
  ~HasDestructor() { std::cout << "destroyed: " << this << "\n"; }
};

// A function that we have a call expression for below in Foo. This just
// needs to accept the right types -- it should never actually be called.
void AcceptArgs(HasDestructor, int, HasDestructor) { std::abort(); }

// A coroutine that creates a HasDestructor object then destroys itself
// before doing anything with it.
MyTask Foo() {
  AcceptArgs(HasDestructor(), co_await DestroySelfTag(), HasDestructor());
  std::abort();
}

int main() {
  Foo();
  return 0;
}
```

When compiled with `-std=c++20 -O2 -fno-exceptions` ([Compiler Explorer](https://godbolt.org/z/bzG8xsMM9)), the program works as expected. It creates one `HasDestructor` object, then destroys it again when `std::coroutine_handle::destroy` is called:

```
created: 0x7ffd04aa2b6a
destroyed: 0x7ffd04aa2b6a
```

However, the program is miscompiled when we put the `[[clang::trivial_abi]] ` attribute on `HasDestructor` ([Compiler Explorer](https://godbolt.org/z/fPxn5jE5b)). In this case we fail to run the destructor, creating but then not ever destroying the `HasDestructor` object:

```
created: 0x7fff8f4da6b2
```

It doesn't seem like this should happen. There isn't extremely rigorous documentation on the semantics of `[[clang::trivial_abi]]`, but [what does exist](https://clang.llvm.org/docs/AttributeReference.html#trivial-abi) says "the convention is that the callee will destroy the object before returning". That makes sense, but _there is no function call here_. `AcceptArgs` is never actually called. Instead this should be treated the same as the following, which [does work correctly](https://godbolt.org/z/fe8EY9KM1):

```c++
MyTask Foo() {
  HasDestructor(), co_await DestroySelfTag();
 std::abort();
}
```

In a real codebase this bug could cause resources to be leaked when a coroutine is stopped early, e.g. due to cancellation.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykWE1v4zwO_jXKhWjgyvk85NCk7U6xGOxid4AXewpoiY41laVAkpvmPexvX0h2nDjNdGfmBYLY0QdFPiQfUkHv1c4Qrdh0zaaPI2xCZd3qOwpbeBwVVh5XX8gR43MPCL5GrWHv7M5hDcKagMooswMEYZ1tgjIEjC_YLHu2ls0yxpcQKgzgA7rgIVigN9QNBgKEsjEiKGtARLH0vnfkffxdNAFCRQYk-eDs0YMKnnQJBZXWEaAIDWp9hBpf4_GhoqEwlj-w7JFlp-9Z1n4E4-v4aUd5rozQjSRg-aY3gOVPN-d9kFoVP5hV1gdHWJ-n07cPrhEBHlsz_k26_IY7YPM1mz-yfD3QkT8z_gwPBgh35C4AdeQbHSAc99SB2ez3NsKJB1QhAnBxAAQ7ECiw8ZQQ2jtbq_huT7im4fNBpcOaxgPNvx6_oX9NGqdh6MY7Wduk1HkW4LRjR2HrKDTObG3xnUSIYcGXcS2042cYID5O4mX0Xf7gG78nI7eG3siBMioo1Ntu9DdloT7g0UOpzAdRxtK7oH34fzIB4M0qCY2p0EhNctvuU9a0knqv9ks7FOL71ZLzQmyCbb25DQ6NL62rGV8M46Yz-bwLTt54iDvJXc8CFNbqTq4jlMePwJWoPX2wsVe-3XvGSljjwxnZPna2LRws37D8CarTIdW4i7Te8vM5w9OUCb2ivqnprOlwHUAX138Q-Mo2WkIbIt22fA0HOsU3SbCN86TfyMP3xgfAMpD7gcTOSmV24-sVvcFYWBdueDqJ6RH8mN3tig7zzl1XNDAUMZTxQ7aA4NSbQg0P65cLhtAUPDQeXo09wCEyqQqJw4UjDCQBjTyDNEz5L-hT3DUi2EFIDSYuIukiGpoAKQQ2wDjvzmL5Q8KYn6ZCpfzFMjbdmPgYxuB_f_W03pp43q-d9gm8fVVJsB4IKnyLpeu6YpXWQUHaHkAZeLZ2DN_iuTHmBhINkUxlEEWim0jATu2qlt493N2BCsPA7otdQenY3l8pQR-SnAe384wvrjDbxKyKj6vxKyCHMX2doD0U5zqRsGi9G7uCYcC0bH-zfA8EdqVc2tQ_mGOo4stBhQpU6CzsaknsJT7QwWeGJ1P4BoTdJk6BayI9Lbi57zKzP038K6QihdWozEddewMuJHdckN2QdupWLoX_EfEUtt4rTbKFic2yu6TfY9fW8Azu_sHhrjT2ri9Lns2y1JNN15t2u4On9722jhybPjK-qELY-2hlcszOysLqMLZux_jzn4w_F3_-bfHuv35ddujwzamdSG3gwbpXD-hjOpAIJMfwcg4PGzvCWTYEepbBqSnYfIgUwB0q07IWm2Wf1Jo4eqovswyU7_LjR91f-_OClrL3eVnKbILIixm20wMeubXgpnu-2ENM1mtslIda-bPbok0Hgn3b30bzUuO9FhrNrjWoI_QtFiq6Z_oYVwGG4FTRBAJrbuL5lzxc_vPdTL8_TYvWw2N4MS1vCvQUFS5R6charjFJcTlgmYRozN6-bzc2QCKvDs1Tk_5JJPySz8pFOZE4K_gnLnkJIC15w_g8gCeqQatXau3qCLbC_Z5M5GpyBKpbS-_BUU36GJk5Bp0HaUVTkwmYaoFtQfBUowlKeLDlz7ky3Yg2CSY2XR8ijUYVgd6VD7dclYSNtX6rO29JKzzjzw-ncPgXleTICBpXodaM592Zd_FMvgQfG17GedvomzcyyQLlWxJPwzFnCA5K68G9oCPyjqdbulJmxziPgGHkulfy4Ml4Olm1DR2SYOzV9S5ObMcRpwvmbrP2qs51RQ5ejA-EcuCxgiB0LUxyAdYUqSddAK3W9pA03MChUqKKICd8I0XF-uVIBH38yZygxdN_ln__ep9o-yeuk58Vq9-qT_n6-iLzeRG6mQQGEByhBmElFei7BCiaHYiEaHs_dORt4wSl3qQg0ISvJ8K6vNxHTwS735MEQqeP0Qoa78Ygm3SxFGgEaZ3yZDySq1wu8yWOaHU_v-fLbJIvZqNqRYuCL_n9ZDmdLZe55HMhi5yX0wWX86lYzkZqxTM-ySb3PJtNZnw2LrHMuZgvJzgt78ViziYZ1ah0nxsj5X1Dq8ViMl-MNBakffpTg_M2IWPn9zhyq7j-rmh2nk0yrXzwZwlBBZ3-CenN9ZF-0_7EgL6nwIum-0yFPnWBaGK-JU-RjH3oIA1GjdOrq9BToWqKsbA1489Rme5xt3e2rZHPybaY98m8_wUAAP__n8N6gQ">