On the x86_64-*-linux-gnu target, G++ enforces 128 bytes as the maximum alignment for data members, even though GCC accepts much more restrictive alignments. For example, in the program below the struct is aligned on a 128-byte boundary in C++ but on a 256-byte boundary in C. The C++ restriction is enforced by the check_cxx_fundamental_alignment_constraints() function defined in c-family/c-common.c. The function uses the locally defined macro MAX_TARGET_FIELD_ALIGNMENT as the upper bound on the alignment: #ifdef BIGGEST_FIELD_ALIGNMENT #define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT #else #define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT #endif The macro BIGGEST_FIELD_ALIGNMENT is not defined in this file, so the function falls back on BIGGEST_ALIGNMENT which is 128 (the __BIGGEST_ALIGNMENT__ user macro is defined to 16). The BIGGEST_FIELD_ALIGNMENT macro is defined in config/i386/i386.h with the following comment: /* ??? Blah -- this macro is used directly by libobjc. Since it supports no vector modes, cut out the complexity and fall back on BIGGEST_FIELD_ALIGNMENT. */ #ifdef IN_TARGET_LIBS #ifdef __x86_64__ #define BIGGEST_FIELD_ALIGNMENT 128 ... which happens to be the same as BIGGEST_ALIGNMENT. However, both alignments are in *bits* not *bytes* as assumed by the C++ functions, so G++ not only enforces a more restrictive limit than G++, it also uses the wrong units. In contrast, the far more liberal alignment limit enforced by the C front end in the check_user_alignment() function uses the following test, allowing for alignments of as great as 2^28 bytes: else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG) { error ("requested alignment is too large"); return -1; $ (set -x; cat t.c; cc="/build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc"; for lang in c c++; do $cc -S -Wall -Wextra -Wpedantic -x$lang t.c; done) + cat t.c #if !__cplusplus # define alignas _Alignas #endif struct S { alignas (256) int i; }; + cc='/build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc' + for lang in c c++ + /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -S -Wall -Wextra -Wpedantic -xc t.c + for lang in c c++ + /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -S -Wall -Wextra -Wpedantic -xc++ t.c t.c:5:30: warning: requested alignment 256 is larger than 128 [-Wattributes] struct S { alignas (256) int i; }; ^
The behavior looks the same in all supported GCC version going all the way back to 4.9.3.
> The BIGGEST_FIELD_ALIGNMENT macro is defined in config/i386/i386.h with the > following comment: ... > #ifdef IN_TARGET_LIBS This definition version is only ever used in libobjc and libgcc.
This is the definition which matters: /* Minimum size in bits of the largest boundary to which any and all fundamental data types supported by the hardware might need to be aligned. No data type wants to be aligned rounder than this. Pentium+ prefers DFmode values to be aligned to 64 bit boundary and Pentium Pro XFmode values at 128 bit boundaries. When increasing the maximum, also update TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */ #define BIGGEST_ALIGNMENT \ (TARGET_IAMCU ? 32 : (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128)))
@defmac BIGGEST_ALIGNMENT Biggest alignment that any data type can require on this machine, in bits. Note that this is not the biggest alignment that is supported, just the biggest alignment that, when violated, may cause a fault. @end defmac @deftypevr {Target Hook} HOST_WIDE_INT TARGET_ABSOLUTE_BIGGEST_ALIGNMENT If defined, this target hook specifies the absolute biggest alignment that a type or variable can have on this machine, otherwise, @code{BIGGEST_ALIGNMENT} is used. @end deftypevr .... #undef TARGET_ABSOLUTE_BIGGEST_ALIGNMENT #define TARGET_ABSOLUTE_BIGGEST_ALIGNMENT 512 I suspect there is a target issue here or the front-end should be using TARGET_ABSOLUTE_BIGGEST_ALIGNMENT instead. The back-end is confused about byte vs bit here and even the comment before the definition of BIGGEST_ALIGNMENT is incorrect.
I should note that attribute aligned is accepted with larger values than 128, so the problem is limited to enforcing the limit requested via the C++ 11 alignas operator. As evident from the number of bugs linked to bug 58601, alignas and its interaction with attribute aligned suffers from many problems in G++. While the x86_64 back end might be confused about some of the alignment macros I think the underlying problem here is thec heck_cxx_fundamental_alignment_constraints() function and its use of the macros.