https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70066
Bug ID: 70066 Summary: alignas imposes the wrong limit on data members Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- 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; }; ^