* V4 [PATCH] C/C++: Add -Waddress-of-packed-member @ 2018-09-25 15:47 H.J. Lu 2018-11-04 15:16 ` PING: " H.J. Lu 2018-12-13 20:50 ` Jason Merrill 0 siblings, 2 replies; 23+ messages in thread From: H.J. Lu @ 2018-09-25 15:47 UTC (permalink / raw) To: Jason Merrill; +Cc: Joseph Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 7755 bytes --] On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > On 07/23/2018 05:24 PM, H.J. Lu wrote: >> >> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> >> wrote: >>> >>> On Mon, 18 Jun 2018, Jason Merrill wrote: >>> >>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> >>>> 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. >> + /* Check alignment of the object. */ >> + if (TREE_CODE (object) == COMPONENT_REF) >> + { >> + field = TREE_OPERAND (object, 1); >> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) >> + { >> + type_align = TYPE_ALIGN (type); >> + context = DECL_CONTEXT (field); >> + record_align = TYPE_ALIGN (context); >> + if ((record_align % type_align) != 0) >> + return context; >> + } >> + } > > > Why doesn't this recurse? What if you have a packed field three > COMPONENT_REFs down? My patch works on [hjl@gnu-cfl-1 pr51628-4]$ cat x.i 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; } [hjl@gnu-cfl-1 pr51628-4]$ make x.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S x.i x.i: In function ‘g8’: x.i:7:25: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 7 | int* g8 (void) { return &p->b.a.i; } | ^~~~~~~~~ [hjl@gnu-cfl-1 pr51628-4]$ If it isn't what you had in mind, can you give me a testcase? >> + 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); >> + if (context) >> + rhs = op1; >> + else >> + { >> + /* Check the ELSE path. */ >> + rhs = TREE_OPERAND (rhs, 2); >> + context = check_address_of_packed_member (type, rhs); >> + } >> + } > > > Likewise, what if you have more levels of COND_EXPR? Or COMPOUND_EXPR > within COND_EXPR? Fixed, now I got [hjl@gnu-cfl-1 pr51628-5]$ cat z.i struct A { int i; } __attribute__ ((packed)); int* foo3 (struct A *p1, int *q1, int *q2, struct A *p2) { return (q1 ? &p1->i : (q2 ? &p2->i : q2)); } [hjl@gnu-cfl-1 pr51628-5]$ make z.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S z.i z.i: In function ‘foo3’: z.i:9:13: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 9 | ? &p1->i | ^~~~~~ z.i:10:19: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 10 | : (q2 ? &p2->i : q2)); | ^~~~~~ [hjl@gnu-cfl-1 pr51628-5]$ >> @@ -7470,6 +7470,9 @@ convert_for_arg_passing (tree type, tree val, >> tsubst_flags_t complain) >> + warn_for_address_or_pointer_of_packed_member (true, type, val); > > >> @@ -8914,6 +8914,8 @@ convert_for_assignment (tree type, tree rhs, >> + warn_for_address_or_pointer_of_packed_member (true, type, rhs); > > > Why would address_p be true in these calls? It seems that you are warning > at the point of assignment but looking for the warning about taking the > address rather than the one about assignment. It happens only with C for incompatible pointer conversion: [hjl@gnu-cfl-1 pr51628-2]$ cat c.i struct B { int i; }; struct C { struct B b; } __attribute__ ((packed)); long* g8 (struct C *p) { return p; } [hjl@gnu-cfl-1 pr51628-2]$ make c.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S c.i c.i: In function ‘g8’: c.i:4:33: warning: returning ‘struct C *’ from a function with incompatible return type ‘long int *’ [-Wincompatible-pointer-types] 4 | long* g8 (struct C *p) { return p; } | ^ 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)); | ^ [hjl@gnu-cfl-1 pr51628-2]$ address_p is false in this case and rhs is PARM_DECL, VAR_DECL or NOP_EXPR. This comes from convert_for_assignment in c/c-typeck.c. For other compatible pointer assignment, address_p is true and rhs is ADDR_EXPR, PARM_DECL, VAR_DECL or NOP_EXPR. Check for ADDR_EXPR won't work. address_p isn't an appropriate parameter name. I changed it to convert_p to indicate that it is an incompatible pointer type conversion. > If you want to warn about taking the address, shouldn't that happen under > cp_build_addr_expr? Alternately, drop the address_p parameter and choose > your path inside warn_for_*_packed_member based on whether rhs is an > ADDR_EXPR there rather than in the caller. > Here is the updated patch. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: text/x-patch, Size: 49029 bytes --] From b5cecbaabfe0fde7aeb3d3c24d8959853985951c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 12 Jan 2018 21:12:05 -0800 Subject: [PATCH] C/C++: Add -Waddress-of-packed-member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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_address_of_packed_member): New function. (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. * 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 | 188 ++++++++++++++++++ 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 | 11 +- 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-3.c | 35 ++++ 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 + 51 files changed, 820 insertions(+), 18 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-3.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 9e868768d01..0d39004ae3d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1272,6 +1272,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 a1a7f935964..c14030cd1a7 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2609,3 +2609,191 @@ 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 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)) + { + 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; + } + } + 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; + unsigned int type_align, record_align; + + /* 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. */ + type_align = TYPE_ALIGN (type); + context = DECL_CONTEXT (field); + 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; + } + + /* Check alignment of the object. */ + if (TREE_CODE (object) == COMPONENT_REF) + { + field = TREE_OPERAND (object, 1); + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) + { + type_align = TYPE_ALIGN (type); + context = DECL_CONTEXT (field); + record_align = TYPE_ALIGN (context); + if ((record_align % type_align) != 0) + return context; + } + } + + 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 43d1d27ac00..3ceee456291 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -616,6 +616,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 a5a7da0084c..7ecd38b27d5 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -6541,7 +6541,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) { @@ -7036,6 +7040,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 b2ca667c8b4..8d4099d3dea 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7539,6 +7539,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 e9932202b46..1400f16a20e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8926,6 +8926,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 7ef4e7a449b..2815f495ebf 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -278,8 +278,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol -pedantic-errors @gol --w -Wextra -Wall -Waddress -Waggregate-return -Waligned-new @gol --Walloc-zero -Walloc-size-larger-than=@var{byte-size} +-w -Wextra -Wall -Waddress -Waddress-of-packed-member -Waggregate-return @gol +-Waligned-new -Walloc-zero -Walloc-size-larger-than=@var{byte-size} -Walloca -Walloca-larger-than=@var{byte-size} @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol -Wno-attributes -Wbool-compare -Wbool-operation @gol @@ -6701,6 +6701,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-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-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.17.1 ^ permalink raw reply [flat|nested] 23+ messages in thread
* PING: V4 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-09-25 15:47 V4 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu @ 2018-11-04 15:16 ` H.J. Lu 2018-11-25 14:38 ` PING^2: " H.J. Lu 2018-12-13 20:50 ` Jason Merrill 1 sibling, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-11-04 15:16 UTC (permalink / raw) To: Jason Merrill; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches On Tue, Sep 25, 2018 at 8:46 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > On 07/23/2018 05:24 PM, H.J. Lu wrote: > >> > >> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > >> wrote: > >>> > >>> On Mon, 18 Jun 2018, Jason Merrill wrote: > >>> > >>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > >>>> 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. > > >> + /* Check alignment of the object. */ > >> + if (TREE_CODE (object) == COMPONENT_REF) > >> + { > >> + field = TREE_OPERAND (object, 1); > >> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) > >> + { > >> + type_align = TYPE_ALIGN (type); > >> + context = DECL_CONTEXT (field); > >> + record_align = TYPE_ALIGN (context); > >> + if ((record_align % type_align) != 0) > >> + return context; > >> + } > >> + } > > > > > > Why doesn't this recurse? What if you have a packed field three > > COMPONENT_REFs down? > > My patch works on > [hjl@gnu-cfl-1 pr51628-4]$ cat x.i > 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; } > [hjl@gnu-cfl-1 pr51628-4]$ make x.s > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S x.i > x.i: In function ‘g8’: > x.i:7:25: warning: taking address of packed member of ‘struct A’ may > result in an unaligned pointer value [-Waddress-of-packed-member] > 7 | int* g8 (void) { return &p->b.a.i; } > | ^~~~~~~~~ > [hjl@gnu-cfl-1 pr51628-4]$ > > If it isn't what you had in mind, can you give me a testcase? > > >> + 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); > >> + if (context) > >> + rhs = op1; > >> + else > >> + { > >> + /* Check the ELSE path. */ > >> + rhs = TREE_OPERAND (rhs, 2); > >> + context = check_address_of_packed_member (type, rhs); > >> + } > >> + } > > > > > > Likewise, what if you have more levels of COND_EXPR? Or COMPOUND_EXPR > > within COND_EXPR? > > Fixed, now I got > > [hjl@gnu-cfl-1 pr51628-5]$ cat z.i > struct A { > int i; > } __attribute__ ((packed)); > > int* > foo3 (struct A *p1, int *q1, int *q2, struct A *p2) > { > return (q1 > ? &p1->i > : (q2 ? &p2->i : q2)); > } > [hjl@gnu-cfl-1 pr51628-5]$ make z.s > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S z.i > z.i: In function ‘foo3’: > z.i:9:13: warning: taking address of packed member of ‘struct A’ may > result in an unaligned pointer value [-Waddress-of-packed-member] > 9 | ? &p1->i > | ^~~~~~ > z.i:10:19: warning: taking address of packed member of ‘struct A’ may > result in an unaligned pointer value [-Waddress-of-packed-member] > 10 | : (q2 ? &p2->i : q2)); > | ^~~~~~ > [hjl@gnu-cfl-1 pr51628-5]$ > > >> @@ -7470,6 +7470,9 @@ convert_for_arg_passing (tree type, tree val, > >> tsubst_flags_t complain) > >> + warn_for_address_or_pointer_of_packed_member (true, type, val); > > > > > >> @@ -8914,6 +8914,8 @@ convert_for_assignment (tree type, tree rhs, > >> + warn_for_address_or_pointer_of_packed_member (true, type, rhs); > > > > > > Why would address_p be true in these calls? It seems that you are warning > > at the point of assignment but looking for the warning about taking the > > address rather than the one about assignment. > > It happens only with C for incompatible pointer conversion: > > [hjl@gnu-cfl-1 pr51628-2]$ cat c.i > struct B { int i; }; > struct C { struct B b; } __attribute__ ((packed)); > > long* g8 (struct C *p) { return p; } > [hjl@gnu-cfl-1 pr51628-2]$ make c.s > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S c.i > c.i: In function ‘g8’: > c.i:4:33: warning: returning ‘struct C *’ from a function with > incompatible return type ‘long int *’ [-Wincompatible-pointer-types] > 4 | long* g8 (struct C *p) { return p; } > | ^ > 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)); > | ^ > [hjl@gnu-cfl-1 pr51628-2]$ > > address_p is false in this case and rhs is PARM_DECL, VAR_DECL or > NOP_EXPR. This comes from convert_for_assignment in c/c-typeck.c. > > For other compatible pointer assignment, address_p is true and rhs is > ADDR_EXPR, PARM_DECL, VAR_DECL or NOP_EXPR. Check > for ADDR_EXPR won't work. > > address_p isn't an appropriate parameter name. I changed it to convert_p > to indicate that it is an incompatible pointer type conversion. > > > If you want to warn about taking the address, shouldn't that happen under > > cp_build_addr_expr? Alternately, drop the address_p parameter and choose > > your path inside warn_for_*_packed_member based on whether rhs is an > > ADDR_EXPR there rather than in the caller. > > > > Here is the updated patch. OK for trunk? > > Thanks. PING: https://gcc.gnu.org/ml/gcc-patches/2018-09/msg01452.html -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* PING^2: V4 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-11-04 15:16 ` PING: " H.J. Lu @ 2018-11-25 14:38 ` H.J. Lu 0 siblings, 0 replies; 23+ messages in thread From: H.J. Lu @ 2018-11-25 14:38 UTC (permalink / raw) To: Jason Merrill; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches On Sun, Nov 4, 2018 at 7:16 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Tue, Sep 25, 2018 at 8:46 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > > On 07/23/2018 05:24 PM, H.J. Lu wrote: > > >> > > >> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > > >> wrote: > > >>> > > >>> On Mon, 18 Jun 2018, Jason Merrill wrote: > > >>> > > >>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > > >>>> 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. > > > > >> + /* Check alignment of the object. */ > > >> + if (TREE_CODE (object) == COMPONENT_REF) > > >> + { > > >> + field = TREE_OPERAND (object, 1); > > >> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) > > >> + { > > >> + type_align = TYPE_ALIGN (type); > > >> + context = DECL_CONTEXT (field); > > >> + record_align = TYPE_ALIGN (context); > > >> + if ((record_align % type_align) != 0) > > >> + return context; > > >> + } > > >> + } > > > > > > > > > Why doesn't this recurse? What if you have a packed field three > > > COMPONENT_REFs down? > > > > My patch works on > > [hjl@gnu-cfl-1 pr51628-4]$ cat x.i > > 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; } > > [hjl@gnu-cfl-1 pr51628-4]$ make x.s > > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > > -S x.i > > x.i: In function ‘g8’: > > x.i:7:25: warning: taking address of packed member of ‘struct A’ may > > result in an unaligned pointer value [-Waddress-of-packed-member] > > 7 | int* g8 (void) { return &p->b.a.i; } > > | ^~~~~~~~~ > > [hjl@gnu-cfl-1 pr51628-4]$ > > > > If it isn't what you had in mind, can you give me a testcase? > > > > >> + 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); > > >> + if (context) > > >> + rhs = op1; > > >> + else > > >> + { > > >> + /* Check the ELSE path. */ > > >> + rhs = TREE_OPERAND (rhs, 2); > > >> + context = check_address_of_packed_member (type, rhs); > > >> + } > > >> + } > > > > > > > > > Likewise, what if you have more levels of COND_EXPR? Or COMPOUND_EXPR > > > within COND_EXPR? > > > > Fixed, now I got > > > > [hjl@gnu-cfl-1 pr51628-5]$ cat z.i > > struct A { > > int i; > > } __attribute__ ((packed)); > > > > int* > > foo3 (struct A *p1, int *q1, int *q2, struct A *p2) > > { > > return (q1 > > ? &p1->i > > : (q2 ? &p2->i : q2)); > > } > > [hjl@gnu-cfl-1 pr51628-5]$ make z.s > > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > > -S z.i > > z.i: In function ‘foo3’: > > z.i:9:13: warning: taking address of packed member of ‘struct A’ may > > result in an unaligned pointer value [-Waddress-of-packed-member] > > 9 | ? &p1->i > > | ^~~~~~ > > z.i:10:19: warning: taking address of packed member of ‘struct A’ may > > result in an unaligned pointer value [-Waddress-of-packed-member] > > 10 | : (q2 ? &p2->i : q2)); > > | ^~~~~~ > > [hjl@gnu-cfl-1 pr51628-5]$ > > > > >> @@ -7470,6 +7470,9 @@ convert_for_arg_passing (tree type, tree val, > > >> tsubst_flags_t complain) > > >> + warn_for_address_or_pointer_of_packed_member (true, type, val); > > > > > > > > >> @@ -8914,6 +8914,8 @@ convert_for_assignment (tree type, tree rhs, > > >> + warn_for_address_or_pointer_of_packed_member (true, type, rhs); > > > > > > > > > Why would address_p be true in these calls? It seems that you are warning > > > at the point of assignment but looking for the warning about taking the > > > address rather than the one about assignment. > > > > It happens only with C for incompatible pointer conversion: > > > > [hjl@gnu-cfl-1 pr51628-2]$ cat c.i > > struct B { int i; }; > > struct C { struct B b; } __attribute__ ((packed)); > > > > long* g8 (struct C *p) { return p; } > > [hjl@gnu-cfl-1 pr51628-2]$ make c.s > > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > > -S c.i > > c.i: In function ‘g8’: > > c.i:4:33: warning: returning ‘struct C *’ from a function with > > incompatible return type ‘long int *’ [-Wincompatible-pointer-types] > > 4 | long* g8 (struct C *p) { return p; } > > | ^ > > 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)); > > | ^ > > [hjl@gnu-cfl-1 pr51628-2]$ > > > > address_p is false in this case and rhs is PARM_DECL, VAR_DECL or > > NOP_EXPR. This comes from convert_for_assignment in c/c-typeck.c. > > > > For other compatible pointer assignment, address_p is true and rhs is > > ADDR_EXPR, PARM_DECL, VAR_DECL or NOP_EXPR. Check > > for ADDR_EXPR won't work. > > > > address_p isn't an appropriate parameter name. I changed it to convert_p > > to indicate that it is an incompatible pointer type conversion. > > > > > If you want to warn about taking the address, shouldn't that happen under > > > cp_build_addr_expr? Alternately, drop the address_p parameter and choose > > > your path inside warn_for_*_packed_member based on whether rhs is an > > > ADDR_EXPR there rather than in the caller. > > > > > > > Here is the updated patch. OK for trunk? > > > > Thanks. > > PING: > > https://gcc.gnu.org/ml/gcc-patches/2018-09/msg01452.html > > PING. -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V4 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-09-25 15:47 V4 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu 2018-11-04 15:16 ` PING: " H.J. Lu @ 2018-12-13 20:50 ` Jason Merrill 2018-12-14 0:09 ` V5 " H.J. Lu 1 sibling, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-13 20:50 UTC (permalink / raw) To: H.J. Lu; +Cc: Joseph Myers, Martin Sebor, GCC Patches On 9/25/18 11:46 AM, H.J. Lu wrote: > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: >> On 07/23/2018 05:24 PM, H.J. Lu wrote: >>> >>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> >>> wrote: >>>> >>>> On Mon, 18 Jun 2018, Jason Merrill wrote: >>>> >>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> >>>>> 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. >>> + /* Check alignment of the object. */ >>> + if (TREE_CODE (object) == COMPONENT_REF) >>> + { >>> + field = TREE_OPERAND (object, 1); >>> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) >>> + { >>> + type_align = TYPE_ALIGN (type); >>> + context = DECL_CONTEXT (field); >>> + record_align = TYPE_ALIGN (context); >>> + if ((record_align % type_align) != 0) >>> + return context; >>> + } >>> + } >> >> >> Why doesn't this recurse? What if you have a packed field three >> COMPONENT_REFs down? > > My patch works on > [hjl@gnu-cfl-1 pr51628-4]$ cat x.i > 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; } > [hjl@gnu-cfl-1 pr51628-4]$ make x.s > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S x.i > x.i: In function âg8â: > x.i:7:25: warning: taking address of packed member of âstruct Aâ may > result in an unaligned pointer value [-Waddress-of-packed-member] > 7 | int* g8 (void) { return &p->b.a.i; } > | ^~~~~~~~~ > [hjl@gnu-cfl-1 pr51628-4]$ > > If it isn't what you had in mind, can you give me a testcase? In that testcase, 'i' is the top COMPONENT_EXPR. What I was talking about would be more like 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; } Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* V5 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-13 20:50 ` Jason Merrill @ 2018-12-14 0:09 ` H.J. Lu 2018-12-14 22:10 ` Jason Merrill 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-14 0:09 UTC (permalink / raw) To: Jason Merrill; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 5585 bytes --] On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > > On 9/25/18 11:46 AM, H.J. Lu wrote: > > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > >> On 07/23/2018 05:24 PM, H.J. Lu wrote: > >>> > >>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > >>> wrote: > >>>> > >>>> On Mon, 18 Jun 2018, Jason Merrill wrote: > >>>> > >>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > >>>>> 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; > >>> + /* Check alignment of the object. */ > >>> + if (TREE_CODE (object) == COMPONENT_REF) > >>> + { > >>> + field = TREE_OPERAND (object, 1); > >>> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)) > >>> + { > >>> + type_align = TYPE_ALIGN (type); > >>> + context = DECL_CONTEXT (field); > >>> + record_align = TYPE_ALIGN (context); > >>> + if ((record_align % type_align) != 0) > >>> + return context; > >>> + } > >>> + } > >> > >> > >> Why doesn't this recurse? What if you have a packed field three > >> COMPONENT_REFs down? > > > > My patch works on > > [hjl@gnu-cfl-1 pr51628-4]$ cat x.i > > 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; } > > [hjl@gnu-cfl-1 pr51628-4]$ make x.s > > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > > -S x.i > > x.i: In function ‘g8’: > > x.i:7:25: warning: taking address of packed member of ‘struct A’ may > > result in an unaligned pointer value [-Waddress-of-packed-member] > > 7 | int* g8 (void) { return &p->b.a.i; } > > | ^~~~~~~~~ > > [hjl@gnu-cfl-1 pr51628-4]$ > > > > If it isn't what you had in mind, can you give me a testcase? > > In that testcase, 'i' is the top COMPONENT_EXPR. What I was talking > about would be more like > > 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; } > Fixed with a recursive call: 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; Here is the updated patch. Tested on i686 and x86-64. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: text/x-patch, Size: 49613 bytes --] From a2d11ab284fa9d04b38c05c9df6a615f951b304d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 12 Jan 2018 21:12:05 -0800 Subject: [PATCH] C/C++: Add -Waddress-of-packed-member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. * 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 | 192 ++++++++++++++++++ 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-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 + 52 files changed, 839 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-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..615134cfdac 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2616,3 +2616,195 @@ 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)) + { + enum tree_code code = TREE_CODE (base); + if (code == COMPONENT_REF) + break; + switch (code) + { + case ARRAY_REF: + base = TREE_OPERAND (base, 0); + break; + default: + return NULL_TREE; + } + } + 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 ac0c81155b5..93b295ade90 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9023,6 +9023,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 44e1069de3b..258760a544a 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-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 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V5 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-14 0:09 ` V5 " H.J. Lu @ 2018-12-14 22:10 ` Jason Merrill 2018-12-14 22:48 ` V6 " H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-14 22:10 UTC (permalink / raw) To: H.J. Lu; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches On 12/13/18 6:56 PM, H.J. Lu wrote: > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: >> >> On 9/25/18 11:46 AM, H.J. Lu wrote: >>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: >>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: >>>>> >>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> >>>>> wrote: >>>>>> >>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: >>>>>> >>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> >>>>>>> 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? Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* V6 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-14 22:10 ` Jason Merrill @ 2018-12-14 22:48 ` H.J. Lu 2018-12-17 9:39 ` Richard Biener 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-14 22:48 UTC (permalink / raw) To: Jason Merrill; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 5318 bytes --] On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > >> > >> On 9/25/18 11:46 AM, H.J. Lu wrote: > >>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > >>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: > >>>>> > >>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > >>>>> wrote: > >>>>>> > >>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: > >>>>>> > >>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > >>>>>>> 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: Now I got [hjl@gnu-cfl-1 pr51628-6]$ cat foo.i 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); } int* foo2 (void) { return &__imag(p->b.a.i); } [hjl@gnu-cfl-1 pr51628-6]$ make foo.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S foo.i foo.i: In function ‘foo1’: foo.i:10:10: warning: taking address of packed member of ‘struct C’ may result in an unaligned pointer value [-Waddress-of-packed-member] 10 | return &__real(p->b.a.i); | ^~~~~~~~~~~~~~~~~ foo.i: In function ‘foo2’: foo.i:15:10: warning: taking address of packed member of ‘struct C’ may result in an unaligned pointer value [-Waddress-of-packed-member] 15 | return &__imag(p->b.a.i); | ^~~~~~~~~~~~~~~~~ [hjl@gnu-cfl-1 pr51628-6]$ OK for trunk? -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: application/x-patch, Size: 50574 bytes --] ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V6 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-14 22:48 ` V6 " H.J. Lu @ 2018-12-17 9:39 ` Richard Biener 2018-12-17 12:43 ` H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: Richard Biener @ 2018-12-17 9:39 UTC (permalink / raw) To: H. J. Lu; +Cc: Jason Merrill, Joseph S. Myers, Martin Sebor, GCC Patches On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: > > > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > > >> > > >> On 9/25/18 11:46 AM, H.J. Lu wrote: > > >>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > >>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: > > >>>>> > > >>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > > >>>>> wrote: > > >>>>>> > > >>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: > > >>>>>> > > >>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > > >>>>>>> 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) > > Now I got > > [hjl@gnu-cfl-1 pr51628-6]$ cat foo.i > 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); > } > int* > foo2 (void) > { > return &__imag(p->b.a.i); > } > [hjl@gnu-cfl-1 pr51628-6]$ make foo.s > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S foo.i > foo.i: In function ‘foo1’: > foo.i:10:10: warning: taking address of packed member of ‘struct C’ > may result in an unaligned pointer value [-Waddress-of-packed-member] > 10 | return &__real(p->b.a.i); > | ^~~~~~~~~~~~~~~~~ > foo.i: In function ‘foo2’: > foo.i:15:10: warning: taking address of packed member of ‘struct C’ > may result in an unaligned pointer value [-Waddress-of-packed-member] > 15 | return &__imag(p->b.a.i); > | ^~~~~~~~~~~~~~~~~ > [hjl@gnu-cfl-1 pr51628-6]$ > > OK for trunk? > > -- > H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V6 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-17 9:39 ` Richard Biener @ 2018-12-17 12:43 ` H.J. Lu 2018-12-17 13:34 ` Richard Biener 2018-12-17 13:53 ` Jason Merrill 0 siblings, 2 replies; 23+ messages in thread From: H.J. Lu @ 2018-12-17 12:43 UTC (permalink / raw) To: Richard Guenther Cc: Jason Merrill, Joseph S. Myers, Martin Sebor, GCC Patches On Mon, Dec 17, 2018 at 1:39 AM Richard Biener <richard.guenther@gmail.com> wrote: > > On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: > > > > > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > > > >> > > > >> On 9/25/18 11:46 AM, H.J. Lu wrote: > > > >>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > > >>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: > > > >>>>> > > > >>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > > > >>>>> wrote: > > > >>>>>> > > > >>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: > > > >>>>>> > > > >>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > > > >>>>>>> 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? -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V6 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-17 12:43 ` H.J. Lu @ 2018-12-17 13:34 ` Richard Biener 2018-12-17 13:53 ` Jason Merrill 1 sibling, 0 replies; 23+ messages in thread From: Richard Biener @ 2018-12-17 13:34 UTC (permalink / raw) To: H. J. Lu; +Cc: Jason Merrill, Joseph S. Myers, Martin Sebor, GCC Patches On Mon, Dec 17, 2018 at 1:43 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Mon, Dec 17, 2018 at 1:39 AM Richard Biener > <richard.guenther@gmail.com> wrote: > > > > On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > > > On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: > > > > > > > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > > > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > > > > >> > > > > >> On 9/25/18 11:46 AM, H.J. Lu wrote: > > > > >>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > > > >>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: > > > > >>>>> > > > > >>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > > > > >>>>> wrote: > > > > >>>>>> > > > > >>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: > > > > >>>>>> > > > > >>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > > > > >>>>>>> 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? No, I suspect it might need some folding to trigger (IIRC I made the FEs use ARRAY_REFs but I'm not sure whether fully, esp. in the case of address-taking). My attempt: typedef int v4si __attribute__((vector_size(16))); struct X { v4si x; } __attribute__((packed)) x; int *foo() { return &x.x[1]; } that shows return &VIEW_CONVERT_EXPR<int[4]>(x.x)[1]; for both C and C++ (albeit checked GCC 8 here). Richard. > -- > H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V6 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-17 12:43 ` H.J. Lu 2018-12-17 13:34 ` Richard Biener @ 2018-12-17 13:53 ` Jason Merrill 2018-12-18 14:11 ` V7 " H.J. Lu 1 sibling, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-17 13:53 UTC (permalink / raw) To: H.J. Lu, Richard Guenther; +Cc: Joseph S. Myers, Martin Sebor, GCC Patches On 12/17/18 7:42 AM, H.J. Lu wrote: > On Mon, Dec 17, 2018 at 1:39 AM Richard Biener > <richard.guenther@gmail.com> wrote: >> >> On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu <hjl.tools@gmail.com> wrote: >>> >>> On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: >>>> >>>> On 12/13/18 6:56 PM, H.J. Lu wrote: >>>>> On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: >>>>>> >>>>>> On 9/25/18 11:46 AM, H.J. Lu wrote: >>>>>>> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: >>>>>>>> On 07/23/2018 05:24 PM, H.J. Lu wrote: >>>>>>>>> >>>>>>>>> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> >>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> On Mon, 18 Jun 2018, Jason Merrill wrote: >>>>>>>>>> >>>>>>>>>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> >>>>>>>>>>> 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. Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* V7 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-17 13:53 ` Jason Merrill @ 2018-12-18 14:11 ` H.J. Lu 2018-12-18 20:36 ` Jason Merrill 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-18 14:11 UTC (permalink / raw) To: Jason Merrill Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches 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 > > <richard.guenther@gmail.com> wrote: > > > > > > On Fri, Dec 14, 2018 at 11:48 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > > > > > On Fri, Dec 14, 2018 at 2:10 PM Jason Merrill <jason@redhat.com> wrote: > > > > > > > > > > On 12/13/18 6:56 PM, H.J. Lu wrote: > > > > > > On Thu, Dec 13, 2018 at 12:50 PM Jason Merrill <jason@redhat.com> wrote: > > > > > > > > > > > > > > On 9/25/18 11:46 AM, H.J. Lu wrote: > > > > > > > > On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <jason@redhat.com> wrote: > > > > > > > > > On 07/23/2018 05:24 PM, H.J. Lu wrote: > > > > > > > > > > > > > > > > > > > > On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <joseph@codesourcery.com> > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > On Mon, 18 Jun 2018, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > > > > > On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <joseph@codesourcery.com> > > > > > > > > > > > > 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 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V7 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-18 14:11 ` V7 " H.J. Lu @ 2018-12-18 20:36 ` Jason Merrill 2018-12-18 21:13 ` V8 " H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-18 20:36 UTC (permalink / raw) To: H.J. Lu; +Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On 12/18/18 9:10 AM, H.J. Lu wrote: > + 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); > + } > + You can see interleaved COMPONENT_REF and ARRAY_REF that this still doesn't look like it will handle, something like struct A { int i; }; struct B { char c; __attribute ((packed)) A ar[4]; }; B b; int *p = &b.ar[1].i; Rather than have a loop in the ADDR_EXPR case of the switch, you can handle everything in the lower loop. And not have a switch at all, just strip any ADDR_EXPR before the loop. > +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)); > +} You probably also want to handle COMPOUND_EXPR. Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* V8 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-18 20:36 ` Jason Merrill @ 2018-12-18 21:13 ` H.J. Lu 2018-12-18 22:14 ` Jason Merrill 2018-12-19 3:19 ` V8 " Sandra Loosemore 0 siblings, 2 replies; 23+ messages in thread From: H.J. Lu @ 2018-12-18 21:13 UTC (permalink / raw) To: Jason Merrill Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 4687 bytes --] On Tue, Dec 18, 2018 at 12:36 PM Jason Merrill <jason@redhat.com> wrote: > > On 12/18/18 9:10 AM, H.J. Lu wrote: > > + 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); > > + } > > + > > You can see interleaved COMPONENT_REF and ARRAY_REF that this still > doesn't look like it will handle, something like > > struct A > { > int i; > }; > > struct B > { > char c; > __attribute ((packed)) A ar[4]; > }; > > B b; > > int *p = &b.ar[1].i; > > Rather than have a loop in the ADDR_EXPR case of the switch, you can > handle everything in the lower loop. And not have a switch at all, just > strip any ADDR_EXPR before the loop. I changed it to if (TREE_CODE (rhs) == ADDR_EXPR) rhs = TREE_OPERAND (rhs, 0); while (handled_component_p (rhs)) { if (TREE_CODE (rhs) == COMPONENT_REF) break; rhs = TREE_OPERAND (rhs, 0); } if (TREE_CODE (rhs) != COMPONENT_REF) return NULL_TREE; object = TREE_OPERAND (rhs, 0); field = TREE_OPERAND (rhs, 1); [hjl@gnu-cfl-1 pr51628-6]$ cat a.i struct A { int i; } __attribute ((packed)); struct B { char c; struct A ar[4]; }; struct B b; int *p = &b.ar[1].i; [hjl@gnu-cfl-1 pr51628-6]$ make a.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S a.i a.i:14:10: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 14 | int *p = &b.ar[1].i; | ^~~~~~~~~~ [hjl@gnu-cfl-1 pr51628-6]$ > > +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)); > > +} > > You probably also want to handle COMPOUND_EXPR. > Done. [hjl@gnu-cfl-1 pr51628-5]$ cat c.i struct A { int i; } __attribute__ ((packed)); int* foo3 (struct A *p1, int *q1, int *q2, struct A *p2) { return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q2 = 2, &p2->i): q2); } [hjl@gnu-cfl-1 pr51628-5]$ /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S c.i c.i: In function ‘foo3’: c.i:8:25: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q2 = 2, &p2->i): q2); | ^~~~~~ c.i:8:51: warning: taking address of packed member of ‘struct A’ may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q2 = 2, &p2->i): q2); | ^~~~~~ [hjl@gnu-cfl-1 pr51628-5]$ Here is the updated patch. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: text/x-patch, Size: 51900 bytes --] From 22e60a16ca5fd9c591e6b44c0245cc51f12d5b6c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 12 Jan 2018 21:12:05 -0800 Subject: [PATCH] C/C++: Add -Waddress-of-packed-member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. * c-c++-common/pr51628-32.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 | 178 ++++++++++++++++++ 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 | 26 +++ 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-32.c | 19 ++ 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 + 55 files changed, 892 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-32.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..9b2895eddb5 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2616,3 +2616,181 @@ 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 object; + tree field; + + if (INDIRECT_REF_P (rhs)) + rhs = TREE_OPERAND (rhs, 0); + + if (TREE_CODE (rhs) == ADDR_EXPR) + rhs = TREE_OPERAND (rhs, 0); + while (handled_component_p (rhs)) + { + if (TREE_CODE (rhs) == COMPONENT_REF) + break; + rhs = TREE_OPERAND (rhs, 0); + } + + if (TREE_CODE (rhs) != COMPONENT_REF) + return NULL_TREE; + + object = TREE_OPERAND (rhs, 0); + field = TREE_OPERAND (rhs, 1); + + 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) + { + while (TREE_CODE (rhs) == COMPOUND_EXPR) + rhs = TREE_OPERAND (rhs, 1); + + 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..38dd116c5bb --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-28.c @@ -0,0 +1,26 @@ +/* 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 } */ +} + +int* +foo4 (struct A *p1, int *q1, int *q2, struct A *p2) +{ + return (q1 ? (*q1 = 1, &p1->i) +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : (q2 ? (*q2 = 2, &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-32.c b/gcc/testsuite/c-c++-common/pr51628-32.c new file mode 100644 index 00000000000..b5c42cd0e73 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-32.c @@ -0,0 +1,19 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A +{ + int i; +} __attribute ((packed)); + +struct B +{ + char c; + struct A ar[4]; +}; + +struct B b; + +int *p = &b.ar[1].i; +/* { 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 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V8 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-18 21:13 ` V8 " H.J. Lu @ 2018-12-18 22:14 ` Jason Merrill 2018-12-19 14:52 ` H.J. Lu 2018-12-19 3:19 ` V8 " Sandra Loosemore 1 sibling, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-18 22:14 UTC (permalink / raw) To: H.J. Lu; +Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On 12/18/18 4:12 PM, H.J. Lu wrote: > On Tue, Dec 18, 2018 at 12:36 PM Jason Merrill <jason@redhat.com> wrote: >> >> On 12/18/18 9:10 AM, H.J. Lu wrote: >>> + 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); >>> + } >>> + >> >> You can see interleaved COMPONENT_REF and ARRAY_REF that this still >> doesn't look like it will handle, something like >> >> struct A >> { >> int i; >> }; >> >> struct B >> { >> char c; >> __attribute ((packed)) A ar[4]; >> }; >> >> B b; >> >> int *p = &b.ar[1].i; >> >> Rather than have a loop in the ADDR_EXPR case of the switch, you can >> handle everything in the lower loop. And not have a switch at all, just >> strip any ADDR_EXPR before the loop. > > I changed it to > > if (TREE_CODE (rhs) == ADDR_EXPR) > rhs = TREE_OPERAND (rhs, 0); > while (handled_component_p (rhs)) > { > if (TREE_CODE (rhs) == COMPONENT_REF) > break; > rhs = TREE_OPERAND (rhs, 0); > } > > if (TREE_CODE (rhs) != COMPONENT_REF) > return NULL_TREE; > > object = TREE_OPERAND (rhs, 0); > field = TREE_OPERAND (rhs, 1); That still doesn't warn about my testcase above. > [hjl@gnu-cfl-1 pr51628-6]$ cat a.i > struct A > { > int i; > } __attribute ((packed)); > > struct B > { > char c; > struct A ar[4]; > }; > > struct B b; > > int *p = &b.ar[1].i; This testcase is importantly different because 'i' is packed, whereas in my testcase only the ar member of B is packed. My suggestion was that this loop: > + /* 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); > + } could loop over all handled_component_p, but only call check_alignment_of_packed_member for COMPONENT_REF. > + if (TREE_CODE (rhs) != COND_EXPR) > + { > + while (TREE_CODE (rhs) == COMPOUND_EXPR) > + rhs = TREE_OPERAND (rhs, 1); What if you have a COND_EXPR inside a COMPOUND_EXPR? Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V8 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-18 22:14 ` Jason Merrill @ 2018-12-19 14:52 ` H.J. Lu 2018-12-19 17:36 ` V9 " H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-19 14:52 UTC (permalink / raw) To: Jason Merrill Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On Tue, Dec 18, 2018 at 2:14 PM Jason Merrill <jason@redhat.com> wrote: > > On 12/18/18 4:12 PM, H.J. Lu wrote: > > On Tue, Dec 18, 2018 at 12:36 PM Jason Merrill <jason@redhat.com> wrote: > >> > >> On 12/18/18 9:10 AM, H.J. Lu wrote: > >>> + 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); > >>> + } > >>> + > >> > >> You can see interleaved COMPONENT_REF and ARRAY_REF that this still > >> doesn't look like it will handle, something like > >> > >> struct A > >> { > >> int i; > >> }; > >> > >> struct B > >> { > >> char c; > >> __attribute ((packed)) A ar[4]; > >> }; > >> > >> B b; > >> > >> int *p = &b.ar[1].i; > >> > >> Rather than have a loop in the ADDR_EXPR case of the switch, you can > >> handle everything in the lower loop. And not have a switch at all, just > >> strip any ADDR_EXPR before the loop. > > > > I changed it to > > > > if (TREE_CODE (rhs) == ADDR_EXPR) > > rhs = TREE_OPERAND (rhs, 0); > > while (handled_component_p (rhs)) > > { > > if (TREE_CODE (rhs) == COMPONENT_REF) > > break; > > rhs = TREE_OPERAND (rhs, 0); > > } > > > > if (TREE_CODE (rhs) != COMPONENT_REF) > > return NULL_TREE; > > > > object = TREE_OPERAND (rhs, 0); > > field = TREE_OPERAND (rhs, 1); > > That still doesn't warn about my testcase above. > > > [hjl@gnu-cfl-1 pr51628-6]$ cat a.i > > struct A > > { > > int i; > > } __attribute ((packed)); > > > > struct B > > { > > char c; > > struct A ar[4]; > > }; > > > > struct B b; > > > > int *p = &b.ar[1].i; > > This testcase is importantly different because 'i' is packed, whereas in > my testcase only the ar member of B is packed. > > My suggestion was that this loop: > > > + /* 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); > > + } > > could loop over all handled_component_p, but only call > check_alignment_of_packed_member for COMPONENT_REF. Thanks for the hint. I changed it to /* Check alignment of the object. */ while (handled_component_p (object)) { if (TREE_CODE (object) == COMPONENT_REF) { do { field = TREE_OPERAND (object, 1); context = check_alignment_of_packed_member (type, field); if (context) return context; object = TREE_OPERAND (object, 0); } while (TREE_CODE (object) == COMPONENT_REF); } else object = TREE_OPERAND (object, 0); } > > + if (TREE_CODE (rhs) != COND_EXPR) > > + { > > + while (TREE_CODE (rhs) == COMPOUND_EXPR) > > + rhs = TREE_OPERAND (rhs, 1); > > What if you have a COND_EXPR inside a COMPOUND_EXPR? > It works for me: [hjl@gnu-cfl-1 pr51628-5]$ cat c.i struct A { int i; } __attribute__ ((packed)); int* foo3 (struct A *p1, int **q1, int *q2, int *q3, struct A *p2) { return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); } [hjl@gnu-cfl-1 pr51628-5]$ /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S c.i c.i: In function \u2018foo3\u2019: c.i:8:20: warning: assignment to \u2018int *\u2019 from \u2018int\u2019 makes pointer from integer without a cast [-Wint-conversion] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); | ^ c.i:8:48: warning: taking address of packed member of \u2018struct A\u2019 may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); | ^~~~~~ c.i:8:25: warning: taking address of packed member of \u2018struct A\u2019 may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); | ^~~~~~ c.i:8:65: warning: taking address of packed member of \u2018struct A\u2019 may result in an unaligned pointer value [-Waddress-of-packed-member] 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); | ^~~~~~ [hjl@gnu-cfl-1 pr51628-5]$ If it isn't what you meant, can you give me a testcase? Thanks. -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* V9 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-19 14:52 ` H.J. Lu @ 2018-12-19 17:36 ` H.J. Lu 2018-12-20 19:40 ` Jason Merrill 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-19 17:36 UTC (permalink / raw) To: Jason Merrill, Sandra Loosemore Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 7031 bytes --] On Wed, Dec 19, 2018 at 6:51 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Tue, Dec 18, 2018 at 2:14 PM Jason Merrill <jason@redhat.com> wrote: > > > > On 12/18/18 4:12 PM, H.J. Lu wrote: > > > On Tue, Dec 18, 2018 at 12:36 PM Jason Merrill <jason@redhat.com> wrote: > > >> > > >> On 12/18/18 9:10 AM, H.J. Lu wrote: > > >>> + 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); > > >>> + } > > >>> + > > >> > > >> You can see interleaved COMPONENT_REF and ARRAY_REF that this still > > >> doesn't look like it will handle, something like > > >> > > >> struct A > > >> { > > >> int i; > > >> }; > > >> > > >> struct B > > >> { > > >> char c; > > >> __attribute ((packed)) A ar[4]; > > >> }; > > >> > > >> B b; > > >> > > >> int *p = &b.ar[1].i; > > >> > > >> Rather than have a loop in the ADDR_EXPR case of the switch, you can > > >> handle everything in the lower loop. And not have a switch at all, just > > >> strip any ADDR_EXPR before the loop. > > > > > > I changed it to > > > > > > if (TREE_CODE (rhs) == ADDR_EXPR) > > > rhs = TREE_OPERAND (rhs, 0); > > > while (handled_component_p (rhs)) > > > { > > > if (TREE_CODE (rhs) == COMPONENT_REF) > > > break; > > > rhs = TREE_OPERAND (rhs, 0); > > > } > > > > > > if (TREE_CODE (rhs) != COMPONENT_REF) > > > return NULL_TREE; > > > > > > object = TREE_OPERAND (rhs, 0); > > > field = TREE_OPERAND (rhs, 1); > > > > That still doesn't warn about my testcase above. > > > > > [hjl@gnu-cfl-1 pr51628-6]$ cat a.i > > > struct A > > > { > > > int i; > > > } __attribute ((packed)); > > > > > > struct B > > > { > > > char c; > > > struct A ar[4]; > > > }; > > > > > > struct B b; > > > > > > int *p = &b.ar[1].i; > > > > This testcase is importantly different because 'i' is packed, whereas in > > my testcase only the ar member of B is packed. > > > > My suggestion was that this loop: > > > > > + /* 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); > > > + } > > > > could loop over all handled_component_p, but only call > > check_alignment_of_packed_member for COMPONENT_REF. > > Thanks for the hint. I changed it to > > /* Check alignment of the object. */ > while (handled_component_p (object)) > { > if (TREE_CODE (object) == COMPONENT_REF) > { > do > { > field = TREE_OPERAND (object, 1); > context = check_alignment_of_packed_member (type, field); > if (context) > return context; > object = TREE_OPERAND (object, 0); > } > while (TREE_CODE (object) == COMPONENT_REF); > } > else > object = TREE_OPERAND (object, 0); > } I got [hjl@gnu-cfl-1 pr51628-6]$ cat a.i struct A { int i; }; struct B { char c; __attribute ((packed)) struct A ar[4]; }; struct B b; int *p = &b.ar[1].i; [hjl@gnu-cfl-1 pr51628-6]$ make a.s /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 -S a.i a.i:14:10: warning: taking address of packed member of ‘struct B’ may result in an unaligned pointer value [-Waddress-of-packed-member] 14 | int *p = &b.ar[1].i; | ^~~~~~~~~~ [hjl@gnu-cfl-1 pr51628-6]$ > > > + if (TREE_CODE (rhs) != COND_EXPR) > > > + { > > > + while (TREE_CODE (rhs) == COMPOUND_EXPR) > > > + rhs = TREE_OPERAND (rhs, 1); > > > > What if you have a COND_EXPR inside a COMPOUND_EXPR? > > > > It works for me: > > [hjl@gnu-cfl-1 pr51628-5]$ cat c.i > struct A { > int i; > } __attribute__ ((packed)); > > int* > foo3 (struct A *p1, int **q1, int *q2, int *q3, struct A *p2) > { > return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = 2, &p2->i): q2); > } > [hjl@gnu-cfl-1 pr51628-5]$ > /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc > -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2 > -S c.i > c.i: In function \u2018foo3\u2019: > c.i:8:20: warning: assignment to \u2018int *\u2019 from > \u2018int\u2019 makes pointer from integer without a cast > [-Wint-conversion] > 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = > 2, &p2->i): q2); > | ^ > c.i:8:48: warning: taking address of packed member of \u2018struct > A\u2019 may result in an unaligned pointer value > [-Waddress-of-packed-member] > 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = > 2, &p2->i): q2); > | ^~~~~~ > c.i:8:25: warning: taking address of packed member of \u2018struct > A\u2019 may result in an unaligned pointer value > [-Waddress-of-packed-member] > 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = > 2, &p2->i): q2); > | ^~~~~~ > c.i:8:65: warning: taking address of packed member of \u2018struct > A\u2019 may result in an unaligned pointer value > [-Waddress-of-packed-member] > 8 | return q1 ? (*q1 = 1, &p1->i) : (q2 ? (*q1 = &p1->i, *q2 = > 2, &p2->i): q2); > | ^~~~~~ > [hjl@gnu-cfl-1 pr51628-5]$ > > If it isn't what you meant, can you give me a testcase? > Here is the updated patch. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: text/x-patch, Size: 53309 bytes --] From 4a5418d5e93369cb5648ba6c0f33203bb6fa8a3f Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 12 Jan 2018 21:12:05 -0800 Subject: [PATCH] C/C++: Add -Waddress-of-packed-member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. * c-c++-common/pr51628-32.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 | 187 ++++++++++++++++++ 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 | 14 +- 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 | 31 +++ 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-32.c | 19 ++ 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 + 55 files changed, 909 insertions(+), 19 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-32.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..2c2aefbd63f 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2616,3 +2616,190 @@ 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 object; + tree field; + + if (INDIRECT_REF_P (rhs)) + rhs = TREE_OPERAND (rhs, 0); + + if (TREE_CODE (rhs) == ADDR_EXPR) + rhs = TREE_OPERAND (rhs, 0); + while (handled_component_p (rhs)) + { + if (TREE_CODE (rhs) == COMPONENT_REF) + break; + rhs = TREE_OPERAND (rhs, 0); + } + + if (TREE_CODE (rhs) != COMPONENT_REF) + return NULL_TREE; + + object = TREE_OPERAND (rhs, 0); + field = TREE_OPERAND (rhs, 1); + + tree context = check_alignment_of_packed_member (type, field); + if (context) + return context; + + /* Check alignment of the object. */ + while (handled_component_p (object)) + { + if (TREE_CODE (object) == COMPONENT_REF) + { + do + { + field = TREE_OPERAND (object, 1); + context = check_alignment_of_packed_member (type, field); + if (context) + return context; + object = TREE_OPERAND (object, 0); + } + while (TREE_CODE (object) == COMPONENT_REF); + } + else + 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) + { + while (TREE_CODE (rhs) == COMPOUND_EXPR) + rhs = TREE_OPERAND (rhs, 1); + + 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..14365fba501 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -281,7 +281,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol -pedantic-errors @gol --w -Wextra -Wall -Waddress -Waggregate-return -Waligned-new @gol +-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol +-Waggregate-return -Waligned-new @gol -Walloc-zero -Walloc-size-larger-than=@var{byte-size} @gol -Walloca -Walloca-larger-than=@var{byte-size} @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol @@ -310,7 +311,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-y2k -Wframe-address @gol -Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object @gol -Wjump-misses-init @gol --Wif-not-aligned @gol +-Whsa -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 @@ -358,7 +359,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 --Wzero-as-null-pointer-constant -Whsa} +-Wzero-as-null-pointer-constant} @item C and Objective-C-only Warning Options @gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol @@ -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..3cc1fec1f71 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-28.c @@ -0,0 +1,31 @@ +/* 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 } */ +} + +int* +foo4 (struct A *p1, int **q1, int *q2, int *q3, struct A *p2) +{ + return (q1 + ? (*q1 = q2, &p1->i) +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : (q2 + ? (*q1 = &p1->i, +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + *q2 = 2, &p2->i) +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : q2)); +} 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-32.c b/gcc/testsuite/c-c++-common/pr51628-32.c new file mode 100644 index 00000000000..a62e57d5b46 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-32.c @@ -0,0 +1,19 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A +{ + int i; +}; + +struct B +{ + char c; + __attribute ((packed)) struct A ar[4]; +}; + +struct B b; + +int *p = &b.ar[1].i; +/* { 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 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V9 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-19 17:36 ` V9 " H.J. Lu @ 2018-12-20 19:40 ` Jason Merrill 2018-12-20 20:07 ` V10 " H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-20 19:40 UTC (permalink / raw) To: H.J. Lu, Sandra Loosemore Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On 12/19/18 12:35 PM, H.J. Lu wrote: > + while (handled_component_p (rhs)) > + { > + if (TREE_CODE (rhs) == COMPONENT_REF) > + break; > + rhs = TREE_OPERAND (rhs, 0); > + } > + > + if (TREE_CODE (rhs) != COMPONENT_REF) > + return NULL_TREE; > + > + object = TREE_OPERAND (rhs, 0); > + field = TREE_OPERAND (rhs, 1); > + > + tree context = check_alignment_of_packed_member (type, field); > + if (context) > + return context; All the above looks unnecessary; it will be handled by the loop below. > + /* Check alignment of the object. */ > + while (handled_component_p (object)) > + { > + if (TREE_CODE (object) == COMPONENT_REF) > + { > + do > + { > + field = TREE_OPERAND (object, 1); > + context = check_alignment_of_packed_member (type, field); > + if (context) > + return context; > + object = TREE_OPERAND (object, 0); > + } > + while (TREE_CODE (object) == COMPONENT_REF); This inner loop also seems unnecessary. > + } > + else > + object = TREE_OPERAND (object, 0); > + } Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* V10 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-20 19:40 ` Jason Merrill @ 2018-12-20 20:07 ` H.J. Lu 2018-12-20 21:31 ` Jason Merrill 0 siblings, 1 reply; 23+ messages in thread From: H.J. Lu @ 2018-12-20 20:07 UTC (permalink / raw) To: Jason Merrill Cc: Sandra Loosemore, Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches [-- Attachment #1: Type: text/plain, Size: 1960 bytes --] On Thu, Dec 20, 2018 at 11:28 AM Jason Merrill <jason@redhat.com> wrote: > > On 12/19/18 12:35 PM, H.J. Lu wrote: > > + while (handled_component_p (rhs)) > > + { > > + if (TREE_CODE (rhs) == COMPONENT_REF) > > + break; > > + rhs = TREE_OPERAND (rhs, 0); > > + } > > + > > + if (TREE_CODE (rhs) != COMPONENT_REF) > > + return NULL_TREE; > > + > > + object = TREE_OPERAND (rhs, 0); > > + field = TREE_OPERAND (rhs, 1); > > + > > + tree context = check_alignment_of_packed_member (type, field); > > + if (context) > > + return context; > > All the above looks unnecessary; it will be handled by the loop below. > > > + /* Check alignment of the object. */ > > + while (handled_component_p (object)) > > + { > > + if (TREE_CODE (object) == COMPONENT_REF) > > + { > > + do > > + { > > + field = TREE_OPERAND (object, 1); > > + context = check_alignment_of_packed_member (type, field); > > + if (context) > > + return context; > > + object = TREE_OPERAND (object, 0); > > + } > > + while (TREE_CODE (object) == COMPONENT_REF); > > This inner loop also seems unnecessary. > > > + } > > + else > > + object = TREE_OPERAND (object, 0); > > + } > > Jason I changed it to static tree check_address_of_packed_member (tree type, tree rhs) { if (INDIRECT_REF_P (rhs)) rhs = TREE_OPERAND (rhs, 0); if (TREE_CODE (rhs) == ADDR_EXPR) rhs = TREE_OPERAND (rhs, 0); tree context = NULL_TREE; /* Check alignment of the object. */ while (handled_component_p (rhs)) { if (TREE_CODE (rhs) == COMPONENT_REF) { tree field = TREE_OPERAND (rhs, 1); context = check_alignment_of_packed_member (type, field); if (context) break; } rhs = TREE_OPERAND (rhs, 0); } return context; } Here is the updated patch. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --] [-- Type: text/x-patch, Size: 52778 bytes --] From f2982a694a2fab4dd1ce2a6819006b451fa0c9a7 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 12 Jan 2018 21:12:05 -0800 Subject: [PATCH] C/C++: Add -Waddress-of-packed-member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. * c-c++-common/pr51628-32.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 | 164 ++++++++++++++++++ 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 | 14 +- 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 | 31 ++++ 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-32.c | 19 ++ 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 + 55 files changed, 886 insertions(+), 19 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-32.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..ba508425233 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2616,3 +2616,167 @@ 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) +{ + if (INDIRECT_REF_P (rhs)) + rhs = TREE_OPERAND (rhs, 0); + + if (TREE_CODE (rhs) == ADDR_EXPR) + rhs = TREE_OPERAND (rhs, 0); + + tree context = NULL_TREE; + + /* Check alignment of the object. */ + while (handled_component_p (rhs)) + { + if (TREE_CODE (rhs) == COMPONENT_REF) + { + tree field = TREE_OPERAND (rhs, 1); + context = check_alignment_of_packed_member (type, field); + if (context) + break; + } + rhs = TREE_OPERAND (rhs, 0); + } + + return context; +} + +/* 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) + { + while (TREE_CODE (rhs) == COMPOUND_EXPR) + rhs = TREE_OPERAND (rhs, 1); + + 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..14365fba501 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -281,7 +281,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol -pedantic-errors @gol --w -Wextra -Wall -Waddress -Waggregate-return -Waligned-new @gol +-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol +-Waggregate-return -Waligned-new @gol -Walloc-zero -Walloc-size-larger-than=@var{byte-size} @gol -Walloca -Walloca-larger-than=@var{byte-size} @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol @@ -310,7 +311,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-y2k -Wframe-address @gol -Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object @gol -Wjump-misses-init @gol --Wif-not-aligned @gol +-Whsa -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 @@ -358,7 +359,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 --Wzero-as-null-pointer-constant -Whsa} +-Wzero-as-null-pointer-constant} @item C and Objective-C-only Warning Options @gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol @@ -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..3cc1fec1f71 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-28.c @@ -0,0 +1,31 @@ +/* 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 } */ +} + +int* +foo4 (struct A *p1, int **q1, int *q2, int *q3, struct A *p2) +{ + return (q1 + ? (*q1 = q2, &p1->i) +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : (q2 + ? (*q1 = &p1->i, +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + *q2 = 2, &p2->i) +/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ + : q2)); +} 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-32.c b/gcc/testsuite/c-c++-common/pr51628-32.c new file mode 100644 index 00000000000..a62e57d5b46 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr51628-32.c @@ -0,0 +1,19 @@ +/* PR c/51628. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct A +{ + int i; +}; + +struct B +{ + char c; + __attribute ((packed)) struct A ar[4]; +}; + +struct B b; + +int *p = &b.ar[1].i; +/* { 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 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V10 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-20 20:07 ` V10 " H.J. Lu @ 2018-12-20 21:31 ` Jason Merrill 2018-12-20 21:47 ` H.J. Lu 0 siblings, 1 reply; 23+ messages in thread From: Jason Merrill @ 2018-12-20 21:31 UTC (permalink / raw) To: H.J. Lu Cc: Sandra Loosemore, Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On 12/20/18 2:52 PM, H.J. Lu wrote: > On Thu, Dec 20, 2018 at 11:28 AM Jason Merrill <jason@redhat.com> wrote: >> >> On 12/19/18 12:35 PM, H.J. Lu wrote: >>> + while (handled_component_p (rhs)) >>> + { >>> + if (TREE_CODE (rhs) == COMPONENT_REF) >>> + break; >>> + rhs = TREE_OPERAND (rhs, 0); >>> + } >>> + >>> + if (TREE_CODE (rhs) != COMPONENT_REF) >>> + return NULL_TREE; >>> + >>> + object = TREE_OPERAND (rhs, 0); >>> + field = TREE_OPERAND (rhs, 1); >>> + >>> + tree context = check_alignment_of_packed_member (type, field); >>> + if (context) >>> + return context; >> >> All the above looks unnecessary; it will be handled by the loop below. >> >>> + /* Check alignment of the object. */ >>> + while (handled_component_p (object)) >>> + { >>> + if (TREE_CODE (object) == COMPONENT_REF) >>> + { >>> + do >>> + { >>> + field = TREE_OPERAND (object, 1); >>> + context = check_alignment_of_packed_member (type, field); >>> + if (context) >>> + return context; >>> + object = TREE_OPERAND (object, 0); >>> + } >>> + while (TREE_CODE (object) == COMPONENT_REF); >> >> This inner loop also seems unnecessary. >> >>> + } >>> + else >>> + object = TREE_OPERAND (object, 0); >>> + } >> >> Jason > > I changed it to > > static tree > check_address_of_packed_member (tree type, tree rhs) > { > if (INDIRECT_REF_P (rhs)) > rhs = TREE_OPERAND (rhs, 0); > > if (TREE_CODE (rhs) == ADDR_EXPR) > rhs = TREE_OPERAND (rhs, 0); > > tree context = NULL_TREE; > > /* Check alignment of the object. */ > while (handled_component_p (rhs)) > { > if (TREE_CODE (rhs) == COMPONENT_REF) > { > tree field = TREE_OPERAND (rhs, 1); > context = check_alignment_of_packed_member (type, field); > if (context) > break; > } > rhs = TREE_OPERAND (rhs, 0); > } > > return context; > } > > Here is the updated patch. OK for trunk? OK. Jason ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V10 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-20 21:31 ` Jason Merrill @ 2018-12-20 21:47 ` H.J. Lu 0 siblings, 0 replies; 23+ messages in thread From: H.J. Lu @ 2018-12-20 21:47 UTC (permalink / raw) To: Jason Merrill Cc: Sandra Loosemore, Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On Thu, Dec 20, 2018 at 1:28 PM Jason Merrill <jason@redhat.com> wrote: > > On 12/20/18 2:52 PM, H.J. Lu wrote: > > On Thu, Dec 20, 2018 at 11:28 AM Jason Merrill <jason@redhat.com> wrote: > >> > >> On 12/19/18 12:35 PM, H.J. Lu wrote: > >>> + while (handled_component_p (rhs)) > >>> + { > >>> + if (TREE_CODE (rhs) == COMPONENT_REF) > >>> + break; > >>> + rhs = TREE_OPERAND (rhs, 0); > >>> + } > >>> + > >>> + if (TREE_CODE (rhs) != COMPONENT_REF) > >>> + return NULL_TREE; > >>> + > >>> + object = TREE_OPERAND (rhs, 0); > >>> + field = TREE_OPERAND (rhs, 1); > >>> + > >>> + tree context = check_alignment_of_packed_member (type, field); > >>> + if (context) > >>> + return context; > >> > >> All the above looks unnecessary; it will be handled by the loop below. > >> > >>> + /* Check alignment of the object. */ > >>> + while (handled_component_p (object)) > >>> + { > >>> + if (TREE_CODE (object) == COMPONENT_REF) > >>> + { > >>> + do > >>> + { > >>> + field = TREE_OPERAND (object, 1); > >>> + context = check_alignment_of_packed_member (type, field); > >>> + if (context) > >>> + return context; > >>> + object = TREE_OPERAND (object, 0); > >>> + } > >>> + while (TREE_CODE (object) == COMPONENT_REF); > >> > >> This inner loop also seems unnecessary. > >> > >>> + } > >>> + else > >>> + object = TREE_OPERAND (object, 0); > >>> + } > >> > >> Jason > > > > I changed it to > > > > static tree > > check_address_of_packed_member (tree type, tree rhs) > > { > > if (INDIRECT_REF_P (rhs)) > > rhs = TREE_OPERAND (rhs, 0); > > > > if (TREE_CODE (rhs) == ADDR_EXPR) > > rhs = TREE_OPERAND (rhs, 0); > > > > tree context = NULL_TREE; > > > > /* Check alignment of the object. */ > > while (handled_component_p (rhs)) > > { > > if (TREE_CODE (rhs) == COMPONENT_REF) > > { > > tree field = TREE_OPERAND (rhs, 1); > > context = check_alignment_of_packed_member (type, field); > > if (context) > > break; > > } > > rhs = TREE_OPERAND (rhs, 0); > > } > > > > return context; > > } > > > > Here is the updated patch. OK for trunk? > > OK. > Checked in. Thanks for everyone, especially Jason. -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V8 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-18 21:13 ` V8 " H.J. Lu 2018-12-18 22:14 ` Jason Merrill @ 2018-12-19 3:19 ` Sandra Loosemore 2018-12-19 14:53 ` H.J. Lu 1 sibling, 1 reply; 23+ messages in thread From: Sandra Loosemore @ 2018-12-19 3:19 UTC (permalink / raw) To: H.J. Lu, Jason Merrill Cc: Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On 12/18/18 2:12 PM, H.J. Lu wrote: > > 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 Minor documentation nit: it looks like some effort has been made to alphabetize that list. Can you please put -Waddress-of-packed member in the right place, and also fix the misplaced -Whsa at the end? -Sandra ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: V8 [PATCH] C/C++: Add -Waddress-of-packed-member 2018-12-19 3:19 ` V8 " Sandra Loosemore @ 2018-12-19 14:53 ` H.J. Lu 0 siblings, 0 replies; 23+ messages in thread From: H.J. Lu @ 2018-12-19 14:53 UTC (permalink / raw) To: Sandra Loosemore Cc: Jason Merrill, Richard Guenther, Joseph S. Myers, Martin Sebor, GCC Patches On Tue, Dec 18, 2018 at 7:19 PM Sandra Loosemore <sandra@codesourcery.com> wrote: > > On 12/18/18 2:12 PM, H.J. Lu wrote: > > > > 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 > > Minor documentation nit: it looks like some effort has been made to > alphabetize that list. Can you please put -Waddress-of-packed member in > the right place, and also fix the misplaced -Whsa at the end? > I am applying diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 47f2fc3f518..14365fba501 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -281,7 +281,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol -pedantic-errors @gol --w -Wextra -Wall -Waddress -Waggregate-return -Waligned-new @gol +-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol +-Waggregate-return -Waligned-new @gol -Walloc-zero -Walloc-size-larger-than=@var{byte-size} @gol -Walloca -Walloca-larger-than=@var{byte-size} @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol @@ -310,7 +311,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-y2k -Wframe-address @gol -Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object @gol -Wjump-misses-init @gol --Wif-not-aligned @gol +-Whsa -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 @@ -358,8 +359,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} +-Wzero-as-null-pointer-constant} @item C and Objective-C-only Warning Options @gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol Thanks. -- H.J. ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2018-12-20 21:43 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-09-25 15:47 V4 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu 2018-11-04 15:16 ` PING: " H.J. Lu 2018-11-25 14:38 ` PING^2: " H.J. Lu 2018-12-13 20:50 ` Jason Merrill 2018-12-14 0:09 ` V5 " H.J. Lu 2018-12-14 22:10 ` Jason Merrill 2018-12-14 22:48 ` V6 " H.J. Lu 2018-12-17 9:39 ` Richard Biener 2018-12-17 12:43 ` H.J. Lu 2018-12-17 13:34 ` Richard Biener 2018-12-17 13:53 ` Jason Merrill 2018-12-18 14:11 ` V7 " H.J. Lu 2018-12-18 20:36 ` Jason Merrill 2018-12-18 21:13 ` V8 " H.J. Lu 2018-12-18 22:14 ` Jason Merrill 2018-12-19 14:52 ` H.J. Lu 2018-12-19 17:36 ` V9 " H.J. Lu 2018-12-20 19:40 ` Jason Merrill 2018-12-20 20:07 ` V10 " H.J. Lu 2018-12-20 21:31 ` Jason Merrill 2018-12-20 21:47 ` H.J. Lu 2018-12-19 3:19 ` V8 " Sandra Loosemore 2018-12-19 14:53 ` H.J. Lu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).