https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114900
Bug ID: 114900
Summary: Overaligned locals in coroutines are not properly
aligned
Product: gcc
Version: 13.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: jankodedic2 at gmail dot com
Target Milestone: ---
GCC 13.2.0 (x86-64)
Flags: -std=c++20
Godbolt link: https://godbolt.org/z/f3KGaGWW6
Overaligned locals in coroutines are not properly aligned. If a local variable
is marked with alignas(n), GCC seemingly does nothing about it. If a local
variable just has an overaligned type, GCC seems to overallocate to try and
align it correctly but alignment is still incorrect (overallocation is probably
the only solution until P2014 is resolved -
https://github.com/cplusplus/papers/issues/750).
Full example pasted below:
```
#include <coroutine>
#include <cstdlib>
#include <cstdint>
#include <iostream>
static constexpr std::size_t alignment = 1 << 13;
bool
is_aligned(void* p)
{
return ((std::uintptr_t)p % alignment) == 0;
}
void* malloc_address = nullptr;
void* local_address = nullptr;
struct coro
{
std::coroutine_handle<> coroutine_handle;
struct promise_type
{
void*
operator new(std::size_t n)
{
std::cout << "allocating " << n << " bytes\n";
malloc_address = std::malloc(n);
return malloc_address;
}
void
operator delete(void* p)
{
std::free(p);
}
std::suspend_never
initial_suspend()
{
return {};
}
coro
get_return_object()
{
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
void
return_void()
{}
void
unhandled_exception()
{}
std::suspend_always
final_suspend() noexcept
{
return {};
}
};
};
struct S
{
alignas(alignment) int x = 42;
};
coro
foo()
{
#if 0
alignas(alignment) int x = 42;
#else
S x;
#endif
local_address = &x;
std::cout << "is aligned? " << is_aligned(local_address) << std::endl;
co_return;
}
int
main()
{
std::cout << "max align: " << alignof(std::max_align_t) << std::endl;
auto c = foo();
std::cout << "malloc_address: " << malloc_address << std::endl;
std::cout << "local_address: " << local_address << std::endl;
std::cout << "difference: " << ((char*)local_address -
(char*)malloc_address) << std::endl;
}
```