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; };
^