From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 88751 invoked by alias); 8 Jul 2017 13:45:43 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 83793 invoked by uid 89); 8 Jul 2017 13:45:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=UID, 5796 X-HELO: mail-pg0-f51.google.com Received: from mail-pg0-f51.google.com (HELO mail-pg0-f51.google.com) (74.125.83.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 08 Jul 2017 13:45:19 +0000 Received: by mail-pg0-f51.google.com with SMTP id u62so29394013pgb.3 for ; Sat, 08 Jul 2017 06:45:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=P8I80SmSp/N2ZhF7o07mK8FltwfJAhw1BITKVb0C5yY=; b=TpYcLUIY5OSS5vvnl8suQZwu3Zo5KbZ5xh+niSx6+wBTy0qNLfCMSRpPOg6NlcN5yq bSg97xVgw98k/0FLCd2CnpwCWHmD8ic+rtzhhMt+McvzfT4Sjg7WRHVkZ0FImoi+K0jx eOzR3BWg0KZfvSgE4K+mJBZLleDgT0eGpg41+zNadTDtlzZlIQRLnW02OCsfB8VcDRNN UHatAfSQer8IGLXmW3aXZSsSwdkyVTYIQE7S5NvygxmDxdpsXJvytkTYXo3A/H3SPW24 1xMORuH/PCHpC5Vd4KrhUgt7xETRESIDCgWn6Hq6NOYvYnvhXUc8JRARGnNeV0KecoM+ Zg5g== X-Gm-Message-State: AIVw113Iuqmffedylkn1GqcEMQrDP32r8snOUZjhRQ0h25tK2ylhUG0I f2l9T2OqgQJ/A4FZ X-Received: by 10.98.74.92 with SMTP id x89mr37059957pfa.123.1499521505700; Sat, 08 Jul 2017 06:45:05 -0700 (PDT) Received: from gnu-tools-1.localdomain (c-73-93-86-59.hsd1.ca.comcast.net. [73.93.86.59]) by smtp.gmail.com with ESMTPSA id j27sm11949116pgn.63.2017.07.08.06.45.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 08 Jul 2017 06:45:04 -0700 (PDT) Received: by gnu-tools-1.localdomain (Postfix, from userid 1000) id 19827208EC; Sat, 8 Jul 2017 06:45:04 -0700 (PDT) Date: Sat, 08 Jul 2017 13:45:00 -0000 From: "H.J. Lu" To: Joseph Myers Cc: Martin Sebor , Jason Merrill , GCC Patches Subject: Re: RFC: [PATCH] Add warn_if_not_aligned attribute Message-ID: <20170708134504.GA1303@gmail.com> References: <6c6c268d-a40b-cfa9-574c-ad235f9205b7@gmail.com> <4a4ac20f-9c27-4844-55dc-38ff56ac138b@gmail.com> <20170616115455.GA3457@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.8.3 (2017-05-23) X-IsSubscribed: yes X-SW-Source: 2017-07/txt/msg00408.txt.bz2 On Thu, Jul 06, 2017 at 03:44:57PM +0000, Joseph Myers wrote: > On Fri, 16 Jun 2017, H.J. Lu wrote: > > > +@code{warning: alignment 8 of 'struct foo' is less than 16}. > > I think @samp is better than @code for warnings, throughout, since they > aren't pieces of program code. Done. > > > +This warning can be disabled by @option{-Wno-if-not-aligned}. > > +The @code{warn_if_not_aligned } attribute can also be used for types > > Stray space before }. Done. > > > +static void > > +handle_warn_if_not_align (tree field, unsigned int record_align) > > Missing comment above this function explaining its semantics and those of > its arguments. > Done. > > + if ((record_align % warn_if_not_align) != 0) > > + warning (opt_w, "alignment %d of %qT is less than %d", > > + record_align, context, warn_if_not_align); > > I'd expect %u for unsigned int alignments, instead of %d. Done. > > > + unsigned int off > > + = (tree_to_uhwi (DECL_FIELD_OFFSET (field)) > > + + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) / BITS_PER_UNIT); > > + if ((off % warn_if_not_align) != 0) > > + warning (opt_w, "%q+D offset %d in %qT isn't aligned to %d", > > + field, off, context, warn_if_not_align); > > And you can have struct offsets that don't fit in unsigned int (i.e. > structures over 4 GB), so should be using unsigned HOST_WIDE_INT to store > the offset and %wu to print it. (Whereas various places in GCC restrict > alignments to unsigned int.) Done. > > What happens if you specify the attribute on a bit-field, or on a type > used to declare a bit-field? I don't think either of those particularly > makes sense, but I don't see tests for it either. > I fixed it and added some testcases. Here is the updated patch. OK for master? Thanks. H.J. ---- 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. (grokfield): 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. --- gcc/c-family/c-attribs.c | 71 +++++++++++++++++++++++---- gcc/c-family/c.opt | 8 ++++ gcc/c/c-decl.c | 11 +++++ gcc/cp/decl.c | 4 ++ gcc/cp/decl2.c | 7 +++ gcc/doc/extend.texi | 87 ++++++++++++++++++++++++++++++++++ gcc/doc/invoke.texi | 29 +++++++++++- gcc/print-tree.c | 9 ++-- gcc/stor-layout.c | 66 ++++++++++++++++++++++++++ gcc/testsuite/c-c++-common/pr53037-5.c | 81 +++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/pr53037-1.C | 81 +++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/pr53037-2.C | 37 +++++++++++++++ gcc/testsuite/g++.dg/pr53037-3.C | 37 +++++++++++++++ gcc/testsuite/g++.dg/pr53037-4.C | 24 ++++++++++ gcc/testsuite/gcc.dg/pr53037-1.c | 81 +++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr53037-2.c | 37 +++++++++++++++ gcc/testsuite/gcc.dg/pr53037-3.c | 37 +++++++++++++++ gcc/testsuite/gcc.dg/pr53037-4.c | 24 ++++++++++ gcc/tree-core.h | 9 +++- gcc/tree.c | 1 + gcc/tree.h | 20 ++++++++ 21 files changed, 747 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr53037-5.c create mode 100644 gcc/testsuite/g++.dg/pr53037-1.C create mode 100644 gcc/testsuite/g++.dg/pr53037-2.C create mode 100644 gcc/testsuite/g++.dg/pr53037-3.C create mode 100644 gcc/testsuite/g++.dg/pr53037-4.C create mode 100644 gcc/testsuite/gcc.dg/pr53037-1.c create mode 100644 gcc/testsuite/gcc.dg/pr53037-2.c create mode 100644 gcc/testsuite/gcc.dg/pr53037-3.c create mode 100644 gcc/testsuite/gcc.dg/pr53037-4.c diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 626ffa1..200e8ae 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -88,6 +88,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 *); @@ -211,6 +213,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, @@ -1640,12 +1645,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; @@ -1694,8 +1700,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) @@ -1728,13 +1742,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 ("% 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. */ diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 05766c4..1dc380e 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -579,6 +579,10 @@ Wformat-truncation= C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) Warn about calls to snprintf and similar functions that truncate output. +Wif-not-aligned +C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning +Warn when the field in a struct is not aligned. + Wignored-qualifiers C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra) Warn whenever type qualifiers are ignored. @@ -710,6 +714,10 @@ Wnamespaces C++ ObjC++ Var(warn_namespaces) Warning Warn on namespace definition. +Wpacked-not-aligned +C ObjC C++ ObjC++ Var(warn_packed_not_aligned) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) +Warn when fields in a struct with the packed attribute are misaligned. + Wsized-deallocation C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra) Warn about missing sized deallocation functions. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 317d5cd..45d561d 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2384,6 +2384,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl)); DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); } + if (DECL_WARN_IF_NOT_ALIGN (olddecl) + > DECL_WARN_IF_NOT_ALIGN (newdecl)) + SET_DECL_WARN_IF_NOT_ALIGN (newdecl, + DECL_WARN_IF_NOT_ALIGN (olddecl)); } /* Keep the old rtl since we can safely use it. */ @@ -7588,6 +7592,13 @@ grokfield (location_t loc, finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; + if (width && TYPE_WARN_IF_NOT_ALIGN (TREE_TYPE (value))) + { + error_at (loc, "cannot declare bit-field %q+D with % type", + value); + TREE_TYPE (value) = error_mark_node; + } + if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE) { /* If we currently have a binding for this field, set the diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 43a94d9..0c34b1b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2510,6 +2510,10 @@ next_arg:; DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); } DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl); + if (DECL_WARN_IF_NOT_ALIGN (olddecl) + > DECL_WARN_IF_NOT_ALIGN (newdecl)) + SET_DECL_WARN_IF_NOT_ALIGN (newdecl, + DECL_WARN_IF_NOT_ALIGN (olddecl)); if (TREE_CODE (newdecl) == FIELD_DECL) DECL_PACKED (olddecl) = DECL_PACKED (newdecl); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 877745c..21bc917 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1008,6 +1008,13 @@ grokbitfield (const cp_declarator *declarator, return NULL_TREE; } + if (width && TYPE_WARN_IF_NOT_ALIGN (TREE_TYPE (value))) + { + error ("cannot declare bit-field %qD with % type", + DECL_NAME (value)); + return NULL_TREE; + } + if (DECL_IN_AGGR_P (value)) { error ("%qD is already defined in the class %qT", value, diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index d0abd7f..df141ca 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5707,6 +5707,41 @@ alignment. See your linker documentation for further information. The @code{aligned} attribute can also be used for functions (@pxref{Common Function Attributes}.) +@cindex @code{warn_if_not_aligned} variable attribute +@item warn_if_not_aligned (@var{alignment}) +This attribute specifies a threshold for the structure field, measured +in bytes. If the structure field is aligned below the threshold, a +warning will be issued. For example, the declaration: + +@smallexample +struct foo +@{ + int i1; + int i2; + unsigned long long x __attribute__((warn_if_not_aligned(16))); +@}; +@end smallexample + +@noindent +causes the compiler to issue an warning on @code{struct foo}, like +@samp{warning: alignment 8 of 'struct foo' is less than 16}. +The compiler also issues a warning, like @samp{warning: 'x' offset +8 in 'struct foo' isn't aligned to 16}, when the structure field has +the misaligned offset: + +@smallexample +struct foo +@{ + int i1; + int i2; + unsigned long long x __attribute__((warn_if_not_aligned(16))); +@} __attribute__((aligned(16))); +@end smallexample + +This warning can be disabled by @option{-Wno-if-not-aligned}. +The @code{warn_if_not_aligned} attribute can also be used for types +(@pxref{Common Type Attributes}.) + @item cleanup (@var{cleanup_function}) @cindex @code{cleanup} variable attribute The @code{cleanup} attribute runs a function when the variable goes @@ -6560,6 +6595,58 @@ alignment. See your linker documentation for further information. The @code{aligned} attribute can only increase alignment. Alignment can be decreased by specifying the @code{packed} attribute. See below. +@cindex @code{warn_if_not_aligned} type attribute +@item warn_if_not_aligned (@var{alignment}) +This attribute specifies a threshold for the structure field, measured +in bytes. If the structure field is aligned below the threshold, a +warning will be issued. For example, the declaration: + +@smallexample +typedef unsigned long long __u64 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo +@{ + int i1; + int i2; + __u64 x; +@}; +@end smallexample + +@noindent +causes the compiler to issue an warning on @code{struct foo}, like +@samp{warning: alignment 4 of 'struct foo' is less than 8}. +It is used to define @code{struct foo} in such a way that +@code{struct foo} has the same layout and the structure field @code{x} +has the same alignment when @code{__u64} is aligned at either 4 or +8 bytes. Align @code{struct foo} to 8 bytes: + +@smallexample +struct foo +@{ + int i1; + int i2; + __u64 x; +@} __attribute__((aligned(8))); +@end smallexample + +@noindent +silences the warning. The compiler also issues a warning, like +@samp{warning: 'x' offset 12 in 'struct foo' isn't aligned to 8}, +when the structure field has the misaligned offset: + +@smallexample +struct foo +@{ + int i1; + int i2; + int i3; + __u64 x; +@} __attribute__((aligned(8))); +@end smallexample + +This warning can be disabled by @option{-Wno-if-not-aligned}. + @item bnd_variable_size @cindex @code{bnd_variable_size} type attribute @cindex Pointer Bounds Checker attributes diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index aa848bb..23046ff 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -284,6 +284,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-security -Wformat-signedness -Wformat-truncation=@var{n} @gol -Wformat-y2k -Wframe-address @gol -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol +-Wif-not-aligned @gol -Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol -Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol -Wimplicit-function-declaration -Wimplicit-int @gol @@ -298,7 +299,7 @@ Objective-C and Objective-C++ Dialects}. -Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} @gol -Wnull-dereference -Wodr -Wno-overflow -Wopenmp-simd @gol -Woverride-init-side-effects -Woverlength-strings @gol --Wpacked -Wpacked-bitfield-compat -Wpadded @gol +-Wpacked -Wpacked-bitfield-compat -Wpacked-not-aligned -Wpadded @gol -Wparentheses -Wno-pedantic-ms-format @gol -Wplacement-new -Wplacement-new=@var{n} @gol -Wpointer-arith -Wpointer-compare -Wno-pointer-to-int-cast @gol @@ -4427,6 +4428,13 @@ switch (cond) The @option{-Wimplicit-fallthrough=3} warning is enabled by @option{-Wextra}. +@item -Wif-not-aligned @r{(C, C++, Objective-C and Objective-C++ only)} +@opindex Wif-not-aligned +@opindex Wno-if-not-aligned +Control if warning triggered by the @code{warn_if_not_aligned} attribute +should be issued. This is is enabled by default. +Use @option{-Wno-if-not-aligned} to disable it. + @item -Wignored-qualifiers @r{(C and C++ only)} @opindex Wignored-qualifiers @opindex Wno-ignored-qualifiers @@ -6520,6 +6528,25 @@ struct foo This warning is enabled by default. Use @option{-Wno-packed-bitfield-compat} to disable this warning. +@item -Wpacked-not-aligned @r{(C, C++, Objective-C and Objective-C++ only)} +@opindex Wpacked-not-aligned +@opindex Wno-packed-not-aligned +Warn if a structure field with explicitly specified alignment in a +packed struct or union is misaligned. For example, a warning will +be issued on @code{struct S}, like, @code{warning: alignment 1 of +'struct S' is less than 8}, in this code: + +@smallexample +@group +struct __attribute__ ((aligned (8))) S8 @{ char a[8]; @}; +struct __attribute__ ((packed)) S @{ + struct S8 s8; +@}; +@end group +@end smallexample + +This warning is enabled by @option{-Wall}. + @item -Wpadded @opindex Wpadded @opindex Wno-padded diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 6a237cc..8bb6230 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -458,7 +458,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent, if (DECL_USER_ALIGN (node)) fprintf (file, " user"); - fprintf (file, " align %d", DECL_ALIGN (node)); + fprintf (file, " align %d warn_if_not_align %d", + DECL_ALIGN (node), DECL_WARN_IF_NOT_ALIGN (node)); if (code == FIELD_DECL) fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED, DECL_OFFSET_ALIGN (node)); @@ -603,8 +604,10 @@ print_node (FILE *file, const char *prefix, tree node, int indent, if (TYPE_USER_ALIGN (node)) fprintf (file, " user"); - fprintf (file, " align %d symtab %d alias set " HOST_WIDE_INT_PRINT_DEC, - TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node), + fprintf (file, " align %d warn_if_not_align %d symtab %d alias set " + HOST_WIDE_INT_PRINT_DEC, + TYPE_ALIGN (node), TYPE_WARN_IF_NOT_ALIGN (node), + TYPE_SYMTAB_ADDRESS (node), (HOST_WIDE_INT) TYPE_ALIAS_SET (node)); if (TYPE_STRUCTURAL_EQUALITY_P (node)) diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 1574e43..54edb5c 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -570,6 +570,8 @@ do_type_align (tree type, tree decl) if (TREE_CODE (decl) == FIELD_DECL) DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type); } + if (TYPE_WARN_IF_NOT_ALIGN (type) > DECL_WARN_IF_NOT_ALIGN (decl)) + SET_DECL_WARN_IF_NOT_ALIGN (decl, TYPE_WARN_IF_NOT_ALIGN (type)); } /* Set the size, mode and alignment of a ..._DECL node. @@ -1074,6 +1076,57 @@ update_alignment_for_field (record_layout_info rli, tree field, return desired_align; } +/* Issue a warning if the record alignment, RECORD_ALIGN, is less than + the field alignment of FIELD or FIELD isn't aligned. */ + +static void +handle_warn_if_not_align (tree field, unsigned int record_align) +{ + tree type = TREE_TYPE (field); + + if (type == error_mark_node) + return; + + unsigned int warn_if_not_align = 0; + + int opt_w = 0; + + if (warn_if_not_aligned) + { + warn_if_not_align = DECL_WARN_IF_NOT_ALIGN (field); + if (!warn_if_not_align) + warn_if_not_align = TYPE_WARN_IF_NOT_ALIGN (type); + if (warn_if_not_align) + opt_w = OPT_Wif_not_aligned; + } + + if (!warn_if_not_align + && warn_packed_not_aligned + && TYPE_USER_ALIGN (type)) + { + warn_if_not_align = TYPE_ALIGN (type); + opt_w = OPT_Wpacked_not_aligned; + } + + if (!warn_if_not_align) + return; + + tree context = DECL_CONTEXT (field); + + warn_if_not_align /= BITS_PER_UNIT; + record_align /= BITS_PER_UNIT; + if ((record_align % warn_if_not_align) != 0) + warning (opt_w, "alignment %u of %qT is less than %u", + record_align, context, warn_if_not_align); + + unsigned HOST_WIDE_INT off + = (tree_to_uhwi (DECL_FIELD_OFFSET (field)) + + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) / BITS_PER_UNIT); + if ((off % warn_if_not_align) != 0) + warning (opt_w, "%q+D offset %wu in %qT isn't aligned to %u", + field, off, context, warn_if_not_align); +} + /* Called from place_field to handle unions. */ static void @@ -1084,6 +1137,7 @@ place_union_field (record_layout_info rli, tree field) DECL_FIELD_OFFSET (field) = size_zero_node; DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT); + handle_warn_if_not_align (field, rli->record_align); /* If this is an ERROR_MARK return *after* having set the field at the start of the union. This helps when parsing @@ -1169,6 +1223,7 @@ place_field (record_layout_info rli, tree field) DECL_FIELD_OFFSET (field) = rli->offset; DECL_FIELD_BIT_OFFSET (field) = rli->bitpos; SET_DECL_OFFSET_ALIGN (field, rli->offset_align); + handle_warn_if_not_align (field, rli->record_align); return; } @@ -1290,6 +1345,9 @@ place_field (record_layout_info rli, tree field) if (! DECL_PACKED (field)) TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type); + + SET_TYPE_WARN_IF_NOT_ALIGN (rli->t, + TYPE_WARN_IF_NOT_ALIGN (type)); } #ifdef BITFIELD_NBYTES_LIMITED @@ -1328,6 +1386,8 @@ place_field (record_layout_info rli, tree field) rli->bitpos = round_up (rli->bitpos, type_align); TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type); + SET_TYPE_WARN_IF_NOT_ALIGN (rli->t, + TYPE_WARN_IF_NOT_ALIGN (type)); } #endif @@ -1478,6 +1538,7 @@ place_field (record_layout_info rli, tree field) DECL_FIELD_OFFSET (field) = rli->offset; DECL_FIELD_BIT_OFFSET (field) = rli->bitpos; SET_DECL_OFFSET_ALIGN (field, rli->offset_align); + handle_warn_if_not_align (field, rli->record_align); /* Evaluate nonconstant offsets only once, either now or as soon as safe. */ if (TREE_CODE (DECL_FIELD_OFFSET (field)) != INTEGER_CST) @@ -2088,6 +2149,8 @@ finish_builtin_struct (tree type, const char *name, tree fields, { SET_TYPE_ALIGN (type, TYPE_ALIGN (align_type)); TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type); + SET_TYPE_WARN_IF_NOT_ALIGN (type, + TYPE_WARN_IF_NOT_ALIGN (align_type)); } layout_type (type); @@ -2324,6 +2387,9 @@ layout_type (tree type) align = MAX (align, TYPE_ALIGN (type)); else TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element); + if (!TYPE_WARN_IF_NOT_ALIGN (type)) + SET_TYPE_WARN_IF_NOT_ALIGN (type, + TYPE_WARN_IF_NOT_ALIGN (element)); #ifdef ROUND_TYPE_ALIGN align = ROUND_TYPE_ALIGN (type, align, BITS_PER_UNIT); #else diff --git a/gcc/testsuite/c-c++-common/pr53037-5.c b/gcc/testsuite/c-c++-common/pr53037-5.c new file mode 100644 index 0000000..97d54b1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr53037-5.c @@ -0,0 +1,81 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wno-if-not-aligned" } */ + +typedef unsigned long long __u64 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo1 +{ + int i1; + int i2; + int i3; + __u64 x; +}; + +struct foo2 +{ + int i1; + int i2; + int i3; + __u64 x; +} __attribute__((aligned(8))); + +struct foo3 +{ + int i1; + int i3; + __u64 x; +}; + +struct foo4 +{ + int i1; + int i2; + __u64 x; +} __attribute__((aligned(8))); + +struct foo5 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +}; + +struct foo6 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); + +struct foo7 +{ + int i1; + int i2; + int i3; + int i4; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); + +union bar1 +{ + int i1; + __u64 x; +}; + +union bar2 +{ + int i1; + __u64 x; +} __attribute__((aligned(8))); + +union bar3 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +}; + +union bar4 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); diff --git a/gcc/testsuite/g++.dg/pr53037-1.C b/gcc/testsuite/g++.dg/pr53037-1.C new file mode 100644 index 0000000..a3d8f99 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr53037-1.C @@ -0,0 +1,81 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +typedef unsigned long long __u64 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo1 /* { dg-warning "alignment 4 of 'foo1' is less than 8" } */ +{ + int i1; + int i2; + int i3; + __u64 x; /* { dg-warning "'foo1::x' offset 12 in 'foo1' isn't aligned to 8" } */ +}; + +struct foo2 +{ + int i1; + int i2; + int i3; + __u64 x; /* { dg-warning "'foo2::x' offset 12 in 'foo2' isn't aligned to 8" } */ +} __attribute__((aligned(8))); + +struct foo3 /* { dg-warning "alignment 4 of 'foo3' is less than 8" } */ +{ + int i1; + int i3; + __u64 x; +}; + +struct foo4 +{ + int i1; + int i2; + __u64 x; +} __attribute__((aligned(8))); + +struct foo5 /* { dg-warning "alignment 4 of 'foo5' is less than 16" } */ +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); /* { dg-warning "'foo5::x' offset 4 in 'foo5' isn't aligned to 16" } */ +}; + +struct foo6 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); /* { dg-warning "'foo6::x' offset 4 in 'foo6' isn't aligned to 16" } */ +} __attribute__((aligned(16))); + +struct foo7 +{ + int i1; + int i2; + int i3; + int i4; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); + +union bar1 /* { dg-warning "alignment 4 of 'bar1' is less than 8" } */ +{ + int i1; + __u64 x; +}; + +union bar2 +{ + int i1; + __u64 x; +} __attribute__((aligned(8))); + +union bar3 /* { dg-warning "alignment 4 of 'bar3' is less than 16" } */ +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +}; + +union bar4 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); diff --git a/gcc/testsuite/g++.dg/pr53037-2.C b/gcc/testsuite/g++.dg/pr53037-2.C new file mode 100644 index 0000000..e617f90 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr53037-2.C @@ -0,0 +1,37 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wpacked-not-aligned" } */ + +struct __attribute__ ((aligned (8))) S8 { char a[8]; }; +struct __attribute__ ((packed)) S1 { /* { dg-warning "alignment 1 of 'S1' is less than 8" } */ + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S2 { + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S3 { + int i1; + struct S8 s8; /* { dg-warning "'S3::s8' offset 4 in 'S3' isn't aligned to 8" } */ +}; + +struct __attribute__ ((packed, aligned (8))) S4 { + int i1; + int i2; + struct S8 s8; +}; + +struct __attribute__ ((packed)) S5 { + long long ll; +}; + +union __attribute__ ((packed)) U1 { /* { dg-warning "alignment 1 of 'U1' is less than 8" } */ + int i1; + struct S8 s8; +}; + +union __attribute__ ((packed, aligned (8))) U2 { + int i1; + struct S8 s8; +}; diff --git a/gcc/testsuite/g++.dg/pr53037-3.C b/gcc/testsuite/g++.dg/pr53037-3.C new file mode 100644 index 0000000..1ed6354 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr53037-3.C @@ -0,0 +1,37 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wall" } */ + +struct __attribute__ ((aligned (8))) S8 { char a[8]; }; +struct __attribute__ ((packed)) S1 { /* { dg-warning "alignment 1 of 'S1' is less than 8" } */ + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S2 { + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S3 { + int i1; + struct S8 s8; /* { dg-warning "'S3::s8' offset 4 in 'S3' isn't aligned to 8" } */ +}; + +struct __attribute__ ((packed, aligned (8))) S4 { + int i1; + int i2; + struct S8 s8; +}; + +struct __attribute__ ((packed)) S5 { + long long ll; +}; + +union __attribute__ ((packed)) U1 { /* { dg-warning "alignment 1 of 'U1' is less than 8" } */ + int i1; + struct S8 s8; +}; + +union __attribute__ ((packed, aligned (8))) U2 { + int i1; + struct S8 s8; +}; diff --git a/gcc/testsuite/g++.dg/pr53037-4.C b/gcc/testsuite/g++.dg/pr53037-4.C new file mode 100644 index 0000000..553dd9a --- /dev/null +++ b/gcc/testsuite/g++.dg/pr53037-4.C @@ -0,0 +1,24 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +int foo1 __attribute__((warn_if_not_aligned(8))); /* { dg-error "'warn_if_not_aligned' may not be specified for 'foo1'" } */ + +__attribute__((warn_if_not_aligned(8))) +void +foo2 (void) /* { dg-error "'warn_if_not_aligned' may not be specified for 'void foo2\\(\\)'" } */ +{ +} + +struct foo3 +{ + int i : 2 __attribute__((warn_if_not_aligned(8))); /* { dg-error "'warn_if_not_aligned' may not be specified for 'i'" } */ +}; + +typedef unsigned int __u32 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo4 +{ + __u32 i : 2; /* { dg-error "cannot declare bit-field 'i' with 'warn_if_not_aligned' type" } */ +}; diff --git a/gcc/testsuite/gcc.dg/pr53037-1.c b/gcc/testsuite/gcc.dg/pr53037-1.c new file mode 100644 index 0000000..93af0a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53037-1.c @@ -0,0 +1,81 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +typedef unsigned long long __u64 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo1 +{ + int i1; + int i2; + int i3; + __u64 x; /* { dg-warning "'x' offset 12 in 'struct foo1' isn't aligned to 8" } */ +}; /* { dg-warning "alignment 4 of 'struct foo1' is less than 8" } */ + +struct foo2 +{ + int i1; + int i2; + int i3; + __u64 x; /* { dg-warning "'x' offset 12 in 'struct foo2' isn't aligned to 8" } */ +} __attribute__((aligned(8))); + +struct foo3 +{ + int i1; + int i3; + __u64 x; +}; /* { dg-warning "alignment 4 of 'struct foo3' is less than 8" } */ + +struct foo4 +{ + int i1; + int i2; + __u64 x; +} __attribute__((aligned(8))); + +struct foo5 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); /* { dg-warning "'x' offset 4 in 'struct foo5' isn't aligned to 16" } */ +}; /* { dg-warning "alignment 4 of 'struct foo5' is less than 16" } */ + +struct foo6 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); /* { dg-warning "'x' offset 4 in 'struct foo6' isn't aligned to 16" } */ +} __attribute__((aligned(16))); + +struct foo7 +{ + int i1; + int i2; + int i3; + int i4; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); + +union bar1 +{ + int i1; + __u64 x; +}; /* { dg-warning "alignment 4 of 'union bar1' is less than 8" } */ + +union bar2 +{ + int i1; + __u64 x; +} __attribute__((aligned(8))); + +union bar3 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +}; /* { dg-warning "alignment 4 of 'union bar3' is less than 16" } */ + +union bar4 +{ + int i1; + int x __attribute__((warn_if_not_aligned(16))); +} __attribute__((aligned(16))); diff --git a/gcc/testsuite/gcc.dg/pr53037-2.c b/gcc/testsuite/gcc.dg/pr53037-2.c new file mode 100644 index 0000000..f9934a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53037-2.c @@ -0,0 +1,37 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wpacked-not-aligned" } */ + +struct __attribute__ ((aligned (8))) S8 { char a[8]; }; +struct __attribute__ ((packed)) S1 { + struct S8 s8; +}; /* { dg-warning "alignment 1 of 'struct S1' is less than 8" } */ + +struct __attribute__ ((packed, aligned (8))) S2 { + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S3 { + int i1; + struct S8 s8; /* { dg-warning "'s8' offset 4 in 'struct S3' isn't aligned to 8" } */ +}; + +struct __attribute__ ((packed, aligned (8))) S4 { + int i1; + int i2; + struct S8 s8; +}; + +struct __attribute__ ((packed)) S5 { + long long ll; +}; + +union __attribute__ ((packed)) U1 { + int i1; + struct S8 s8; +}; /* { dg-warning "alignment 1 of 'union U1' is less than 8" } */ + +union __attribute__ ((packed, aligned (8))) U2 { + int i1; + struct S8 s8; +}; diff --git a/gcc/testsuite/gcc.dg/pr53037-3.c b/gcc/testsuite/gcc.dg/pr53037-3.c new file mode 100644 index 0000000..fc69ae8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53037-3.c @@ -0,0 +1,37 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wall" } */ + +struct __attribute__ ((aligned (8))) S8 { char a[8]; }; +struct __attribute__ ((packed)) S1 { + struct S8 s8; +}; /* { dg-warning "alignment 1 of 'struct S1' is less than 8" } */ + +struct __attribute__ ((packed, aligned (8))) S2 { + struct S8 s8; +}; + +struct __attribute__ ((packed, aligned (8))) S3 { + int i1; + struct S8 s8; /* { dg-warning "'s8' offset 4 in 'struct S3' isn't aligned to 8" } */ +}; + +struct __attribute__ ((packed, aligned (8))) S4 { + int i1; + int i2; + struct S8 s8; +}; + +struct __attribute__ ((packed)) S5 { + long long ll; +}; + +union __attribute__ ((packed)) U1 { + int i1; + struct S8 s8; +}; /* { dg-warning "alignment 1 of 'union U1' is less than 8" } */ + +union __attribute__ ((packed, aligned (8))) U2 { + int i1; + struct S8 s8; +}; diff --git a/gcc/testsuite/gcc.dg/pr53037-4.c b/gcc/testsuite/gcc.dg/pr53037-4.c new file mode 100644 index 0000000..feb3afa --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53037-4.c @@ -0,0 +1,24 @@ +/* PR c/53037. */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +int foo1 __attribute__((warn_if_not_aligned(8))); /* { dg-error "'warn_if_not_aligned' may not be specified for 'foo1'" } */ + +__attribute__((warn_if_not_aligned(8))) +void +foo2 (void) /* { dg-error "'warn_if_not_aligned' may not be specified for 'foo2'" } */ +{ +} + +struct foo3 +{ + int i : 2 __attribute__((warn_if_not_aligned(8))); /* { dg-error "'warn_if_not_aligned' may not be specified for 'i'" } */ +}; + +typedef unsigned int __u32 + __attribute__((aligned(4),warn_if_not_aligned(8))); + +struct foo4 +{ + __u32 i : 2; /* { dg-error "cannot declare bit-field 'i' with 'warn_if_not_aligned' type" } */ +}; diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 278d0c9..a58b673 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1523,8 +1523,9 @@ struct GTY(()) tree_type_common { so we need to store the value 32 (not 31, as we need the zero as well), hence six bits. */ unsigned align : 6; + unsigned warn_if_not_align : 6; unsigned typeless_storage : 1; - unsigned spare : 24; + unsigned spare : 18; alias_set_type alias_set; tree pointer_to; @@ -1631,7 +1632,11 @@ struct GTY(()) tree_decl_common { /* DECL_ALIGN. It should have the same size as TYPE_ALIGN. */ unsigned int align : 6; - /* 20 bits unused. */ + /* DECL_WARN_IF_NOT_ALIGN. It should have the same size as + TYPE_WARN_IF_NOT_ALIGN. */ + unsigned int warn_if_not_align : 6; + + /* 14 bits unused. */ /* UID for points-to sets, stable over copying from inlining. */ unsigned int pt_uid; diff --git a/gcc/tree.c b/gcc/tree.c index ca28afa..87f6504 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -8305,6 +8305,7 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared) TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (type); SET_TYPE_ALIGN (itype, TYPE_ALIGN (type)); TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type); + SET_TYPE_WARN_IF_NOT_ALIGN (itype, TYPE_WARN_IF_NOT_ALIGN (type)); if (!shared) return itype; diff --git a/gcc/tree.h b/gcc/tree.h index 91cf253..55f3ebf 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1922,6 +1922,16 @@ extern machine_mode element_mode (const_tree t); /* The alignment for NODE, in bytes. */ #define TYPE_ALIGN_UNIT(NODE) (TYPE_ALIGN (NODE) / BITS_PER_UNIT) +/* The minimum alignment necessary for objects of this type without + warning. The value is an int, measured in bits. */ +#define TYPE_WARN_IF_NOT_ALIGN(NODE) \ + (TYPE_CHECK (NODE)->type_common.warn_if_not_align \ + ? ((unsigned)1) << ((NODE)->type_common.warn_if_not_align - 1) : 0) + +/* Specify that TYPE_WARN_IF_NOT_ALIGN(NODE) is X. */ +#define SET_TYPE_WARN_IF_NOT_ALIGN(NODE, X) \ + (TYPE_CHECK (NODE)->type_common.warn_if_not_align = ffs_hwi (X)) + /* If your language allows you to declare types, and you want debug info for them, then you need to generate corresponding TYPE_DECL nodes. These "stub" TYPE_DECL nodes have no name, and simply point at the @@ -2377,6 +2387,16 @@ extern machine_mode element_mode (const_tree t); #define SET_DECL_ALIGN(NODE, X) \ (DECL_COMMON_CHECK (NODE)->decl_common.align = ffs_hwi (X)) +/* The minimum alignment necessary for the datum, in bits, without + warning. */ +#define DECL_WARN_IF_NOT_ALIGN(NODE) \ + (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align \ + ? ((unsigned)1) << ((NODE)->decl_common.warn_if_not_align - 1) : 0) + +/* Specify that DECL_WARN_IF_NOT_ALIGN(NODE) is X. */ +#define SET_DECL_WARN_IF_NOT_ALIGN(NODE, X) \ + (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align = ffs_hwi (X)) + /* The alignment of NODE, in bytes. */ #define DECL_ALIGN_UNIT(NODE) (DECL_ALIGN (NODE) / BITS_PER_UNIT) /* Set if the alignment of this DECL has been set by the user, for -- 2.9.4