Add warn_if_not_aligned attribute
authorH.J. Lu <hongjiu.lu@intel.com>
Fri, 18 Aug 2017 09:38:38 +0000 (09:38 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Fri, 18 Aug 2017 09:38:38 +0000 (02:38 -0700)
commit00aa1fa221744dc57f6c6cea8baa669b732d1101
tree1dbbe35f67ab9fc825f52d4cbe56fbeed0afafa3
parentc32bd276c68f5089b7e8ee58a8bc85c9bd543455
Add warn_if_not_aligned attribute

Add warn_if_not_aligned attribute as well as  command line options:
-Wif-not-aligned and -Wpacked-not-aligned.

__attribute__((warn_if_not_aligned(N))) causes compiler to issue a
warning if the field in a struct or union is not aligned to N:

typedef unsigned long long __u64
  __attribute__((aligned(4),warn_if_not_aligned(8)));

struct foo
{
  int i1;
  int i2;
  __u64 x;
};

__u64 is aligned to 4 bytes.  But inside struct foo, __u64 should be
aligned at 8 bytes.  It is used to define struct foo in such a way that
struct foo has the same layout and x has the same alignment when __u64
is aligned at either 4 or 8 bytes.

Since struct foo is normally aligned to 4 bytes, a warning will be issued:

warning: alignment 4 of 'struct foo' is less than 8

Align struct foo to 8 bytes:

struct foo
{
  int i1;
  int i2;
  __u64 x;
} __attribute__((aligned(8)));

silences the warning.  It also warns the field with misaligned offset:

struct foo
{
  int i1;
  int i2;
  int i3;
  __u64 x;
} __attribute__((aligned(8)));

warning: 'x' offset 12 in 'struct foo' isn't aligned to 8

This warning is controlled by -Wif-not-aligned and is enabled by default.

When -Wpacked-not-aligned is used, the same warning is also issued for
the field with explicitly specified alignment in a packed struct or union:

struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
  struct S8 s8;
};

warning: alignment 1 of 'struct S' is less than 8

This warning is disabled by default and enabled by -Wall.

gcc/

PR c/53037
* print-tree.c (print_node): Support DECL_WARN_IF_NOT_ALIGN
and TYPE_WARN_IF_NOT_ALIGN.
* stor-layout.c (do_type_align): Merge DECL_WARN_IF_NOT_ALIGN.
(handle_warn_if_not_align): New.
(place_union_field): Call handle_warn_if_not_align.
(place_field): Call handle_warn_if_not_align.  Copy
TYPE_WARN_IF_NOT_ALIGN.
(finish_builtin_struct): Copy TYPE_WARN_IF_NOT_ALIGN.
(layout_type): Likewise.
* tree-core.h (tree_type_common): Add warn_if_not_align.  Set
spare to 18.
(tree_decl_common): Add warn_if_not_align.
* tree.c (build_range_type_1): Copy TYPE_WARN_IF_NOT_ALIGN.
* tree.h (TYPE_WARN_IF_NOT_ALIGN): New.
(SET_TYPE_WARN_IF_NOT_ALIGN): Likewise.
(DECL_WARN_IF_NOT_ALIGN): Likewise.
(SET_DECL_WARN_IF_NOT_ALIGN): Likewise.
* doc/extend.texi: Document warn_if_not_aligned attribute.
* doc/invoke.texi: Document -Wif-not-aligned and
-Wpacked-not-aligned.

gcc/c-family/

PR c/53037
* c-attribs.c (handle_warn_if_not_aligned_attribute): New.
(c_common_attribute_table): Add warn_if_not_aligned.
(handle_aligned_attribute): Renamed to ...
(common_handle_aligned_attribute): Remove argument, name, and add
argument, warn_if_not_aligned.  Handle warn_if_not_aligned.
(handle_aligned_attribute): New.
* c.opt: Add -Wif-not-aligned and -Wpacked-not-aligned.

gcc/c/

PR c/53037
* c-decl.c (merge_decls): Also merge DECL_WARN_IF_NOT_ALIGN.
(check_bitfield_type_and_width): Don't allow bit-field with
warn_if_not_aligned type.

gcc/cp/

PR c/53037
* decl.c (duplicate_decls): Also merge DECL_WARN_IF_NOT_ALIGN.
* decl2.c (grokbitfield): Don't allow bit-field with
warn_if_not_aligned type.

gcc/testsuite/

PR c/53037
* c-c++-common/pr53037-5.c: New test.
* g++.dg/pr53037-1.C: Likewise.
* g++.dg/pr53037-2.C: Likewise.
* g++.dg/pr53037-3.C: Likewise.
* g++.dg/pr53037-4.C: Likewise.
* gcc.dg/pr53037-1.c: Likewise.
* gcc.dg/pr53037-2.c: Likewise.
* gcc.dg/pr53037-3.c: Likewise.
* gcc.dg/pr53037-4.c: Likewise.

From-SVN: r251180
26 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/c-family/c.opt
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/print-tree.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr53037-5.c [new file with mode: 0644]
gcc/testsuite/g++.dg/pr53037-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr53037-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr53037-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr53037-4.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr53037-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr53037-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr53037-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr53037-4.c [new file with mode: 0644]
gcc/tree-core.h
gcc/tree.c
gcc/tree.h