aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-attribs.c
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2017-08-18 09:38:38 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2017-08-18 02:38:38 -0700
commit00aa1fa221744dc57f6c6cea8baa669b732d1101 (patch)
tree1dbbe35f67ab9fc825f52d4cbe56fbeed0afafa3 /gcc/c-family/c-attribs.c
parentc32bd276c68f5089b7e8ee58a8bc85c9bd543455 (diff)
downloadgcc-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.c71
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. */