I'm reporting a GCC problem that caused Emacs to SIGSEGV as described here: https://bugs.gnu.org/29183 I tracked the problem down to an '__attribute__ ((aligned (8)))' that GCC silently ignored. To reproduce the problem, consider the following program: struct s { char mem; }; __attribute__ ((aligned (8))) struct s a; struct __attribute__ ((aligned (8))) s b; struct s __attribute__ ((aligned (8))) c; struct s d __attribute__ ((aligned (8))); Compile this with 'gcc -S' on x86-64, and you get: .comm a,1,8 .comm b,1,1 .comm c,1,8 .comm d,1,8 Although the variables a, c, and d are properly aligned, the variable b is not: the 'aligned' attribute is silently ignored for b. I reproduced this problem with GCC 7.2.1 20170915 (Red Hat 7.2.1-2), running on Fedora 26 x86-64.
(In reply to Paul Eggert from comment #0) Sorry, but my example in comment #0 (although it illustrates a bug) doesn't illustrate the bug that crashed GCC. Here's a better example: struct t { long mem; }; __attribute__ ((aligned (2))) struct t a; struct __attribute__ ((aligned (2))) t b; struct t __attribute__ ((aligned (2))) c; struct t d __attribute__ ((aligned (2))); This compiles into: .comm a,8,2 .comm b,8,8 .comm c,8,2 .comm d,8,2 Here, only 'b' is aligned correctly. The variables a, c, and d have an alignment of only 2, but they should have an alignment of 8 because __attribute__ ((aligned (8))) is documented to never decrease the alignment of a structure, only to increase it. The GCC 7.2 documentation <https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Common-Variable-Attributes.html> says, "When used on a struct, or struct member, the 'aligned' attribute can only increase the alignment; in order to decrease it, the 'packed' attribute must be specified as well."
(In reply to Paul Eggert from comment #1) > (In reply to Paul Eggert from comment #0) > > Sorry, but my example in comment #0 (although it illustrates a bug) doesn't > illustrate the bug that crashed GCC. Here's a better example: > > struct t { long mem; }; > __attribute__ ((aligned (2))) struct t a; > struct __attribute__ ((aligned (2))) t b; > struct t __attribute__ ((aligned (2))) c; > struct t d __attribute__ ((aligned (2))); > > This compiles into: > > .comm a,8,2 > .comm b,8,8 > .comm c,8,2 > .comm d,8,2 > > Here, only 'b' is aligned correctly. The variables a, c, and d have an > alignment of only 2, but they should have an alignment of 8 because > __attribute__ ((aligned (8))) is documented to never decrease the alignment > of a structure, only to increase it. The GCC 7.2 documentation > <https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Common-Variable-Attributes. > html> says, "When used on a struct, or struct member, the 'aligned' > attribute can only increase the alignment; in order to decrease it, the > 'packed' attribute must be specified as well." I think this applies to types but not to variables. IIRC there's no packed attribute for variables: int a __attribute__((aligned(2),packed)); > gcc-7 -S t.c t.c:1:1: warning: ‘packed’ attribute ignored [-Wattributes] int a __attribute__((aligned(2),packed)); ^~~ so yes, for type definitions you should need packed to decrease alignment but for variable declarations aligned is taken literally. You are not using aligned on a 'struct or struct member' but on the variable in all but (b).
(In reply to Richard Biener from comment #2) > (In reply to Paul Eggert from comment #1) > > (In reply to Paul Eggert from comment #0) > > > > Sorry, but my example in comment #0 (although it illustrates a bug) doesn't > > illustrate the bug that crashed GCC. Here's a better example: > > > > struct t { long mem; }; > > __attribute__ ((aligned (2))) struct t a; > > struct __attribute__ ((aligned (2))) t b; > > struct t __attribute__ ((aligned (2))) c; > > struct t d __attribute__ ((aligned (2))); > > > > This compiles into: > > > > .comm a,8,2 > > .comm b,8,8 > > .comm c,8,2 > > .comm d,8,2 > > > > Here, only 'b' is aligned correctly. The variables a, c, and d have an > > alignment of only 2, but they should have an alignment of 8 because > > __attribute__ ((aligned (8))) is documented to never decrease the alignment > > of a structure, only to increase it. The GCC 7.2 documentation > > <https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Common-Variable-Attributes. > > html> says, "When used on a struct, or struct member, the 'aligned' > > attribute can only increase the alignment; in order to decrease it, the > > 'packed' attribute must be specified as well." > > I think this applies to types but not to variables. IIRC there's no packed > attribute for variables: > > int a __attribute__((aligned(2),packed)); > > gcc-7 -S t.c > t.c:1:1: warning: ‘packed’ attribute ignored [-Wattributes] > int a __attribute__((aligned(2),packed)); > ^~~ > > so yes, for type definitions you should need packed to decrease alignment > but for variable declarations aligned is taken literally. > > You are not using aligned on a 'struct or struct member' but on the variable > in all but (b). You'd still think there'd be a diagnostic from -Wattributes for the aligned attribute, too, not just the packed one...
(In reply to Richard Biener from comment #2) > You are not using aligned on a 'struct or struct member' but on the variable > in all but (b). If that's the intent, then GCC is mishandling the first example I gave in comment #0: struct s { char mem; }; __attribute__ ((aligned (8))) struct s a; struct __attribute__ ((aligned (8))) s b; struct s __attribute__ ((aligned (8))) c; struct s d __attribute__ ((aligned (8))); Here, GCC says the alignment of 'b' is 1, not 8. What happened to the attribute? Later discussion in https://bugs.gnu.org/29183 has revealed that this first example is also relevant to Emacs, and that Emacs crashes due to problems in this area as well. In summary there seems to be no straightforward way in GNU C to get what Emacs wants, which is to say, "I want V's address to be a multiple of max(8, (natural alignment for V))." I think I'll look into fixing Emacs to use unions instead. Could you please fix the GCC documentation to clarify what's going on here? I don't understand it myself, so I'm afraid any doc patch that I propose wouldc be wrong.
(In reply to Paul Eggert from comment #4) > Here, GCC says the alignment of 'b' is 1, not 8. What happened to the > attribute? GCC silently drops it, without validating it. For instance, this is accepted as well: struct s { char mem; }; struct __attribute__ ((foobar)) s b; I view it as a bug. At a minimum, GCC should point out that it's ignoring the attribute like other compilers do, such as Clang: warning: unknown attribute 'foobar' ignored [-Wunknown-attributes] I happened to notice this bug while testing a fix for pr84108. It seems that a simple fix is fairly straightforward so hopefully Richard won't be offended if I reopen this bug, assign it to myself, and submit my patch in stage 1 of GCC 9.
Created attachment 43330 [details] Patch tested on x86_64-linux. GCC 9 patch regression-tested on x86_64-linux.
(In reply to Martin Sebor from comment #5) > (In reply to Paul Eggert from comment #4) > > Here, GCC says the alignment of 'b' is 1, not 8. What happened to the > > attribute? > > GCC silently drops it, without validating it. For instance, this is > accepted as well: > > struct s { char mem; }; > > struct __attribute__ ((foobar)) > s b; > > I view it as a bug. At a minimum, GCC should point out that it's ignoring > the attribute like other compilers do, such as Clang: > > warning: unknown attribute 'foobar' ignored [-Wunknown-attributes] > > I happened to notice this bug while testing a fix for pr84108. It seems > that a simple fix is fairly straightforward so hopefully Richard won't be > offended if I reopen this bug, assign it to myself, and submit my patch in > stage 1 of GCC 9. It's stage 1 of gcc 9 now.
I'm not working on this anymore.