Bug 82914 - 'struct __attribute__ ((aligned (N))) s' ignores 'aligned' attribute
Summary: 'struct __attribute__ ((aligned (N))) s' ignores 'aligned' attribute
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 7.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2017-11-09 04:48 UTC by Paul Eggert
Modified: 2022-01-26 17:44 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-02-02 00:00:00


Attachments
Patch tested on x86_64-linux. (860 bytes, patch)
2018-02-02 20:45 UTC, Martin Sebor
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Eggert 2017-11-09 04:48:52 UTC
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.
Comment 1 Paul Eggert 2017-11-09 05:09:04 UTC
(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."
Comment 2 Richard Biener 2017-11-09 08:32:04 UTC
(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).
Comment 3 Eric Gallager 2017-11-09 11:47:08 UTC
(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...
Comment 4 Paul Eggert 2017-11-09 23:17:03 UTC
(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.
Comment 5 Martin Sebor 2018-02-02 20:42:40 UTC
(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.
Comment 6 Martin Sebor 2018-02-02 20:45:52 UTC
Created attachment 43330 [details]
Patch tested on x86_64-linux.

GCC 9 patch regression-tested on x86_64-linux.
Comment 7 Eric Gallager 2018-05-21 04:42:26 UTC
(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.
Comment 8 Martin Sebor 2022-01-26 17:44:19 UTC
I'm not working on this anymore.