* 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 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-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
* 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
* 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
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).