Issue 56671
Summary Clang misaligns variables stored in coroutine frames
Labels new issue
Assignees
Reporter jacobsa
    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.)
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to