diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2017-08-18 09:38:38 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2017-08-18 02:38:38 -0700 |
commit | 00aa1fa221744dc57f6c6cea8baa669b732d1101 (patch) | |
tree | 1dbbe35f67ab9fc825f52d4cbe56fbeed0afafa3 /gcc/c-family/c-attribs.c | |
parent | c32bd276c68f5089b7e8ee58a8bc85c9bd543455 (diff) | |
download | gcc-00aa1fa221744dc57f6c6cea8baa669b732d1101.zip gcc-00aa1fa221744dc57f6c6cea8baa669b732d1101.tar.gz gcc-00aa1fa221744dc57f6c6cea8baa669b732d1101.tar.bz2 |
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
Diffstat (limited to 'gcc/c-family/c-attribs.c')
-rw-r--r-- | gcc/c-family/c-attribs.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index ad2289c..5f79468 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -89,6 +89,8 @@ static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); static tree handle_mode_attribute (tree *, tree, tree, int, bool *); static tree handle_section_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, + int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -217,6 +219,9 @@ const struct attribute_spec c_common_attribute_table[] = handle_section_attribute, false }, { "aligned", 0, 1, false, false, false, handle_aligned_attribute, false }, + { "warn_if_not_aligned", 0, 1, false, false, false, + handle_warn_if_not_aligned_attribute, + false }, { "weak", 0, 0, true, false, false, handle_weak_attribute, false }, { "noplt", 0, 0, true, false, false, @@ -1666,12 +1671,13 @@ check_cxx_fundamental_alignment_constraints (tree node, return !alignment_too_large_p; } -/* Handle a "aligned" attribute; arguments as in - struct attribute_spec.handler. */ +/* Common codes shared by handle_warn_if_not_aligned_attribute and + handle_aligned_attribute. */ static tree -handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, - int flags, bool *no_add_attrs) +common_handle_aligned_attribute (tree *node, tree args, int flags, + bool *no_add_attrs, + bool warn_if_not_aligned_p) { tree decl = NULL_TREE; tree *type = NULL; @@ -1720,8 +1726,16 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, else *type = build_variant_type_copy (*type); - SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT); - TYPE_USER_ALIGN (*type) = 1; + if (warn_if_not_aligned_p) + { + SET_TYPE_WARN_IF_NOT_ALIGN (*type, (1U << i) * BITS_PER_UNIT); + warn_if_not_aligned_p = false; + } + else + { + SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT); + TYPE_USER_ALIGN (*type) = 1; + } } else if (! VAR_OR_FUNCTION_DECL_P (decl) && TREE_CODE (decl) != FIELD_DECL) @@ -1754,13 +1768,54 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, } else { - SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT); - DECL_USER_ALIGN (decl) = 1; + if (warn_if_not_aligned_p) + { + if (TREE_CODE (decl) == FIELD_DECL && !DECL_INITIAL (decl)) + { + SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT); + warn_if_not_aligned_p = false; + } + } + else + { + SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT); + DECL_USER_ALIGN (decl) = 1; + } + } + + if (warn_if_not_aligned_p) + { + error ("%<warn_if_not_aligned%> may not be specified for %q+D", + decl); + *no_add_attrs = true; } return NULL_TREE; } +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + return common_handle_aligned_attribute (node, args, flags, + no_add_attrs, false); +} + +/* Handle a "warn_if_not_aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_warn_if_not_aligned_attribute (tree *node, tree ARG_UNUSED (name), + tree args, int flags, + bool *no_add_attrs) +{ + return common_handle_aligned_attribute (node, args, flags, + no_add_attrs, true); +} + /* Handle a "weak" attribute; arguments as in struct attribute_spec.handler. */ |