From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22703 invoked by alias); 18 Dec 2018 14:11:08 -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 22676 invoked by uid 89); 18 Dec 2018 14:11:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS,TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=ba, pi, ci, align2c X-HELO: mail-pl1-f193.google.com Received: from mail-pl1-f193.google.com (HELO mail-pl1-f193.google.com) (209.85.214.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 18 Dec 2018 14:10:56 +0000 Received: by mail-pl1-f193.google.com with SMTP id z23so7888992plo.0 for ; Tue, 18 Dec 2018 06:10:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=GQ3azwr8Ctj60iqdUdb1M5XkR89pXid740F+d5KeMmY=; b=SCx8G4bEahfkzjgfR5l3MHKOboGK3lEmZu7BsDbVDJasmkfflTrZXwZu0xaJf1HO07 2nV15+sU0e4t5SI/5iI8mC3r9PForzVTkfo4JbHSw/jgq8sGs5hlIkvFo8cInhwHmwst WONXgO/E1nreW/j4E3FogqIR+jvwTziW2K57JSW6ZDC80ncOYyWHh5LoWgx6WELvJnod U6g+9yEkvRJxufc+MayRCuv9l7gEcoJz5unP8mIHAU3iTp3JZFoMuGRen5Q+C7fXzhBn P0GZRtnoesbvUbTlW4bHzLi2JvATt3BhHYUhaOT3DWVqe+/NrWCbr/IgxwQLG5zlNaJM NUjQ== Return-Path: Received: from gnu-cfl-2.localdomain (c-73-93-86-59.hsd1.ca.comcast.net. [73.93.86.59]) by smtp.gmail.com with ESMTPSA id l22sm25205595pfj.179.2018.12.18.06.10.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 06:10:53 -0800 (PST) Received: by gnu-cfl-2.localdomain (Postfix, from userid 1000) id DA7E1C02AD; Tue, 18 Dec 2018 06:10:51 -0800 (PST) Date: Tue, 18 Dec 2018 14:11:00 -0000 From: "H.J. Lu" To: Jason Merrill Cc: Richard Guenther , "Joseph S. Myers" , Martin Sebor , GCC Patches Subject: V7 [PATCH] C/C++: Add -Waddress-of-packed-member Message-ID: <20181218141051.GA3461@gmail.com> References: <24f8a201-bb3e-3acb-b679-570a8796358d@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) X-IsSubscribed: yes X-SW-Source: 2018-12/txt/msg01306.txt.bz2 On Mon, Dec 17, 2018 at 08:53:32AM -0500, Jason Merrill wrote: > On 12/17/18 7:42 AM, H.J. Lu wrote: > > On Mon, Dec 17, 2018 at 1:39 AM Richard Biener > > wrote: > > > > > > On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu wrote: > > > > > > > > On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill wrote: > > > > > > > > > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > > > > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill wrote: > > > > > > > > > > > > > > On 9/25/18 11:46 AM, H.J. Lu wrote: > > > > > > > > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill wrote: > > > > > > > > > On 07/23/2018 05:24 PM, H.J. Lu wrote: > > > > > > > > > > > > > > > > > > > > On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > On Mon, 18 Jun 2018, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > > > > > On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > On Mon, 18 Jun 2018, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > + if (TREE_CODE (rhs) == COND_EXPR) > > > > > > > > > > > > > > > + { > > > > > > > > > > > > > > > + /* Check the THEN path first. */ > > > > > > > > > > > > > > > + tree op1 = TREE_OPERAND (rhs, 1); > > > > > > > > > > > > > > > + context = check_address_of_packed_member (type, op1); > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > This should handle the GNU extension of re-using operand 0 if operand > > > > > > > > > > > > > > 1 is omitted. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Doesn't that just use a SAVE_EXPR? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Hmm, I suppose it does, but many places in the compiler seem to expect > > > > > > > > > > > > that it produces a COND_EXPR with TREE_OPERAND 1 as NULL_TREE. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Maybe that's used somewhere inside the C++ front end. For C a SAVE_EXPR > > > > > > > > > > > is produced directly. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Here is the updated patch. Changes from the last one: > > > > > > > > > > > > > > > > > > > > 1. Handle COMPOUND_EXPR. > > > > > > > > > > 2. Fixed typos in comments. > > > > > > > > > > 3. Combined warn_for_pointer_of_packed_member and > > > > > > > > > > warn_for_address_of_packed_member into > > > > > > > > > > warn_for_address_or_pointer_of_packed_member. > > > > > > > > > > > > > > > > > > > > > > > > > > > > c.i:4:33: warning: converting a packed ‘struct C *’ pointer increases the > > > > > > > > > > alignment of ‘long int *’ pointer from 1 to 8 [-Waddress-of-packed-member] > > > > > > > > > > > > > > > > > > > > > > > > > > > I think this would read better as > > > > > > > > > > > > > > > > > > c.i:4:33: warning: converting a packed ‘struct C *’ pointer (alignment 1) to > > > > > > > > > ‘long int *’ (alignment 8) may result in an unaligned pointer value > > > > > > > > > [-Waddress-of-packed-member] > > > > > > > > > > > > > > > > Fixed. > > > > > > > > > > > > > > > > > > + while (TREE_CODE (base) == ARRAY_REF) > > > > > > > > > > + base = TREE_OPERAND (base, 0); > > > > > > > > > > + if (TREE_CODE (base) != COMPONENT_REF) > > > > > > > > > > + return NULL_TREE; > > > > > > > > > > > > > > > > > > > > > > > > > > > Are you deliberately not handling the other handled_component_p cases? If > > > > > > > > > so, there should be a comment. > > > > > > > > > > > > > > > > I changed it to > > > > > > > > > > > > > > > > while (handled_component_p (base)) > > > > > > > > { > > > > > > > > enum tree_code code = TREE_CODE (base); > > > > > > > > if (code == COMPONENT_REF) > > > > > > > > break; > > > > > > > > switch (code) > > > > > > > > { > > > > > > > > case ARRAY_REF: > > > > > > > > base = TREE_OPERAND (base, 0); > > > > > > > > break; > > > > > > > > default: > > > > > > > > /* FIXME: Can it ever happen? */ > > > > > > > > gcc_unreachable (); > > > > > > > > break; > > > > > > > > } > > > > > > > > } > > > > > > > > > > > > > > > > Is there a testcase to trigger this ICE? I couldn't find one. > > > > > > > > > > > > > > You can take the address of an element of complex: > > > > > > > > > > > > > > __complex int i; > > > > > > > int *p = &__real(i); > > > > > > > > > > > > > > You may get VIEW_CONVERT_EXPR with location wrappers. > > > > > > > > > > > > Fixed. I replaced gcc_unreachable with return NULL_TREE; > > > > > > > > > > Then we're back to my earlier question: are you deliberately not > > > > > handling the other cases? Why not look through them as well? What if > > > > > e.g. the operand of __real is a packed field? > > > > > > > > > > > > > Here is the updated patch with > > > > > > > > diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c > > > > index 615134cfdac..f105742598e 100644 > > > > --- a/gcc/c-family/c-warn.c > > > > +++ b/gcc/c-family/c-warn.c > > > > @@ -2669,6 +2669,9 @@ check_address_of_packed_member (tree type, tree rhs) > > > > switch (code) > > > > { > > > > case ARRAY_REF: > > > > + case REALPART_EXPR: > > > > + case IMAGPART_EXPR: > > > > + case VIEW_CONVERT_EXPR: > > > > base = TREE_OPERAND (base, 0); > > > > break; > > > > default: > > > > > > don't we have handled_component_p () for this? (you're still > > > missing BIT_FIELD_REF which might be used for vector > > > element accesses) > > > > > > > Do you have a testcase? > > Is there a reason you only want to handle some component references and not > others? If not, checking handled_component_p is simpler and more future > proof than enumerating specific codes. > Here is the updated patch. The difference from the last patch is while (handled_component_p (base)) { if (TREE_CODE (base) == COMPONENT_REF) break; base = TREE_OPERAND (base, 0); } OK for trunk? H.J. --- When address of packed member of struct or union is taken, it may result in an unaligned pointer value. This patch adds -Waddress-of-packed-member to check alignment at pointer assignment and warn unaligned address as well as unaligned pointer: $ cat x.i struct pair_t { char c; int i; } __attribute__ ((packed)); extern struct pair_t p; int *addr = &p.i; $ gcc -O2 -S x.i x.i:8:13: warning: taking address of packed member of ‘struct pair_t’ may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | int *addr = &p.i; | ^ $ cat c.i struct B { int i; }; struct C { struct B b; } __attribute__ ((packed)); long* g8 (struct C *p) { return p; } $ gcc -O2 -S c.i -Wno-incompatible-pointer-types c.i: In function ‘g8’: c.i:4:18: warning: converting a packed ‘struct C *’ pointer (alignment 1) to ‘long int *’ (alignment 8) may may result in an unaligned pointer value [-Waddress-of-packed-member] 4 | long* g8 (struct C *p) { return p; } | ^ c.i:2:8: note: defined here 2 | struct C { struct B b; } __attribute__ ((packed)); | ^ $ This warning is enabled by default. Since read_encoded_value_with_base in unwind-pe.h has union unaligned { void *ptr; unsigned u2 __attribute__ ((mode (HI))); unsigned u4 __attribute__ ((mode (SI))); unsigned u8 __attribute__ ((mode (DI))); signed s2 __attribute__ ((mode (HI))); signed s4 __attribute__ ((mode (SI))); signed s8 __attribute__ ((mode (DI))); } __attribute__((__packed__)); _Unwind_Internal_Ptr result; and GCC warns: gcc/libgcc/unwind-pe.h:210:37: warning: taking address of packed member of 'union unaligned' may result in an unaligned pointer value [-Waddress-of-packed-member] result = (_Unwind_Internal_Ptr) u->ptr; ^ we need to add GCC pragma to ignore -Waddress-of-packed-member. gcc/c/ PR c/51628 * doc/invoke.texi: Document -Wno-address-of-packed-member. gcc/c-family/ PR c/51628 * c-common.h (warn_for_address_or_pointer_of_packed_member): New. * c-warn.c (check_alignment_of_packed_member): New function. (check_address_of_packed_member): Likewise. (check_and_warn_address_of_packed_member): Likewise. (warn_for_address_or_pointer_of_packed_member): Likewise. * c.opt: Add -Wno-address-of-packed-member. gcc/c/ PR c/51628 * c-typeck.c (convert_for_assignment): Call warn_for_address_or_pointer_of_packed_member. gcc/cp/ PR c/51628 * call.c (convert_for_arg_passing): Call warn_for_address_or_pointer_of_packed_member. * typeck.c (convert_for_assignment): Likewise. gcc/testsuite/ PR c/51628 * c-c++-common/pr51628-1.c: New test. * c-c++-common/pr51628-2.c: Likewise. * c-c++-common/pr51628-3.c: Likewise. * c-c++-common/pr51628-4.c: Likewise. * c-c++-common/pr51628-5.c: Likewise. * c-c++-common/pr51628-6.c: Likewise. * c-c++-common/pr51628-7.c: Likewise. * c-c++-common/pr51628-8.c: Likewise. * c-c++-common/pr51628-9.c: Likewise. * c-c++-common/pr51628-10.c: Likewise. * c-c++-common/pr51628-11.c: Likewise. * c-c++-common/pr51628-12.c: Likewise. * c-c++-common/pr51628-13.c: Likewise. * c-c++-common/pr51628-14.c: Likewise. * c-c++-common/pr51628-15.c: Likewise. * c-c++-common/pr51628-26.c: Likewise. * c-c++-common/pr51628-27.c: Likewise. * c-c++-common/pr51628-28.c: Likewise. * c-c++-common/pr51628-29.c: Likewise. * c-c++-common/pr51628-30.c: Likewise. * c-c++-common/pr51628-31.c: Likewise. * gcc.dg/pr51628-17.c: Likewise. * gcc.dg/pr51628-18.c: Likewise. * gcc.dg/pr51628-19.c: Likewise. * gcc.dg/pr51628-20.c: Likewise. * gcc.dg/pr51628-21.c: Likewise. * gcc.dg/pr51628-22.c: Likewise. * gcc.dg/pr51628-23.c: Likewise. * gcc.dg/pr51628-24.c: Likewise. * gcc.dg/pr51628-25.c: Likewise. * c-c++-common/asan/misalign-1.c: Add -Wno-address-of-packed-member. * c-c++-common/asan/misalign-2.c: Likewise. * c-c++-common/ubsan/align-2.c: Likewise. * c-c++-common/ubsan/align-4.c: Likewise. * c-c++-common/ubsan/align-6.c: Likewise. * c-c++-common/ubsan/align-7.c: Likewise. * c-c++-common/ubsan/align-8.c: Likewise. * c-c++-common/ubsan/align-10.c: Likewise. * g++.dg/ubsan/align-2.C: Likewise. * gcc.target/i386/avx512bw-vmovdqu16-2.c: Likewise. * gcc.target/i386/avx512f-vmovdqu32-2.c: Likewise. * gcc.target/i386/avx512f-vmovdqu64-2.c: Likewise. * gcc.target/i386/avx512vl-vmovdqu16-2.c: Likewise. * gcc.target/i386/avx512vl-vmovdqu32-2.c: Likewise. * gcc.target/i386/avx512vl-vmovdqu64-2.c: Likewise. libgcc/ * unwind-pe.h (read_encoded_value_with_base): Add GCC pragma to ignore -Waddress-of-packed-member. --- gcc/c-family/c-common.h | 1 + gcc/c-family/c-warn.c | 184 ++++++++++++++++++ gcc/c-family/c.opt | 4 + gcc/c/c-typeck.c | 11 +- gcc/cp/call.c | 3 + gcc/cp/typeck.c | 2 + gcc/doc/invoke.texi | 8 + gcc/testsuite/c-c++-common/asan/misalign-1.c | 2 +- gcc/testsuite/c-c++-common/asan/misalign-2.c | 2 +- gcc/testsuite/c-c++-common/pr51628-1.c | 29 +++ gcc/testsuite/c-c++-common/pr51628-10.c | 24 +++ gcc/testsuite/c-c++-common/pr51628-11.c | 17 ++ gcc/testsuite/c-c++-common/pr51628-12.c | 18 ++ gcc/testsuite/c-c++-common/pr51628-13.c | 9 + gcc/testsuite/c-c++-common/pr51628-14.c | 9 + gcc/testsuite/c-c++-common/pr51628-15.c | 14 ++ gcc/testsuite/c-c++-common/pr51628-16.c | 13 ++ gcc/testsuite/c-c++-common/pr51628-2.c | 29 +++ gcc/testsuite/c-c++-common/pr51628-26.c | 33 ++++ gcc/testsuite/c-c++-common/pr51628-27.c | 12 ++ gcc/testsuite/c-c++-common/pr51628-28.c | 17 ++ gcc/testsuite/c-c++-common/pr51628-29.c | 16 ++ gcc/testsuite/c-c++-common/pr51628-3.c | 35 ++++ gcc/testsuite/c-c++-common/pr51628-30.c | 23 +++ gcc/testsuite/c-c++-common/pr51628-31.c | 16 ++ gcc/testsuite/c-c++-common/pr51628-4.c | 35 ++++ gcc/testsuite/c-c++-common/pr51628-5.c | 35 ++++ gcc/testsuite/c-c++-common/pr51628-6.c | 35 ++++ gcc/testsuite/c-c++-common/pr51628-7.c | 29 +++ gcc/testsuite/c-c++-common/pr51628-8.c | 36 ++++ gcc/testsuite/c-c++-common/pr51628-9.c | 36 ++++ gcc/testsuite/c-c++-common/ubsan/align-10.c | 2 +- gcc/testsuite/c-c++-common/ubsan/align-2.c | 2 +- gcc/testsuite/c-c++-common/ubsan/align-4.c | 2 +- gcc/testsuite/c-c++-common/ubsan/align-6.c | 2 +- gcc/testsuite/c-c++-common/ubsan/align-7.c | 2 +- gcc/testsuite/c-c++-common/ubsan/align-8.c | 2 +- gcc/testsuite/g++.dg/ubsan/align-2.C | 2 +- gcc/testsuite/gcc.dg/pr51628-17.c | 10 + gcc/testsuite/gcc.dg/pr51628-18.c | 23 +++ gcc/testsuite/gcc.dg/pr51628-19.c | 26 +++ gcc/testsuite/gcc.dg/pr51628-20.c | 11 ++ gcc/testsuite/gcc.dg/pr51628-21.c | 11 ++ gcc/testsuite/gcc.dg/pr51628-22.c | 9 + gcc/testsuite/gcc.dg/pr51628-23.c | 9 + gcc/testsuite/gcc.dg/pr51628-24.c | 10 + gcc/testsuite/gcc.dg/pr51628-25.c | 9 + .../gcc.target/i386/avx512bw-vmovdqu16-2.c | 2 +- .../gcc.target/i386/avx512f-vmovdqu32-2.c | 2 +- .../gcc.target/i386/avx512f-vmovdqu64-2.c | 2 +- .../gcc.target/i386/avx512vl-vmovdqu16-2.c | 2 +- .../gcc.target/i386/avx512vl-vmovdqu32-2.c | 2 +- .../gcc.target/i386/avx512vl-vmovdqu64-2.c | 2 +- libgcc/unwind-pe.h | 5 + 54 files changed, 870 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr51628-1.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-10.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-11.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-12.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-13.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-14.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-15.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-16.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-2.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-26.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-27.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-28.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-29.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-3.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-30.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-31.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-4.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-5.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-6.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-7.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-8.c create mode 100644 gcc/testsuite/c-c++-common/pr51628-9.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-17.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-18.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-19.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-20.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-21.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-22.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-23.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-24.c create mode 100644 gcc/testsuite/gcc.dg/pr51628-25.c diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 4187343c0b3..eb0ad60940d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1282,6 +1282,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool, bool); extern void warn_for_omitted_condop (location_t, tree); extern bool warn_for_restrict (unsigned, tree *, unsigned); +extern void warn_for_address_or_pointer_of_packed_member (bool, tree, tree); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 798ad1bcb39..ca28dd66918 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2616,3 +2616,187 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc, inform (guard_loc, "some parts of macro expansion are not guarded by " "this %qs clause", guard_tinfo_to_string (keyword)); } + +/* Return struct or union type if the alignment of data memeber, FIELD, + is less than the alignment of TYPE. Otherwise, return NULL_TREE. */ + +static tree +check_alignment_of_packed_member (tree type, tree field) +{ + /* Check alignment of the data member. */ + if (TREE_CODE (field) == FIELD_DECL + && (DECL_PACKED (field) + || TYPE_PACKED (TREE_TYPE (field)))) + { + /* Check the expected alignment against the field alignment. */ + unsigned int type_align = TYPE_ALIGN (type); + tree context = DECL_CONTEXT (field); + unsigned int record_align = TYPE_ALIGN (context); + if ((record_align % type_align) != 0) + return context; + tree field_off = byte_position (field); + if (!multiple_of_p (TREE_TYPE (field_off), field_off, + size_int (type_align / BITS_PER_UNIT))) + return context; + } + + return NULL_TREE; +} + +/* Return struct or union type if the right hand value, RHS, takes the + unaligned address of packed member of struct or union when assigning + to TYPE. Otherwise, return NULL_TREE. */ + +static tree +check_address_of_packed_member (tree type, tree rhs) +{ + tree base; + tree object; + tree field; + + if (INDIRECT_REF_P (rhs)) + rhs = TREE_OPERAND (rhs, 0); + + switch (TREE_CODE (rhs)) + { + case ADDR_EXPR: + base = TREE_OPERAND (rhs, 0); + while (handled_component_p (base)) + { + if (TREE_CODE (base) == COMPONENT_REF) + break; + base = TREE_OPERAND (base, 0); + } + if (TREE_CODE (base) != COMPONENT_REF) + return NULL_TREE; + object = TREE_OPERAND (base, 0); + field = TREE_OPERAND (base, 1); + break; + case COMPONENT_REF: + object = TREE_OPERAND (rhs, 0); + field = TREE_OPERAND (rhs, 1); + break; + default: + return NULL_TREE; + } + + tree context = check_alignment_of_packed_member (type, field); + if (context) + return context; + + /* Check alignment of the object. */ + while (TREE_CODE (object) == COMPONENT_REF) + { + field = TREE_OPERAND (object, 1); + context = check_alignment_of_packed_member (type, field); + if (context) + return context; + object = TREE_OPERAND (object, 0); + } + + return NULL_TREE; +} + +/* Check and warn if the right hand value, RHS, takes the unaligned + address of packed member of struct or union when assigning to TYPE. */ + +static void +check_and_warn_address_of_packed_member (tree type, tree rhs) +{ + if (TREE_CODE (rhs) != COND_EXPR) + { + tree context = check_address_of_packed_member (type, rhs); + if (context) + { + location_t loc = EXPR_LOC_OR_LOC (rhs, input_location); + warning_at (loc, OPT_Waddress_of_packed_member, + "taking address of packed member of %qT may result " + "in an unaligned pointer value", + context); + } + return; + } + + /* Check the THEN path. */ + check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 1)); + + /* Check the ELSE path. */ + check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 2)); +} + +/* Warn if the right hand value, RHS: + 1. For CONVERT_P == true, is a pointer value which isn't aligned to a + pointer type TYPE. + 2. For CONVERT_P == false, is an address which takes the unaligned + address of packed member of struct or union when assigning to TYPE. +*/ + +void +warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type, + tree rhs) +{ + if (!warn_address_of_packed_member) + return; + + /* Don't warn if we don't assign RHS to a pointer. */ + if (!POINTER_TYPE_P (type)) + return; + + while (TREE_CODE (rhs) == COMPOUND_EXPR) + rhs = TREE_OPERAND (rhs, 1); + + if (convert_p) + { + bool rhspointer_p; + tree rhstype; + + /* Check the original type of RHS. */ + switch (TREE_CODE (rhs)) + { + case PARM_DECL: + case VAR_DECL: + rhstype = TREE_TYPE (rhs); + rhspointer_p = POINTER_TYPE_P (rhstype); + break; + case NOP_EXPR: + rhs = TREE_OPERAND (rhs, 0); + if (TREE_CODE (rhs) == ADDR_EXPR) + rhs = TREE_OPERAND (rhs, 0); + rhstype = TREE_TYPE (rhs); + rhspointer_p = TREE_CODE (rhstype) == ARRAY_TYPE; + break; + default: + return; + } + + if (rhspointer_p && TYPE_PACKED (TREE_TYPE (rhstype))) + { + unsigned int type_align = TYPE_ALIGN_UNIT (TREE_TYPE (type)); + unsigned int rhs_align = TYPE_ALIGN_UNIT (TREE_TYPE (rhstype)); + if ((rhs_align % type_align) != 0) + { + location_t location = EXPR_LOC_OR_LOC (rhs, input_location); + warning_at (location, OPT_Waddress_of_packed_member, + "converting a packed %qT pointer (alignment %d) " + "to %qT (alignment %d) may may result in an " + "unaligned pointer value", + rhstype, rhs_align, type, type_align); + tree decl = TYPE_STUB_DECL (TREE_TYPE (rhstype)); + inform (DECL_SOURCE_LOCATION (decl), "defined here"); + decl = TYPE_STUB_DECL (TREE_TYPE (type)); + if (decl) + inform (DECL_SOURCE_LOCATION (decl), "defined here"); + } + } + } + else + { + /* Get the type of the pointer pointing to. */ + type = TREE_TYPE (type); + + if (TREE_CODE (rhs) == NOP_EXPR) + rhs = TREE_OPERAND (rhs, 0); + + check_and_warn_address_of_packed_member (type, rhs); + } +} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 07ff1c84f96..22ccf910a85 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -625,6 +625,10 @@ Wincompatible-pointer-types C ObjC Var(warn_incompatible_pointer_types) Init(1) Warning Warn when there is a conversion between pointers that have incompatible types. +Waddress-of-packed-member +C ObjC C++ ObjC++ Var(warn_address_of_packed_member) Init(1) Warning +Warn when the address of packed member of struct or union is taken. + Winit-self C ObjC C++ ObjC++ Var(warn_init_self) Warning LangEnabledBy(C++ ObjC++,Wall) Warn about variables which are initialized to themselves. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 1a897273088..da4a8169d56 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -6724,7 +6724,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) - return rhs; + { + warn_for_address_or_pointer_of_packed_member (false, type, + orig_rhs); + return rhs; + } if (coder == VOID_TYPE) { @@ -7279,6 +7283,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } } + /* If RHS is't an address, check pointer or array of packed + struct or union. */ + warn_for_address_or_pointer_of_packed_member + (TREE_CODE (orig_rhs) != ADDR_EXPR, type, orig_rhs); + return convert (type, rhs); } else if (codel == POINTER_TYPE && coder == ARRAY_TYPE) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6328a36b604..40ffc863091 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7618,6 +7618,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain) } maybe_warn_parm_abi (type, cp_expr_loc_or_loc (val, input_location)); } + + warn_for_address_or_pointer_of_packed_member (false, type, val); + return val; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 47ddad16fc1..70b60a928f4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9036,6 +9036,8 @@ convert_for_assignment (tree type, tree rhs, TREE_NO_WARNING (rhs) = 1; } + warn_for_address_or_pointer_of_packed_member (false, type, rhs); + return perform_implicit_conversion_flags (strip_top_quals (type), rhs, complain, flags); } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ac2ee59d92c..47f2fc3f518 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -358,6 +358,7 @@ Objective-C and Objective-C++ Dialects}. -Wuseless-cast -Wvariadic-macros -Wvector-operation-performance @gol -Wvla -Wvla-larger-than=@var{byte-size} -Wvolatile-register-var @gol -Wwrite-strings @gol +-Waddress-of-packed-member @gol -Wzero-as-null-pointer-constant -Whsa} @item C and Objective-C-only Warning Options @@ -6981,6 +6982,13 @@ behavior and are not portable in C, so they usually indicate that the programmer intended to use @code{strcmp}. This warning is enabled by @option{-Wall}. +@item -Waddress-of-packed-member +@opindex Waddress-of-packed-member +@opindex Wno-address-of-packed-member +Warn when the address of packed member of struct or union is taken, +which usually results in an unaligned pointer value. This is +enabled by default. + @item -Wlogical-op @opindex Wlogical-op @opindex Wno-logical-op diff --git a/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc/testsuite/c-c++-common/asan/misalign-1.c index 5cd605ac045..ebeb0306706 100644 --- a/gcc/testsuite/c-c++-common/asan/misalign-1.c +++ b/gcc/testsuite/c-c++-common/asan/misalign-1.c @@ -1,5 +1,5 @@ /* { dg-do run { target { ilp32 || lp64 } } } */ -/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2 -Wno-address-of-packed-member" } } */ /* { dg-additional-options "-fno-omit-frame-pointer" { target *-*-darwin* } } */ /* { dg-shouldfail "asan" } */ diff --git a/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc/testsuite/c-c++-common/asan/misalign-2.c index a6ed49bac05..b27e22d35a8 100644 --- a/gcc/testsuite/c-c++-common/asan/misalign-2.c +++ b/gcc/testsuite/c-c++-common/asan/misalign-2.c @@ -1,5 +1,5 @@ /* { dg-do run { target { ilp32 || lp64 } } } */ -/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2 -Wno-address-of-packed-member" } } */ /* { dg-additional-options "-fno-omit-frame-pointer" { target *-*-darwin* } } */ /* { dg-shouldfail "asan" } */ diff --git a/gcc/testsuite/c-c++-common/pr51628-1.c b/gcc/testsuite/c-c++-common/pr51628-1.c new file mode 100644 index 00000000000..5324f9cc964 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-1.c @@ -0,0 +1,29 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i; +} __attribute__((packed, aligned (4))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; + bar (p0); + p1 = &arr[1].i; + bar (p1); + bar (&p.i); + x = &p.i; + return &p.i; +} diff --git a/gcc/testsuite/c-c++-common/pr51628-10.c b/gcc/testsuite/c-c++-common/pr51628-10.c new file mode 100644 index 00000000000..085fe1608c4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-10.c @@ -0,0 +1,24 @@ +/* PR c/51628. */ +/* { dg-do run { target int128 } } */ +/* { dg-options "-O2" } */ + +struct pair_t +{ + char c; + __int128_t i; +} __attribute__ ((packed)); + +typedef struct unaligned_int128_t_ +{ + __int128_t value; +} __attribute__((packed)) unaligned_int128_t; + +struct pair_t p = {0, 1}; +unaligned_int128_t *addr = (unaligned_int128_t *) &p.i; + +int +main() +{ + addr->value = ~(__int128_t)0; + return (p.i != 1) ? 0 : 1; +} diff --git a/gcc/testsuite/c-c++-common/pr51628-11.c b/gcc/testsuite/c-c++-common/pr51628-11.c new file mode 100644 index 00000000000..7661232ac88 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-11.c @@ -0,0 +1,17 @@ +/* PR c/51628. */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O" } */ + +struct tuple_t +{ + char c[12]; + __int128_t i; +} __attribute__((packed, aligned (8))); + +typedef struct unaligned_int128_t_ +{ + __int128_t value; +} __attribute__ ((packed, aligned(4))) unaligned_int128_t; + +struct tuple_t p = {{0}, 1}; +unaligned_int128_t *addr = (unaligned_int128_t *)(&p.i); diff --git a/gcc/testsuite/c-c++-common/pr51628-12.c b/gcc/testsuite/c-c++-common/pr51628-12.c new file mode 100644 index 00000000000..bc221fa87ef --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-12.c @@ -0,0 +1,18 @@ +/* PR c/51628. */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O" } */ + +struct tuple_t +{ + char c[10]; + __int128_t i; +} __attribute__((packed, aligned (8))); + +typedef struct unaligned_int128_t_ +{ + __int128_t value; +} __attribute__ ((packed, aligned(4))) unaligned_int128_t; + +struct tuple_t p = {{0}, 1}; +unaligned_int128_t *addr = (unaligned_int128_t *)(&p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/pr51628-13.c b/gcc/testsuite/c-c++-common/pr51628-13.c new file mode 100644 index 00000000000..0edd5e7f84d --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-13.c @@ -0,0 +1,9 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct B { int i; }; +struct C { struct B b; } __attribute__ ((packed)); + +int* h4 (struct C *p) { return &p->b.i; } +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/pr51628-14.c b/gcc/testsuite/c-c++-common/pr51628-14.c new file mode 100644 index 00000000000..f50378b8651 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-14.c @@ -0,0 +1,9 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +void* f0 (struct A *p) { return &p->i; } diff --git a/gcc/testsuite/c-c++-common/pr51628-15.c b/gcc/testsuite/c-c++-common/pr51628-15.c new file mode 100644 index 00000000000..bcac6d70ad5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-15.c @@ -0,0 +1,14 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +int* +f (struct A *p, int *q) +{ + return q ? q : &p->i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-16.c b/gcc/testsuite/c-c++-common/pr51628-16.c new file mode 100644 index 00000000000..cd502fe76b8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-16.c @@ -0,0 +1,13 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct __attribute__ ((packed)) A { int i; }; +struct B { + struct A a; +} b; + +int *p = (int*)&b.a.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +int *q = (int*)&b.a; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/pr51628-2.c b/gcc/testsuite/c-c++-common/pr51628-2.c new file mode 100644 index 00000000000..abfb84ddd05 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-2.c @@ -0,0 +1,29 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i; +} __attribute__((packed, aligned (8))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; + bar (p0); + p1 = &arr[1].i; + bar (p1); + bar (&p.i); + x = &p.i; + return &p.i; +} diff --git a/gcc/testsuite/c-c++-common/pr51628-26.c b/gcc/testsuite/c-c++-common/pr51628-26.c new file mode 100644 index 00000000000..2042379860a --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-26.c @@ -0,0 +1,33 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +struct A p = {1}; +int *addr; + +int i, j; + +void +foo1 (void) +{ + addr = (i = -1, &p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} + +void +foo2 (void) +{ + addr = (i = -1, j = -2, &p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} + +void +foo3 (void) +{ + addr = (i = -1, (j = -2, &p.i)); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-27.c b/gcc/testsuite/c-c++-common/pr51628-27.c new file mode 100644 index 00000000000..9ae1efd7afb --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-27.c @@ -0,0 +1,12 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { int i; } __attribute__ ((packed)); +struct B { struct A a; }; +struct C { struct B b; }; + +extern struct C *p; + +int* g8 (void) { return &p->b.a.i; } +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/pr51628-28.c b/gcc/testsuite/c-c++-common/pr51628-28.c new file mode 100644 index 00000000000..e8c752d0b12 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-28.c @@ -0,0 +1,17 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +int * +foo3 (struct A *p1, int *q1, int *q2, struct A *p2) +{ + return (q1 + ? &p1->i +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : (q2 ? &p2->i : q2)); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-29.c b/gcc/testsuite/c-c++-common/pr51628-29.c new file mode 100644 index 00000000000..94b3722d2c8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-29.c @@ -0,0 +1,16 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { int i; }; +struct B { struct A a; }; +struct C { struct B b __attribute__ ((packed)); }; + +extern struct C *p; + +int* +g8 (void) +{ + return &p->b.a.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-3.c b/gcc/testsuite/c-c++-common/pr51628-3.c new file mode 100644 index 00000000000..0ea94c845a0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-3.c @@ -0,0 +1,35 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i; +} __attribute__((packed, aligned (2))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &arr[1].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (&p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-30.c b/gcc/testsuite/c-c++-common/pr51628-30.c new file mode 100644 index 00000000000..578edf4e8f9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-30.c @@ -0,0 +1,23 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A { __complex int i; }; +struct B { struct A a; }; +struct C { struct B b __attribute__ ((packed)); }; + +extern struct C *p; + +int* +foo1 (void) +{ + return &__real(p->b.a.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} + +int* +foo2 (void) +{ + return &__imag(p->b.a.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-31.c b/gcc/testsuite/c-c++-common/pr51628-31.c new file mode 100644 index 00000000000..9730f53f582 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-31.c @@ -0,0 +1,16 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +typedef int v4si __attribute__((vector_size(16))); +struct X +{ + v4si x; +} __attribute__((packed)) x; + +int * +foo() +{ + return &x.x[1]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-4.c b/gcc/testsuite/c-c++-common/pr51628-4.c new file mode 100644 index 00000000000..c4c1fb72d6d --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-4.c @@ -0,0 +1,35 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i; +} __attribute__((packed)); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &arr[1].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (&p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-5.c b/gcc/testsuite/c-c++-common/pr51628-5.c new file mode 100644 index 00000000000..9d7c309a0ef --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-5.c @@ -0,0 +1,35 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + char x; + int i; +} __attribute__((packed)); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &arr[1].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (&p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-6.c b/gcc/testsuite/c-c++-common/pr51628-6.c new file mode 100644 index 00000000000..52aa07a4cf3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-6.c @@ -0,0 +1,35 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + char x; + int i; +} __attribute__((packed, aligned (4))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (void) +{ + struct pair_t arr[2] = { { 1, 10 }, { 2, 20 } }; + int *p0, *p1; + p0 = &arr[0].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &arr[1].i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (&p.i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-7.c b/gcc/testsuite/c-c++-common/pr51628-7.c new file mode 100644 index 00000000000..ae4a681f966 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-7.c @@ -0,0 +1,29 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i[4]; +} __attribute__((packed, aligned (4))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = p.i; + +int * +foo (struct pair_t *p) +{ + int *p0, *p1; + p0 = p->i; + bar (p0); + p1 = &p->i[1]; + bar (p1); + bar (p->i); + bar (&p->i[2]); + x = p->i; + return &p->i[3]; +} diff --git a/gcc/testsuite/c-c++-common/pr51628-8.c b/gcc/testsuite/c-c++-common/pr51628-8.c new file mode 100644 index 00000000000..cc2dae096ae --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-8.c @@ -0,0 +1,36 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + char x; + int i[4]; +} __attribute__ ((packed, aligned (4))); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (struct pair_t *p) +{ + int *p0, *p1; + p0 = p->i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &p->i[1]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (p->i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (&p->i[2]); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = p->i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p->i[3]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/pr51628-9.c b/gcc/testsuite/c-c++-common/pr51628-9.c new file mode 100644 index 00000000000..0470aa3b93d --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-9.c @@ -0,0 +1,36 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct pair_t +{ + int x; + int i[4]; +} __attribute__ ((packed)); + +extern struct pair_t p; +extern int *x; +extern void bar (int *); + +int *addr = p.i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + +int * +foo (struct pair_t *p) +{ + int *p0, *p1; + p0 = p->i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p0); + p1 = &p->i[1]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (p1); + bar (p->i); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + bar (&p->i[2]); +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + x = p->i; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + return &p->i[3]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/ubsan/align-10.c b/gcc/testsuite/c-c++-common/ubsan/align-10.c index 56ae9ebfe30..6210533173c 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-10.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-10.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-O -fsanitize=alignment -fsanitize-recover=alignment" } */ +/* { dg-options "-O -fsanitize=alignment -fsanitize-recover=alignment -Wno-address-of-packed-member" } */ struct R { int a; } r; struct S { struct R a; char b; long long c; short d[10]; }; diff --git a/gcc/testsuite/c-c++-common/ubsan/align-2.c b/gcc/testsuite/c-c++-common/ubsan/align-2.c index 071de8c202a..336b1c3c907 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-2.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-2.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-fsanitize=alignment" } */ +/* { dg-options "-fsanitize=alignment -Wno-address-of-packed-member" } */ struct S { int a; char b; long long c; short d[10]; }; struct T { char a; long long b; }; diff --git a/gcc/testsuite/c-c++-common/ubsan/align-4.c b/gcc/testsuite/c-c++-common/ubsan/align-4.c index 3252595d330..d5feeee29c6 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-4.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-4.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-fsanitize=null,alignment" } */ +/* { dg-options "-fsanitize=null,alignment -Wno-address-of-packed-member" } */ #include "align-2.c" diff --git a/gcc/testsuite/c-c++-common/ubsan/align-6.c b/gcc/testsuite/c-c++-common/ubsan/align-6.c index 3364746fb27..0302b7b8894 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-6.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-6.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-O -fsanitize=alignment -fsanitize-recover=alignment" } */ +/* { dg-options "-O -fsanitize=alignment -fsanitize-recover=alignment -Wno-address-of-packed-member" } */ struct S { int a; char b; long long c; short d[10]; }; struct T { char a; long long b; }; diff --git a/gcc/testsuite/c-c++-common/ubsan/align-7.c b/gcc/testsuite/c-c++-common/ubsan/align-7.c index ec4e87f56d5..dd1e8c91cef 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-7.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-7.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-O -fsanitize=alignment -fno-sanitize-recover=alignment -fdump-tree-sanopt-details" } */ +/* { dg-options "-O -fsanitize=alignment -fno-sanitize-recover=alignment -Wno-address-of-packed-member -fdump-tree-sanopt-details" } */ /* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */ /* { dg-shouldfail "ubsan" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/align-8.c b/gcc/testsuite/c-c++-common/ubsan/align-8.c index 61c1ceb6682..5fe0e0fe931 100644 --- a/gcc/testsuite/c-c++-common/ubsan/align-8.c +++ b/gcc/testsuite/c-c++-common/ubsan/align-8.c @@ -1,6 +1,6 @@ /* Limit this to known non-strict alignment targets. */ /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ -/* { dg-options "-O -fsanitize=alignment -fsanitize-undefined-trap-on-error -fdump-tree-sanopt-details" } */ +/* { dg-options "-O -fsanitize=alignment -fsanitize-undefined-trap-on-error -Wno-address-of-packed-member -fdump-tree-sanopt-details" } */ /* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */ /* { dg-shouldfail "ubsan" } */ diff --git a/gcc/testsuite/g++.dg/ubsan/align-2.C b/gcc/testsuite/g++.dg/ubsan/align-2.C index 3e4f5485d02..c97ede88392 100644 --- a/gcc/testsuite/g++.dg/ubsan/align-2.C +++ b/gcc/testsuite/g++.dg/ubsan/align-2.C @@ -1,6 +1,6 @@ // Limit this to known non-strict alignment targets. // { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } -// { dg-options "-fsanitize=alignment -Wall -Wno-unused-variable -std=c++11" } +// { dg-options "-fsanitize=alignment -Wall -Wno-unused-variable -Wno-address-of-packed-member -std=c++11" } typedef const long int L; struct S { long int l; char buf[1 + sizeof (int) + sizeof (L)]; } s; diff --git a/gcc/testsuite/gcc.dg/pr51628-17.c b/gcc/testsuite/gcc.dg/pr51628-17.c new file mode 100644 index 00000000000..0be95b2294e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-17.c @@ -0,0 +1,10 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +long* f8 (struct A *p) { return &p->i; } +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-18.c b/gcc/testsuite/gcc.dg/pr51628-18.c new file mode 100644 index 00000000000..03a04eff75c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-18.c @@ -0,0 +1,23 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +void foo (int *); + +int * +bar (int n, int k, void *ptr) +{ + struct A + { + int c[k]; + int x[n]; + } __attribute__ ((packed, aligned (4))); + struct A *p = (struct A *) ptr; + + int *p0, *p1; + p0 = p->x; + foo (p0); + p1 = &p->x[1]; + foo (p1); + return &p->x[1]; +} diff --git a/gcc/testsuite/gcc.dg/pr51628-19.c b/gcc/testsuite/gcc.dg/pr51628-19.c new file mode 100644 index 00000000000..7ff03e85cea --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-19.c @@ -0,0 +1,26 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +void foo (int *); + +int * +bar (int n, int k, void *ptr) +{ + struct A + { + char c[k]; + int x[n]; + } __attribute__ ((packed)); + struct A *p = (struct A *) ptr; + + int *p0, *p1; + p0 = p->x; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + foo (p0); + p1 = &p->x[1]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + foo (p1); + return &p->x[1]; +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.dg/pr51628-20.c b/gcc/testsuite/gcc.dg/pr51628-20.c new file mode 100644 index 00000000000..80888283b73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-20.c @@ -0,0 +1,11 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct B { int i; }; +struct C { struct B b; } __attribute__ ((packed)); + +extern struct C *p; + +long* g8 (void) { return p; } +/* { dg-warning "may may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-21.c b/gcc/testsuite/gcc.dg/pr51628-21.c new file mode 100644 index 00000000000..3077e72c8d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-21.c @@ -0,0 +1,11 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct B { int i; }; +struct C { struct B b; } __attribute__ ((packed)); + +extern struct C p[]; + +long* g8 (void) { return p; } +/* { dg-warning "may may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-22.c b/gcc/testsuite/gcc.dg/pr51628-22.c new file mode 100644 index 00000000000..1bd5d791639 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-22.c @@ -0,0 +1,9 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct B { int i; }; +struct C { struct B b; } __attribute__ ((packed)); + +int* g4 (struct C *p) { return &p->b; } +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-23.c b/gcc/testsuite/gcc.dg/pr51628-23.c new file mode 100644 index 00000000000..5709be60ac8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-23.c @@ -0,0 +1,9 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +char* f0 (struct A *p) { return &p->i; } diff --git a/gcc/testsuite/gcc.dg/pr51628-24.c b/gcc/testsuite/gcc.dg/pr51628-24.c new file mode 100644 index 00000000000..3ad99cd2f16 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-24.c @@ -0,0 +1,10 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct A { + int i; +} __attribute__ ((packed)); + +short* f2 (struct A *p) { return &p->i; } +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-25.c b/gcc/testsuite/gcc.dg/pr51628-25.c new file mode 100644 index 00000000000..2fc5c028711 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr51628-25.c @@ -0,0 +1,9 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-incompatible-pointer-types" } */ + +struct B { int i; }; +struct C { struct B b; } __attribute__ ((packed)); + +long* g8 (struct C *p) { return p; } +/* { dg-warning "may may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-2.c b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-2.c index a61609c40d2..c6e3ebdc507 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512bw" } */ +/* { dg-options "-O2 -mavx512bw -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512bw } */ #define AVX512BW diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-2.c index f2edc3dff7b..95a657fc5ff 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512f } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu64-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu64-2.c index 14176965ace..954b091d976 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu64-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu64-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512f } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu16-2.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu16-2.c index 45ae83d4552..81465f8d9a0 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu16-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu16-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512bw -mavx512vl" } */ +/* { dg-options "-O2 -mavx512bw -mavx512vl -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512vl } */ /* { dg-require-effective-target avx512bw } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu32-2.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu32-2.c index 4b928d0cd42..19390664bd0 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu32-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu32-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512vl" } */ +/* { dg-options "-O2 -mavx512vl -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512vl } */ #define AVX512VL diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu64-2.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu64-2.c index 1863ed3616f..aea0c12a5ff 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu64-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqu64-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512vl" } */ +/* { dg-options "-O2 -mavx512vl -Wno-address-of-packed-member" } */ /* { dg-require-effective-target avx512vl } */ #define AVX512VL diff --git a/libgcc/unwind-pe.h b/libgcc/unwind-pe.h index dd5ae95fc2c..05c2fb4dd50 100644 --- a/libgcc/unwind-pe.h +++ b/libgcc/unwind-pe.h @@ -177,6 +177,9 @@ read_sleb128 (const unsigned char *p, _sleb128_t *val) The function returns P incremented past the value. BASE is as given by base_of_encoded_value for this encoding in the appropriate context. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + static const unsigned char * read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, const unsigned char *p, _Unwind_Ptr *val) @@ -270,6 +273,8 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, return p; } +#pragma GCC diagnostic pop + #ifndef NO_BASE_OF_ENCODED_VALUE /* Like read_encoded_value_with_base, but get the base from the context -- 2.19.2