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

    <tr>
        <th>Summary</th>
        <td>
            Clang misaligns variables stored in coroutine frames
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    Clang seems to fail to correctly align objects in a coroutine frame that need more than 8 bytes of alignment on x86-64. Here is a program that demonstrates this by having a 64-byte-aligned object persist across a `co_await` ([Compiler Explorer](https://godbolt.org/z/bnxEY7Mf1)):

```c++
#include <stdlib.h>

#include <coroutine>
#include <cstdint>
#include <iostream>

struct Promise;

struct Task {
  using promise_type = Promise;
};

// A promise type that never suspends.
struct Promise {
  std::suspend_never initial_suspend() { return {}; }
  void unhandled_exception() {}
  std::suspend_never final_suspend() noexcept { return {}; }
  Task get_return_object() { return Task{}; }
  void return_value(const bool value) {}
};

// An awaitable that is always immediately ready with the value true.
struct Awaitable final {
  // __attribute__((noinline)) apparently prevents the compiler from seeing that
  // co_await can be a no-op.
  bool __attribute__((noinline)) await_ready() { return true; }

  void await_suspend(std::coroutine_handle<> h) {}
  bool await_resume() { return true; }
};

// Crash if p is not aligned to 64 bytes.
void __attribute__((noinline)) CheckAlignment(void* const p) {
  if (reinterpret_cast<intptr_t>(p) % 64 == 0) {
    return;
  }

  std::cerr << "Bad alignment: " << p << "\n";
  exit(1);
}

// A class that needs to be aligned to 64 bytes, and crashes if it isn't.
class HighlyAligned final {
 public:
  explicit HighlyAligned() { CheckAlignment(this); }

 private:
  alignas(64) char storage[16];
};

static_assert(alignof(HighlyAligned) == 64);

// A coroutine that creates an object that needs to be aligned to 64 bytes in
// the coroutine frame, ensuring it exists across a co_await.
Task Coroutine() {
  auto a = HighlyAligned();
  const bool result = co_await Awaitable{};
  static_cast<void>(a);

  co_return result;
}

int main(int argc, char** argv) {
  Coroutine();
}
```

This dies pretty reliably with a `Bad alignment` message. If you instead change the program so that it creates `HighlyAligned` objects on the stack in `main`, it doesn't crash.

(For the record, [here](https://godbolt.org/z/bnxEY7Mf1) is a gtest version that is a little easier to work with but has more dependencies.)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyVV0tv2zgQ_jXyZRDDlt8HHxKnQfewwB562ZNASbTFhiYFknLi_fX7DSX5GaMt4Fa2yHl9M_PNJLflcb3RwuzIS7n3FCxthdL8LKxzsgj6SEKrnSGb_8RPT8qQ4EPbBGUkbZ3YSwqVCGSkLGlvXfxpaEn5MUhPdttq2EsTyBr6XM6f5tMhfZe4qTy01c7uoKbVUsq9NT44wbKhwoX8SJU4KDgpaD59Yq1PUSPMtV5RLZ1XPpAonPWsMpmPCpuJD6ECvlKSLpPZy8bua6Wlo2-ftYafLpm94qQKofbJ5DlJ3_DZ2TK3Ogyt2-HXf_iXm89v_y7-3o6TdMUf3By9JqP-__mo_RRJ-sKf9m06UabQTSkpmWx8KLXKh1Uy-XYlenXphOn51vU5tCgTHpwqC8yk2N-YwMsG-Pzj7F55aH754vCH8O-ULLojosYz1nUrkoVjzQZe73UsXm_0tQDScy9LUbarjQNw942vpSn98CvnLl1AqAzz5LmTyFp5ZVRQQmfdW85qumI5cjI0zkQV0S3iR6fsYFVJjUFNllqWmfwsZB2UNWfxi8sPLG-VubNrbKvqlw5EgHcyZO2lrC3ae-_53uMIOuGD0I2EbMFdQrm1mrpX16E8Tg8amPtC5LpLDjeh_hBHNPd-L0uF1kPbo5rKI32oUOGWbI0QMiavs_d80hUxusxiZzDLRAhO5U2QWRajXhqrjOZSjx1Foq6FAz3Aau2Atwk-2iz6ht2iRJiiuDDZ5RsLfatTAd7JJfrf2CdbD_trEaXfcIN1ZDHu--Rw5FdpuUpOK3quj1MZnbo6a-sPrYoWpeq-8qKTvQu-2cvf8eFRkjdO-IrUlmrOrrGBesYEtc-nLTV3-MQAfo3OppLF-3PP5DhnuSR9prYS6z6iLhzYxh2HlAXpkNWQFcIHZioT6uCySGTpshVLZ-wUWIaJZnSjibrwT5HSfRLOeEvnKIK8gdr0RZTn6YNjftcf1xf3ktnG8ONsQn4qDjKS_iXlfcV3hRben4dgnKNchveQJ-mGUAdUcH4w4ICS4gaE8UXo8tFq-652lT4-dypue6tucq2K0yhid2u8gK4ruYsSuksfz9Y2uDs4a6cOIIEL9TEUgfvL-ZQ1FpUAnQfrxE5iso7nPEofTwYfRFBFhrikY9tRnd3i2427q74IoplH8-W8fkTMC7Qsbwui31J-KxWYJldqW8K52ms4W9L4xjHvAFvUhAc1nbaMnne6xEWe35zG-Hm89CA2MC_iMP0iSxe1d8HtTAU6RJkTy50o9zQszm0Qce46LTZo7DJxDyZb6QZSZ-RRmaNhaS8Uz0v-KtyuYGC4BND-zAB4dbiJ9QaGL3T3e9OlqR-875UKyWHGCDyEtEKk3RyKe911S2O520vvUYZD-mtLR9sgrz6Aw9lBs5Mxr_2G6W038c5FAw3XyYDGftfFtsrSQLV458UXZxEIOA0AoKS0sm3dtqGH19W6fLMuKsAibV3JMuiVCnvvny-e7aa8g8eBDrztRt-64U1ahYAJLIVXmJaosg_r3lvMwOhYn327mJeS55M0hWL2T1eDcj0pV5OVGAQFBd3fAtjGIsAeQ98x_ICJex39AxBuesQPGqfXN6HAcJMPMb7xQ-tD_3hCHtrV50153zAdvs3m88V4UK1XYjEtZT4aT6ZbOc_Hi9V0Ph8v5HySrvLleDHQIpfar4EgiNrID4oqIne_DtQ6HaXpaJGm4_FsMRoNp8tZvlrNxKicjYpyNU6mI4nc6SH7wRgP3Dq6lDc7j0PNnX0-BFNxNchoDvrRupV165-isLkXg2h6HV3_H5DZFzk">