* [PATCH] C/C++: Add -Waddress-of-packed-member
@ 2018-01-14 15:02 H.J. Lu
2018-01-15 9:47 ` Jakub Jelinek
2018-01-19 17:18 ` Martin Sebor
0 siblings, 2 replies; 10+ messages in thread
From: H.J. Lu @ 2018-01-14 15:02 UTC (permalink / raw)
To: gcc-patches
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 warn it:
$ 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: initialization of 'int *' from address of packed member of 'struct pair_t' may result in an unaligned pointer value [-Waddress-of-packed-member]
int *addr = &p.i;
^
$
This warning is enabled by default.
Tested on i686 and x86-64. OK for trunk?
H.J.
---
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_of_packed_member): New.
* c-warn.c (warn_for_address_of_packed_member): New function.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (convert_for_assignment): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
* typeck.c (convert_for_assignment): Likewise.
gcc/testsuite/
PR c/51628
* c-c++-common/pr51628-1.c: New tests.
* 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/ubsan/align-2.c: Add -Wno-address-of-packed-member.
* 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.
* g++.dg/ubsan/align-2.C: Likewise.
---
gcc/c-family/c-common.h | 1 +
gcc/c-family/c-warn.c | 38 +++++++++++++++++++++++++++
gcc/c-family/c.opt | 4 +++
gcc/c/c-typeck.c | 40 ++++++++++++++++++++++++++++-
gcc/cp/call.c | 8 ++++++
gcc/cp/typeck.c | 41 ++++++++++++++++++++++++++++++
gcc/doc/invoke.texi | 11 ++++++--
gcc/testsuite/c-c++-common/pr51628-1.c | 29 +++++++++++++++++++++
gcc/testsuite/c-c++-common/pr51628-2.c | 29 +++++++++++++++++++++
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/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 +-
19 files changed, 344 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/pr51628-1.c
create mode 100644 gcc/testsuite/c-c++-common/pr51628-2.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
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d090881e95d..ef31e4d0aa2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1384,6 +1384,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 void warn_for_restrict (unsigned, tree *, unsigned);
+extern tree warn_for_address_of_packed_member (tree type, tree rhs);
/* 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 7d87c455ec0..ac0a2ffcb42 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2576,3 +2576,41 @@ 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 type, RHS, is the
+ address of packed member of struct or union when assigning to TYPE.
+ Otherwise, return NULL_TREE. */
+
+tree
+warn_for_address_of_packed_member (tree type, tree rhs)
+{
+ if (!warn_address_of_packed_member)
+ return NULL_TREE;
+
+ if (TREE_CODE (rhs) == ADDR_EXPR && POINTER_TYPE_P (type))
+ {
+ tree base = TREE_OPERAND (rhs, 0);
+ if (TREE_CODE (base) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (base, 1);
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+ {
+ tree field_type = TREE_TYPE (field);
+ unsigned int type_align = TYPE_ALIGN (field_type);
+ tree context = DECL_CONTEXT (field);
+ unsigned int record_align = TYPE_ALIGN (context);
+ if ((record_align % type_align) != 0)
+ return context;
+ type_align /= BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT field_off
+ = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
+ + (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
+ / BITS_PER_UNIT));
+ if ((field_off % type_align) != 0)
+ return context;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 16a515afd55..686d52a2055 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 e22bc740bca..8e31d6cc5fd 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6495,7 +6495,45 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- return rhs;
+ {
+ tree context = warn_for_address_of_packed_member (type, orig_rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ic_argpass:
+ warning_at (expr_loc, OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qE from address "
+ "of packed member of %qT may result in an "
+ "unaligned pointer value",
+ parmnum, type, rname, context);
+ break;
+ case ic_assign:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_init:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_return:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT "
+ "from a function with return type %qT may "
+ "result in an unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f5542850cea..8672ab0d58c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7416,6 +7416,14 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ tree context = warn_for_address_of_packed_member (type, val);
+ if (context)
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument of type %qT from address of member of "
+ "packed %qT may result in an unaligned pointer value",
+ type, context);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index f0dc03de111..1199c27d2f0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8887,6 +8887,47 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ tree context = warn_for_address_of_packed_member (type, rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ICR_ARGPASS:
+ case ICR_DEFAULT_ARGUMENT:
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qD from address of "
+ "packed member of %qT may result in an unaligned "
+ "pointer value",
+ parmnum, type, fndecl, context);
+ break;
+ case ICR_CONVERTING:
+ warning (OPT_Waddress_of_packed_member,
+ "converting to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_ASSIGN:
+ warning (OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_INIT:
+ warning (OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed member "
+ "of %qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_RETURN:
+ warning (OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT from a "
+ "function with return type %qT may result in an "
+ "unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
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 28c61a078d2..13fd0abca3a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -259,8 +259,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6374,6 +6374,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/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-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-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/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;
--
2.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-14 15:02 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu
@ 2018-01-15 9:47 ` Jakub Jelinek
2018-01-15 15:02 ` H.J. Lu
2018-01-19 17:18 ` Martin Sebor
1 sibling, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2018-01-15 9:47 UTC (permalink / raw)
To: H.J. Lu; +Cc: gcc-patches
On Sun, Jan 14, 2018 at 06:29:54AM -0800, H.J. Lu wrote:
> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
> + {
> + tree field_type = TREE_TYPE (field);
> + unsigned int type_align = TYPE_ALIGN (field_type);
> + tree context = DECL_CONTEXT (field);
> + unsigned int record_align = TYPE_ALIGN (context);
> + if ((record_align % type_align) != 0)
> + return context;
> + type_align /= BITS_PER_UNIT;
> + unsigned HOST_WIDE_INT field_off
> + = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
> + + (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
> + / BITS_PER_UNIT));
This has the same bug I've just created PR83844 for, you can't assume
DECL_FIELD_OFFSET is INTEGER_CST that fits into UHWI, and also we have
byte_position wrapper that should be used to compute the offset from
DECL_FIELD_*OFFSET.
Jakub
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-15 9:47 ` Jakub Jelinek
@ 2018-01-15 15:02 ` H.J. Lu
2018-01-17 11:44 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2018-01-15 15:02 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 1128 bytes --]
On Mon, Jan 15, 2018 at 1:42 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Sun, Jan 14, 2018 at 06:29:54AM -0800, H.J. Lu wrote:
>> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
>> + {
>> + tree field_type = TREE_TYPE (field);
>> + unsigned int type_align = TYPE_ALIGN (field_type);
>> + tree context = DECL_CONTEXT (field);
>> + unsigned int record_align = TYPE_ALIGN (context);
>> + if ((record_align % type_align) != 0)
>> + return context;
>> + type_align /= BITS_PER_UNIT;
>> + unsigned HOST_WIDE_INT field_off
>> + = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
>> + + (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
>> + / BITS_PER_UNIT));
>
> This has the same bug I've just created PR83844 for, you can't assume
> DECL_FIELD_OFFSET is INTEGER_CST that fits into UHWI, and also we have
> byte_position wrapper that should be used to compute the offset from
> DECL_FIELD_*OFFSET.
Here is the updated patch to use byte_position wrapper. OK for trunk?
--
H.J.
[-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --]
[-- Type: text/x-patch, Size: 27934 bytes --]
From 2a26ed809f7af5f52a24367bfa0b29898ac7fa87 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
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 warn it:
$ 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: initialization of 'int *' from address of packed member of 'struct pair_t' may result in an unaligned pointer value [-Waddress-of-packed-member]
int *addr = &p.i;
^
$
This warning is enabled by default.
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_of_packed_member): New.
* c-warn.c (warn_for_address_of_packed_member): New function.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (convert_for_assignment): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
* typeck.c (convert_for_assignment): Likewise.
gcc/testsuite/
PR c/51628
* c-c++-common/pr51628-1.c: New tests.
* 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.
* gcc.dg/pr51628-10.c: Likewise.
* gcc.dg/pr51628-11.c: Likewise.
* c-c++-common/ubsan/align-10.c: Add -Wno-address-of-packed-member.
* 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.
* g++.dg/ubsan/align-2.C: Likewise.
---
gcc/c-family/c-common.h | 1 +
gcc/c-family/c-warn.c | 56 +++++++++++++++++++++++++++++
gcc/c-family/c.opt | 4 +++
gcc/c/c-typeck.c | 40 ++++++++++++++++++++-
gcc/cp/call.c | 8 +++++
gcc/cp/typeck.c | 41 +++++++++++++++++++++
gcc/doc/invoke.texi | 11 ++++--
gcc/testsuite/c-c++-common/pr51628-1.c | 29 +++++++++++++++
gcc/testsuite/c-c++-common/pr51628-2.c | 29 +++++++++++++++
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-10.c | 23 ++++++++++++
gcc/testsuite/gcc.dg/pr51628-11.c | 26 ++++++++++++++
25 files changed, 513 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/pr51628-1.c
create mode 100644 gcc/testsuite/c-c++-common/pr51628-2.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-10.c
create mode 100644 gcc/testsuite/gcc.dg/pr51628-11.c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d090881e95d..ef31e4d0aa2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1384,6 +1384,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 void warn_for_restrict (unsigned, tree *, unsigned);
+extern tree warn_for_address_of_packed_member (tree type, tree rhs);
/* 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 7d87c455ec0..09f219014d9 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2576,3 +2576,59 @@ 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 type, RHS, is the
+ address of packed member of struct or union when assigning to TYPE.
+ Otherwise, return NULL_TREE. */
+
+tree
+warn_for_address_of_packed_member (tree type, tree rhs)
+{
+ if (!warn_address_of_packed_member || !POINTER_TYPE_P (type))
+ return NULL_TREE;
+
+ if (TREE_CODE (rhs) == NOP_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ tree base;
+ tree field = NULL_TREE;
+ tree rhs_type;
+
+ switch (TREE_CODE (rhs))
+ {
+ case ADDR_EXPR:
+ base = TREE_OPERAND (rhs, 0);
+ while (TREE_CODE (base) == ARRAY_REF)
+ base = TREE_OPERAND (base, 0);
+ if (TREE_CODE (base) != COMPONENT_REF)
+ return NULL_TREE;
+ field = TREE_OPERAND (base, 1);
+ break;
+ case COMPONENT_REF:
+ rhs_type = TREE_TYPE (rhs);
+ if (TREE_CODE (rhs_type) != ARRAY_TYPE
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (type))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (rhs_type))))
+ return NULL_TREE;
+ field = TREE_OPERAND (rhs, 1);
+ break;
+ default:
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+ {
+ tree field_type = TREE_TYPE (field);
+ unsigned int type_align = TYPE_ALIGN (field_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;
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 16a515afd55..686d52a2055 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 e22bc740bca..8e31d6cc5fd 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6495,7 +6495,45 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- return rhs;
+ {
+ tree context = warn_for_address_of_packed_member (type, orig_rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ic_argpass:
+ warning_at (expr_loc, OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qE from address "
+ "of packed member of %qT may result in an "
+ "unaligned pointer value",
+ parmnum, type, rname, context);
+ break;
+ case ic_assign:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_init:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_return:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT "
+ "from a function with return type %qT may "
+ "result in an unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f5542850cea..8672ab0d58c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7416,6 +7416,14 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ tree context = warn_for_address_of_packed_member (type, val);
+ if (context)
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument of type %qT from address of member of "
+ "packed %qT may result in an unaligned pointer value",
+ type, context);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index f0dc03de111..1199c27d2f0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8887,6 +8887,47 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ tree context = warn_for_address_of_packed_member (type, rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ICR_ARGPASS:
+ case ICR_DEFAULT_ARGUMENT:
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qD from address of "
+ "packed member of %qT may result in an unaligned "
+ "pointer value",
+ parmnum, type, fndecl, context);
+ break;
+ case ICR_CONVERTING:
+ warning (OPT_Waddress_of_packed_member,
+ "converting to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_ASSIGN:
+ warning (OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_INIT:
+ warning (OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed member "
+ "of %qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_RETURN:
+ warning (OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT from a "
+ "function with return type %qT may result in an "
+ "unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
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 98b73db17af..b83d113b76d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -259,8 +259,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6379,6 +6379,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/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-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-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-10.c b/gcc/testsuite/gcc.dg/pr51628-10.c
new file mode 100644
index 00000000000..03a04eff75c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-10.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-11.c b/gcc/testsuite/gcc.dg/pr51628-11.c
new file mode 100644
index 00000000000..7ff03e85cea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-11.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 } */
+}
--
2.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-15 15:02 ` H.J. Lu
@ 2018-01-17 11:44 ` H.J. Lu
0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2018-01-17 11:44 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 1683 bytes --]
On Mon, Jan 15, 2018 at 7:02 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, Jan 15, 2018 at 1:42 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Sun, Jan 14, 2018 at 06:29:54AM -0800, H.J. Lu wrote:
>>> + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
>>> + {
>>> + tree field_type = TREE_TYPE (field);
>>> + unsigned int type_align = TYPE_ALIGN (field_type);
>>> + tree context = DECL_CONTEXT (field);
>>> + unsigned int record_align = TYPE_ALIGN (context);
>>> + if ((record_align % type_align) != 0)
>>> + return context;
>>> + type_align /= BITS_PER_UNIT;
>>> + unsigned HOST_WIDE_INT field_off
>>> + = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
>>> + + (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
>>> + / BITS_PER_UNIT));
>>
>> This has the same bug I've just created PR83844 for, you can't assume
>> DECL_FIELD_OFFSET is INTEGER_CST that fits into UHWI, and also we have
>> byte_position wrapper that should be used to compute the offset from
>> DECL_FIELD_*OFFSET.
>
> Here is the updated patch to use byte_position wrapper. OK for trunk?
>
Here is the updated patch not to warn:
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;
}
by properly checking the expected alignment against the field alignment.
--
H.J.
[-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --]
[-- Type: text/x-patch, Size: 32567 bytes --]
From 54b68f11c18971d1371d5bb5bde7b0c1d3e6ee7b 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
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 warn it:
$ 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: initialization of 'int *' from address of packed member of 'struct pair_t' may result in an unaligned pointer value [-Waddress-of-packed-member]
int *addr = &p.i;
^
$
This warning is enabled by default.
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_of_packed_member): New.
* c-warn.c (warn_for_address_of_packed_member): New function.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (convert_for_assignment): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_of_packed_member. Issue an warning if address
of packed member is taken.
* typeck.c (convert_for_assignment): Likewise.
gcc/testsuite/
PR c/51628
* c-c++-common/pr51628-1.c: New tests.
* c-c++-common/pr51628-10.c: Likewise.
* 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.
* gcc.dg/pr51628-10.c: Likewise.
* gcc.dg/pr51628-11.c: Likewise.
* c-c++-common/ubsan/align-10.c: Add -Wno-address-of-packed-member.
* 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.
* 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.
---
gcc/c-family/c-common.h | 1 +
gcc/c-family/c-warn.c | 56 ++++++++++++++++++++++
gcc/c-family/c.opt | 4 ++
gcc/c/c-typeck.c | 40 +++++++++++++++-
gcc/cp/call.c | 8 ++++
gcc/cp/typeck.c | 41 ++++++++++++++++
gcc/doc/invoke.texi | 11 ++++-
gcc/testsuite/c-c++-common/pr51628-1.c | 29 +++++++++++
gcc/testsuite/c-c++-common/pr51628-10.c | 24 ++++++++++
gcc/testsuite/c-c++-common/pr51628-2.c | 29 +++++++++++
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-10.c | 23 +++++++++
gcc/testsuite/gcc.dg/pr51628-11.c | 26 ++++++++++
.../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 +-
32 files changed, 543 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-2.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-10.c
create mode 100644 gcc/testsuite/gcc.dg/pr51628-11.c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d090881e95d..ef31e4d0aa2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1384,6 +1384,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 void warn_for_restrict (unsigned, tree *, unsigned);
+extern tree warn_for_address_of_packed_member (tree type, tree rhs);
/* 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 7d87c455ec0..c755df13ca1 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2576,3 +2576,59 @@ 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 type, RHS, is the
+ address of packed member of struct or union when assigning to TYPE.
+ Otherwise, return NULL_TREE. */
+
+tree
+warn_for_address_of_packed_member (tree type, tree rhs)
+{
+ if (!warn_address_of_packed_member || !POINTER_TYPE_P (type))
+ return NULL_TREE;
+
+ if (TREE_CODE (rhs) == NOP_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ tree base;
+ tree field = NULL_TREE;
+ tree rhs_type;
+
+ switch (TREE_CODE (rhs))
+ {
+ case ADDR_EXPR:
+ base = TREE_OPERAND (rhs, 0);
+ while (TREE_CODE (base) == ARRAY_REF)
+ base = TREE_OPERAND (base, 0);
+ if (TREE_CODE (base) != COMPONENT_REF)
+ return NULL_TREE;
+ field = TREE_OPERAND (base, 1);
+ break;
+ case COMPONENT_REF:
+ rhs_type = TREE_TYPE (rhs);
+ if (TREE_CODE (rhs_type) != ARRAY_TYPE
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (type))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (rhs_type))))
+ return NULL_TREE;
+ field = TREE_OPERAND (rhs, 1);
+ break;
+ default:
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+ {
+ /* Check the expected alignment against the field alignment. */
+ unsigned int type_align = TYPE_ALIGN (TREE_TYPE (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;
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 16a515afd55..686d52a2055 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 e22bc740bca..8e31d6cc5fd 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6495,7 +6495,45 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- return rhs;
+ {
+ tree context = warn_for_address_of_packed_member (type, orig_rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ic_argpass:
+ warning_at (expr_loc, OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qE from address "
+ "of packed member of %qT may result in an "
+ "unaligned pointer value",
+ parmnum, type, rname, context);
+ break;
+ case ic_assign:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_init:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed "
+ "member of %qT may result in an unaligned "
+ "pointer value",
+ type, context);
+ break;
+ case ic_return:
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT "
+ "from a function with return type %qT may "
+ "result in an unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f5542850cea..8672ab0d58c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7416,6 +7416,14 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ tree context = warn_for_address_of_packed_member (type, val);
+ if (context)
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument of type %qT from address of member of "
+ "packed %qT may result in an unaligned pointer value",
+ type, context);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d0adb798278..78ed0d61f8b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8887,6 +8887,47 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ tree context = warn_for_address_of_packed_member (type, rhs);
+ if (context)
+ switch (errtype)
+ {
+ case ICR_ARGPASS:
+ case ICR_DEFAULT_ARGUMENT:
+ warning (OPT_Waddress_of_packed_member,
+ "passing argument %d %qT of %qD from address of "
+ "packed member of %qT may result in an unaligned "
+ "pointer value",
+ parmnum, type, fndecl, context);
+ break;
+ case ICR_CONVERTING:
+ warning (OPT_Waddress_of_packed_member,
+ "converting to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_ASSIGN:
+ warning (OPT_Waddress_of_packed_member,
+ "assignment to %qT from address of packed member of "
+ "%qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_INIT:
+ warning (OPT_Waddress_of_packed_member,
+ "initialization of %qT from address of packed member "
+ "of %qT may result in an unaligned pointer value",
+ type, context);
+ break;
+ case ICR_RETURN:
+ warning (OPT_Waddress_of_packed_member,
+ "returning address of packed member of %qT from a "
+ "function with return type %qT may result in an "
+ "unaligned pointer value",
+ context, type);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
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 98b73db17af..b83d113b76d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -259,8 +259,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6379,6 +6379,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/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-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-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-10.c b/gcc/testsuite/gcc.dg/pr51628-10.c
new file mode 100644
index 00000000000..03a04eff75c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-10.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-11.c b/gcc/testsuite/gcc.dg/pr51628-11.c
new file mode 100644
index 00000000000..7ff03e85cea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-11.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.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
--
2.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-14 15:02 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu
2018-01-15 9:47 ` Jakub Jelinek
@ 2018-01-19 17:18 ` Martin Sebor
2018-01-20 6:17 ` Martin Sebor
1 sibling, 1 reply; 10+ messages in thread
From: Martin Sebor @ 2018-01-19 17:18 UTC (permalink / raw)
To: H.J. Lu, gcc-patches
On 01/14/2018 07:29 AM, H.J. Lu wrote:
> 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 warn it:
>
> $ 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: initialization of 'int *' from address of packed member of 'struct pair_t' may result in an unaligned pointer value [-Waddress-of-packed-member]
> int *addr = &p.i;
> ^
> $
>
> This warning is enabled by default.
I like this enhancement. It would be useful for data types,
packed or not, such as casting int* to long*.
I noticed some differences from Clang for the test case below.
It seems that GCC should warn on all the cases Clang does.
Also, since converting the address of a struct to that of its
first member is common (especially in C and when the member
itself is a struct) I wonder if the warning should trigger
for those conversions as well.
struct A {
int i;
} __attribute__ ((packed));
long* f8 (struct A *p) { return &p->i; } // Clang only
int* f4 (struct A *p) { return &p->i; } // Clang, GCC
short* f2 (struct A *p) { return &p->i; } // Clang only
char* f1 (struct A *p) { return &p->i; }
void* f0 (struct A *p) { return &p->i; }
struct B { int i; };
struct C { struct B b; } __attribute__ ((packed));
long* g8 (struct C *p) { return p; } // should warn?
int* g4 (struct C *p) { return &p->b; } // Clang only
int* h4 (struct C *p) { return &p->b.i; } // Clang only
Martin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-19 17:18 ` Martin Sebor
@ 2018-01-20 6:17 ` Martin Sebor
2018-01-20 17:32 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: Martin Sebor @ 2018-01-20 6:17 UTC (permalink / raw)
To: H.J. Lu, gcc-patches
On 01/19/2018 10:14 AM, Martin Sebor wrote:
> On 01/14/2018 07:29 AM, H.J. Lu wrote:
>> 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 warn it:
>>
>> $ 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: initialization of 'int *' from address of packed
>> member of 'struct pair_t' may result in an unaligned pointer value
>> [-Waddress-of-packed-member]
>> int *addr = &p.i;
>> ^
>> $
>>
>> This warning is enabled by default.
>
> I like this enhancement. It would be useful for data types,
> packed or not, such as casting int* to long*.
>
> I noticed some differences from Clang for the test case below.
> It seems that GCC should warn on all the cases Clang does.
>
> Also, since converting the address of a struct to that of its
> first member is common (especially in C and when the member
> itself is a struct) I wonder if the warning should trigger
> for those conversions as well.
>
> struct A {
> int i;
> } __attribute__ ((packed));
>
> long* f8 (struct A *p) { return &p->i; } // Clang only
> int* f4 (struct A *p) { return &p->i; } // Clang, GCC
> short* f2 (struct A *p) { return &p->i; } // Clang only
> char* f1 (struct A *p) { return &p->i; }
> void* f0 (struct A *p) { return &p->i; }
>
> struct B { int i; };
> struct C { struct B b; } __attribute__ ((packed));
>
> long* g8 (struct C *p) { return p; } // should warn?
> int* g4 (struct C *p) { return &p->b; } // Clang only
>
> int* h4 (struct C *p) { return &p->b.i; } // Clang only
>
After reading the Clang code review for the warning
(https://reviews.llvm.org/D20561) and experimenting with a few
more test cases I noticed some additional false negatives that
I think would be worthwhile diagnosing:
struct A {
int i;
} __attribute__ ((packed));
int f (struct A *p)
{
return *&p->i;
}
An example similar to one of those discussed in the review is
one involving a conditional expression (Clang diagnoses this):
int* f (struct A *p, int *q)
{
return q ? q : &p->i; // missing warning
}
Clang doesn't diagnose the conversion of a packed member array
to a pointer to its element. It seems to me that it should be
diagnosed:
struct B {
int a[1];
} __attribute__ ((packed));
int* f (struct B *p)
{
return p->a; // missing warning
}
Similarly, in C++, binding to more strictly aligned references
should probably be diagnosed (Clang misses it):
int* g (struct A &r)
{
int &ir = r.i; // missing warning here
return &ir; // regardless of how ir is used
}
Martin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-20 6:17 ` Martin Sebor
@ 2018-01-20 17:32 ` H.J. Lu
2018-01-20 20:28 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2018-01-20 17:32 UTC (permalink / raw)
To: Martin Sebor; +Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 8767 bytes --]
On Fri, Jan 19, 2018 at 7:57 PM, Martin Sebor <msebor@gmail.com> wrote:
> On 01/19/2018 10:14 AM, Martin Sebor wrote:
>>
>> On 01/14/2018 07:29 AM, H.J. Lu wrote:
>>>
>>> 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 warn it:
>>>
>>> $ 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: initialization of 'int *' from address of packed
>>> member of 'struct pair_t' may result in an unaligned pointer value
>>> [-Waddress-of-packed-member]
>>> int *addr = &p.i;
>>> ^
>>> $
>>>
>>> This warning is enabled by default.
>>
>>
>> I like this enhancement. It would be useful for data types,
>> packed or not, such as casting int* to long*.
>>
>> I noticed some differences from Clang for the test case below.
>> It seems that GCC should warn on all the cases Clang does.
>>
>> Also, since converting the address of a struct to that of its
>> first member is common (especially in C and when the member
>> itself is a struct) I wonder if the warning should trigger
>> for those conversions as well.
>>
>> struct A {
>> int i;
>> } __attribute__ ((packed));
>>
>> long* f8 (struct A *p) { return &p->i; } // Clang only
>> int* f4 (struct A *p) { return &p->i; } // Clang, GCC
>> short* f2 (struct A *p) { return &p->i; } // Clang only
>> char* f1 (struct A *p) { return &p->i; }
>> void* f0 (struct A *p) { return &p->i; }
>>
>> struct B { int i; };
>> struct C { struct B b; } __attribute__ ((packed));
>>
>> long* g8 (struct C *p) { return p; } // should warn?
>> int* g4 (struct C *p) { return &p->b; } // Clang only
>>
>> int* h4 (struct C *p) { return &p->b.i; } // Clang only
>>
With my current patch, I got
[hjl@gnu-tools-1 pr51628]$ cat m1.c
struct A {
int i;
} __attribute__ ((packed));
long* f8 (struct A *p) { return &p->i; } // Clang only
int* f4 (struct A *p) { return &p->i; } // Clang, GCC
short* f2 (struct A *p) { return &p->i; } // Clang only
char* f1 (struct A *p) { return &p->i; }
void* f0 (struct A *p) { return &p->i; }
struct B { int i; };
struct C { struct B b; } __attribute__ ((packed));
long* g8 (struct C *p) { return p; } // should warn?
int* g4 (struct C *p) { return &p->b; } // Clang only
int* h4 (struct C *p) { return &p->b.i; } // Clang only
[hjl@gnu-tools-1 pr51628]$ make m1.s
/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S m1.c
m1.c: In function ‘f8’:
m1.c:5:33: warning: returning ‘int *’ from a function with
incompatible return type ‘long int *’ [-Wincompatible-pointer-types]
long* f8 (struct A *p) { return &p->i; } // Clang only
^~~~~
m1.c:5:33: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
m1.c: In function ‘f4’:
m1.c:6:32: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
int* f4 (struct A *p) { return &p->i; } // Clang, GCC
^~~~~
m1.c: In function ‘f2’:
m1.c:7:34: warning: returning ‘int *’ from a function with
incompatible return type ‘short int *’ [-Wincompatible-pointer-types]
short* f2 (struct A *p) { return &p->i; } // Clang only
^~~~~
m1.c:7:34: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
m1.c: In function ‘f1’:
m1.c:8:33: warning: returning ‘int *’ from a function with
incompatible return type ‘char *’ [-Wincompatible-pointer-types]
char* f1 (struct A *p) { return &p->i; }
^~~~~
m1.c: In function ‘g8’:
m1.c:14:33: warning: returning ‘struct C *’ from a function with
incompatible return type ‘long int *’ [-Wincompatible-pointer-types]
long* g8 (struct C *p) { return p; } // should warn?
^
m1.c:14:33: warning: taking pointer of packed ‘struct C *’ may result
in an unaligned pointer value [-Waddress-of-packed-member]
m1.c: In function ‘g4’:
m1.c:15:32: warning: returning ‘struct B *’ from a function with
incompatible return type ‘int *’ [-Wincompatible-pointer-types]
int* g4 (struct C *p) { return &p->b; } // Clang only
^~~~~
m1.c:15:32: warning: taking address of packed member of ‘struct C’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
m1.c: In function ‘h4’:
m1.c:17:32: warning: taking address of packed member of ‘struct C’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
int* h4 (struct C *p) { return &p->b.i; } // Clang only
^~~~~~~
[hjl@gnu-tools-1 pr51628]$
> After reading the Clang code review for the warning
> (https://reviews.llvm.org/D20561) and experimenting with a few
> more test cases I noticed some additional false negatives that
> I think would be worthwhile diagnosing:
>
> struct A {
> int i;
> } __attribute__ ((packed));
>
> int f (struct A *p)
> {
> return *&p->i;
> }
I now got
[hjl@gnu-tools-1 pr51628]$ cat a1.i
struct A {
int i;
} __attribute__ ((packed));
int f (struct A *p)
{
return *&p->i;
}
[hjl@gnu-tools-1 pr51628]$ make a1.s
/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S a1.i
a1.i: In function ‘f’:
a1.i:7:10: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
return *&p->i;
^~~~~~
[hjl@gnu-tools-1 pr51628]$
> An example similar to one of those discussed in the review is
> one involving a conditional expression (Clang diagnoses this):
>
> int* f (struct A *p, int *q)
> {
> return q ? q : &p->i; // missing warning
> }
I now got
[hjl@gnu-tools-1 pr51628]$ cat a2.i
struct A {
int i;
} __attribute__ ((packed));
int* f (struct A *p, int *q)
{
return q ? q : &p->i;
}
[hjl@gnu-tools-1 pr51628]$ make a2.s
/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S a2.i
a2.i: In function ‘f’:
a2.i:7:18: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
return q ? q : &p->i;
^~~~~
[hjl@gnu-tools-1 pr51628]$
> Clang doesn't diagnose the conversion of a packed member array
> to a pointer to its element. It seems to me that it should be
> diagnosed:
>
> struct B {
> int a[1];
> } __attribute__ ((packed));
>
> int* f (struct B *p)
> {
> return p->a; // missing warning
> }
[hjl@gnu-tools-1 pr51628]$ cat a3.i
struct B {
int a[1];
} __attribute__ ((packed));
int* f (struct B *p)
{
return p->a; // missing warning
}
[hjl@gnu-tools-1 pr51628]$ make a3.s
/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S a3.i
a3.i: In function ‘f’:
a3.i:7:12: warning: taking address of packed member of ‘struct B’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
return p->a; // missing warning
^
[hjl@gnu-tools-1 pr51628]$
> Similarly, in C++, binding to more strictly aligned references
> should probably be diagnosed (Clang misses it):
>
> int* g (struct A &r)
> {
> int &ir = r.i; // missing warning here
> return &ir; // regardless of how ir is used
> }
This won't compile:
[hjl@gnu-tools-1 pr51628]$ cat r1.ii
struct A {
int i;
} __attribute__ ((packed));
int* g (struct A &r)
{
int &ir = r.i; // missing warning here
return &ir; // regardless of how ir is used
}
[hjl@gnu-tools-1 pr51628]$ make r1.s
/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -S r1.ii
r1.ii: In function ‘int* g(A&)’:
r1.ii:7:15: error: cannot bind packed field ‘r.A::i’ to ‘int&’
int &ir = r.i; // missing warning here
~~^
make: *** [Makefile:14: r1.s] Error 1
[hjl@gnu-tools-1 pr51628]$
Here is the updated patch. You can also get it from
https://github.com/hjl-tools/gcc/tree/hjl/pr51628/master
Thanks.
--
H.J.
[-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --]
[-- Type: text/x-patch, Size: 44906 bytes --]
From a9cbca91d6c53a111146e9787fc5c888fccc78e3 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 warn it:
$ 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]
int *addr = &p.i;
^
$
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_of_packed_member): New.
* c-warn.c (check_address_of_packed_member): New function.
(warn_for_address_of_packed_member): Likewise.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (warn_for_pointer_of_packed_member): New function.
(convert_for_assignment): Call warn_for_address_of_packed_member
and warn_for_pointer_of_packed_member.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_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-16.c: Likewise.
* c-c++-common/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.
* gcc.dg/pr51628-26.c: Likewise.
* c-c++-common/ubsan/align-10.c: Add -Wno-address-of-packed-member.
* 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.
* 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 | 115 +++++++++++++++++++++
gcc/c-family/c.opt | 4 +
gcc/c/c-typeck.c | 60 ++++++++++-
gcc/cp/call.c | 3 +
gcc/cp/typeck.c | 2 +
gcc/doc/invoke.texi | 11 +-
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 | 14 +++
gcc/testsuite/c-c++-common/pr51628-17.c | 14 +++
gcc/testsuite/c-c++-common/pr51628-2.c | 29 ++++++
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-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 | 10 ++
gcc/testsuite/gcc.dg/pr51628-26.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 +
47 files changed, 747 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-17.c
create mode 100644 gcc/testsuite/c-c++-common/pr51628-2.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-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
create mode 100644 gcc/testsuite/gcc.dg/pr51628-26.c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d090881e95d..073f6108f33 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1384,6 +1384,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 void warn_for_restrict (unsigned, tree *, unsigned);
+extern void warn_for_address_of_packed_member (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 7d87c455ec0..c17051070ed 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2576,3 +2576,118 @@ 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 (TREE_CODE (base) == ARRAY_REF)
+ 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;
+ unsigned int type_align, record_align;
+
+ /* Check alignment of the data member. */
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (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;
+}
+
+/* Warn 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. */
+
+void
+warn_for_address_of_packed_member (tree type, tree rhs)
+{
+ if (!warn_address_of_packed_member)
+ return;
+
+ if (POINTER_TYPE_P (type))
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (rhs) == NOP_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ location_t loc;
+ tree context = NULL_TREE;
+
+ if (TREE_CODE (rhs) == COND_EXPR)
+ {
+ tree op1 = TREE_OPERAND (rhs, 1);
+ context = check_address_of_packed_member (type, op1);
+ if (context)
+ loc = EXPR_LOC_OR_LOC (op1, input_location);
+ else
+ {
+ tree op2 = TREE_OPERAND (rhs, 2);
+ context = check_address_of_packed_member (type, op2);
+ if (context)
+ loc = EXPR_LOC_OR_LOC (op2, input_location);
+ }
+ }
+ else
+ {
+ context = check_address_of_packed_member (type, rhs);
+ if (context)
+ loc = EXPR_LOC_OR_LOC (rhs, input_location);
+ }
+
+ if (context)
+ warning_at (loc, OPT_Waddress_of_packed_member,
+ "taking address of packed member of %qT may result "
+ "in an unaligned pointer value",
+ context);
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9c7172607a7..354b04c4793 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 e22bc740bca..f93e4c22dae 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6285,6 +6285,54 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum,
expected_type, actual_type);
}
+/* Warn if the right hand poiner value RHS isn't aligned to a
+ pointer type TYPE. ERRTYPE says whether it is argument passing,
+ assignment, initialization or return. PARMNUM is the number of
+ the argument, for printing in error messages. NAME is the name
+ of the function. */
+
+static void
+warn_for_pointer_of_packed_member (location_t location, tree type,
+ tree rhs)
+{
+ if (!warn_address_of_packed_member || !POINTER_TYPE_P (type))
+ return;
+
+ bool pointer_p;
+ tree rhstype;
+
+ /* Check the original type of LHS. */
+ switch (TREE_CODE (rhs))
+ {
+ case PARM_DECL:
+ case VAR_DECL:
+ rhstype = TREE_TYPE (rhs);
+ pointer_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);
+ pointer_p = TREE_CODE (rhstype) == ARRAY_TYPE;
+ break;
+ default:
+ return;
+ }
+
+ if (pointer_p
+ && TYPE_PACKED (TREE_TYPE (rhstype)))
+ {
+ unsigned int type_align = TYPE_ALIGN (TREE_TYPE (type));
+ unsigned int rhs_align = TYPE_ALIGN (TREE_TYPE (rhstype));
+ if ((rhs_align % type_align) != 0)
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "taking pointer of packed %qT may result in an "
+ "unaligned pointer value",
+ rhstype);
+ }
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -6495,7 +6543,10 @@ 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_of_packed_member (type, orig_rhs);
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
@@ -6982,6 +7033,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
}
+ /* If LHS is't an address, check pointer or array of packed
+ struct or union. */
+ if (TREE_CODE (orig_rhs) != ADDR_EXPR)
+ warn_for_pointer_of_packed_member (location, type, orig_rhs);
+ else
+ warn_for_address_of_packed_member (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 46d5ef5e7c0..77f3f45557b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7430,6 +7430,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ warn_for_address_of_packed_member (type, val);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1102f677f15..f62ed731e89 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8888,6 +8888,8 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ warn_for_address_of_packed_member (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 27c597492be..d2df13903da 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -260,8 +260,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6390,6 +6390,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/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..9386035211e
--- /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)
+{
+ return *&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..bcac6d70ad5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr51628-16.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-17.c b/gcc/testsuite/c-c++-common/pr51628-17.c
new file mode 100644
index 00000000000..cca6ade91df
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr51628-17.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-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-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-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..bcdbff1e554
--- /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 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..0c7fab75d8a
--- /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 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..0be95b2294e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-25.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-26.c b/gcc/testsuite/gcc.dg/pr51628-26.c
new file mode 100644
index 00000000000..94a3a8fbaf2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-26.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 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.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-20 17:32 ` H.J. Lu
@ 2018-01-20 20:28 ` H.J. Lu
2018-01-21 4:27 ` H.J. Lu
0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2018-01-20 20:28 UTC (permalink / raw)
To: Martin Sebor; +Cc: GCC Patches
On Sat, Jan 20, 2018 at 8:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Jan 19, 2018 at 7:57 PM, Martin Sebor <msebor@gmail.com> wrote:
>> On 01/19/2018 10:14 AM, Martin Sebor wrote:
>>>
>
>> After reading the Clang code review for the warning
>> (https://reviews.llvm.org/D20561) and experimenting with a few
>> more test cases I noticed some additional false negatives that
>> I think would be worthwhile diagnosing:
>>
>> struct A {
>> int i;
>> } __attribute__ ((packed));
>>
>> int f (struct A *p)
>> {
>> return *&p->i;
>> }
>
> I now got
>
> [hjl@gnu-tools-1 pr51628]$ cat a1.i
> struct A {
> int i;
> } __attribute__ ((packed));
>
> int f (struct A *p)
> {
> return *&p->i;
> }
> [hjl@gnu-tools-1 pr51628]$ make a1.s
> /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
> -B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S a1.i
> a1.i: In function ‘f’:
> a1.i:7:10: warning: taking address of packed member of ‘struct A’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
> return *&p->i;
> ^~~~~~
> [hjl@gnu-tools-1 pr51628]$
It is wrong to warn "*&p->i;" since GCC always converts to "p->i;". Unless
we want to warn
[hjl@gnu-tools-1 pr51628]$ cat g5.i
struct A {
int i;
} __attribute__ ((packed));
int f (struct A *p)
{
return p->i;
}
we shouldn't warn:
[hjl@gnu-tools-1 pr51628]$ cat a1.i
struct A {
int i;
} __attribute__ ((packed));
int f (struct A *p)
{
return *&p->i;
}
[hjl@gnu-tools-1 pr51628]$
There is no unaligned load here. I am testing a new patch.
--
H.J.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] C/C++: Add -Waddress-of-packed-member
2018-01-20 20:28 ` H.J. Lu
@ 2018-01-21 4:27 ` H.J. Lu
0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2018-01-21 4:27 UTC (permalink / raw)
To: Martin Sebor; +Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 1869 bytes --]
On Sat, Jan 20, 2018 at 9:50 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Jan 20, 2018 at 8:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Fri, Jan 19, 2018 at 7:57 PM, Martin Sebor <msebor@gmail.com> wrote:
>>> On 01/19/2018 10:14 AM, Martin Sebor wrote:
>>>>
>>
>>> After reading the Clang code review for the warning
>>> (https://reviews.llvm.org/D20561) and experimenting with a few
>>> more test cases I noticed some additional false negatives that
>>> I think would be worthwhile diagnosing:
>>>
>>> struct A {
>>> int i;
>>> } __attribute__ ((packed));
>>>
>>> int f (struct A *p)
>>> {
>>> return *&p->i;
>>> }
>>
>> I now got
>>
>> [hjl@gnu-tools-1 pr51628]$ cat a1.i
>> struct A {
>> int i;
>> } __attribute__ ((packed));
>>
>> int f (struct A *p)
>> {
>> return *&p->i;
>> }
>> [hjl@gnu-tools-1 pr51628]$ make a1.s
>> /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
>> -B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -O2 -S a1.i
>> a1.i: In function ‘f’:
>> a1.i:7:10: warning: taking address of packed member of ‘struct A’ may
>> result in an unaligned pointer value [-Waddress-of-packed-member]
>> return *&p->i;
>> ^~~~~~
>> [hjl@gnu-tools-1 pr51628]$
>
>
> It is wrong to warn "*&p->i;" since GCC always converts to "p->i;". Unless
> we want to warn
>
> [hjl@gnu-tools-1 pr51628]$ cat g5.i
> struct A {
> int i;
> } __attribute__ ((packed));
>
> int f (struct A *p)
> {
> return p->i;
> }
>
> we shouldn't warn:
>
> [hjl@gnu-tools-1 pr51628]$ cat a1.i
> struct A {
> int i;
> } __attribute__ ((packed));
>
> int f (struct A *p)
> {
> return *&p->i;
> }
> [hjl@gnu-tools-1 pr51628]$
>
> There is no unaligned load here. I am testing a new patch.
>
Here is the updated patch. Tested on x86-64 and i686.
--
H.J.
[-- Attachment #2: 0001-C-C-Add-Waddress-of-packed-member.patch --]
[-- Type: text/x-patch, Size: 45454 bytes --]
From e4fb83119762ac8aaa0cd1095e273f5c70e9d4a3 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]
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:33: warning: taking value of packed 'struct C *' may result in an unaligned pointer value [-Waddress-of-packed-member]
long* g8 (struct C *p) { return p; }
^
$
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_of_packed_member): New.
* c-warn.c (check_address_of_packed_member): New function.
(warn_for_address_of_packed_member): Likewise.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (warn_for_pointer_of_packed_member): New function.
(convert_for_assignment): Call warn_for_address_of_packed_member
and warn_for_pointer_of_packed_member.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_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.
* gcc.dg/pr51628-16.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.
* 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 | 117 +++++++++++++++++++++
gcc/c-family/c.opt | 4 +
gcc/c/c-typeck.c | 60 ++++++++++-
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-2.c | 29 +++++
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-16.c | 9 ++
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.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 +
47 files changed, 723 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-2.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-16.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
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d090881e95d..073f6108f33 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1384,6 +1384,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 void warn_for_restrict (unsigned, tree *, unsigned);
+extern void warn_for_address_of_packed_member (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 7d87c455ec0..356fd3bf227 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2576,3 +2576,120 @@ 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 (TREE_CODE (base) == ARRAY_REF)
+ 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;
+ unsigned int type_align, record_align;
+
+ /* Check alignment of the data member. */
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (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;
+}
+
+/* Warn 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. */
+
+void
+warn_for_address_of_packed_member (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;
+
+ /* Get the type of the pointer pointing to. */
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (rhs) == NOP_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ tree context;
+
+ 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);
+ }
+ }
+ else
+ 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);
+ }
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9c7172607a7..354b04c4793 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 e22bc740bca..9d924dbcdc1 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6285,6 +6285,54 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum,
expected_type, actual_type);
}
+/* Warn if the right hand poiner value RHS isn't aligned to a
+ pointer type TYPE. ERRTYPE says whether it is argument passing,
+ assignment, initialization or return. PARMNUM is the number of
+ the argument, for printing in error messages. NAME is the name
+ of the function. */
+
+static void
+warn_for_pointer_of_packed_member (location_t location, tree type,
+ tree rhs)
+{
+ if (!warn_address_of_packed_member || !POINTER_TYPE_P (type))
+ return;
+
+ bool pointer_p;
+ tree rhstype;
+
+ /* Check the original type of LHS. */
+ switch (TREE_CODE (rhs))
+ {
+ case PARM_DECL:
+ case VAR_DECL:
+ rhstype = TREE_TYPE (rhs);
+ pointer_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);
+ pointer_p = TREE_CODE (rhstype) == ARRAY_TYPE;
+ break;
+ default:
+ return;
+ }
+
+ if (pointer_p
+ && TYPE_PACKED (TREE_TYPE (rhstype)))
+ {
+ unsigned int type_align = TYPE_ALIGN (TREE_TYPE (type));
+ unsigned int rhs_align = TYPE_ALIGN (TREE_TYPE (rhstype));
+ if ((rhs_align % type_align) != 0)
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "taking value of packed %qT may result in an "
+ "unaligned pointer value",
+ rhstype);
+ }
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -6495,7 +6543,10 @@ 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_of_packed_member (type, orig_rhs);
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
@@ -6982,6 +7033,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
}
+ /* If LHS is't an address, check pointer or array of packed
+ struct or union. */
+ if (TREE_CODE (orig_rhs) != ADDR_EXPR)
+ warn_for_pointer_of_packed_member (location, type, orig_rhs);
+ else
+ warn_for_address_of_packed_member (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 46d5ef5e7c0..77f3f45557b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7430,6 +7430,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ warn_for_address_of_packed_member (type, val);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1102f677f15..f62ed731e89 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8888,6 +8888,8 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ warn_for_address_of_packed_member (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 27c597492be..d2df13903da 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -260,8 +260,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6390,6 +6390,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-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-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-16.c b/gcc/testsuite/gcc.dg/pr51628-16.c
new file mode 100644
index 00000000000..94a3a8fbaf2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-16.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 result in an unaligned pointer value" "" { target *-*-* } .-1 } */
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..bcdbff1e554
--- /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 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..0c7fab75d8a
--- /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 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.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.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] C/C++: Add -Waddress-of-packed-member
@ 2018-04-26 3:49 H.J. Lu
0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2018-04-26 3:49 UTC (permalink / raw)
To: gcc-patches
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]
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:33: warning: taking value of packed 'struct C *' may result in an unaligned pointer value [-Waddress-of-packed-member]
long* g8 (struct C *p) { return p; }
^
$
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.
OK for trunk?
H.J.
----
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_of_packed_member): New.
* c-warn.c (check_address_of_packed_member): New function.
(warn_for_address_of_packed_member): Likewise.
* c.opt: Add -Wno-address-of-packed-member.
gcc/c/
PR c/51628
* c-typeck.c (warn_for_pointer_of_packed_member): New function.
(convert_for_assignment): Call warn_for_address_of_packed_member
and warn_for_pointer_of_packed_member.
gcc/cp/
PR c/51628
* call.c (convert_for_arg_passing): Call
warn_for_address_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.
* gcc.dg/pr51628-16.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.
* 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 | 117 +++++++++++++++++++++
gcc/c-family/c.opt | 4 +
gcc/c/c-typeck.c | 60 ++++++++++-
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-2.c | 29 +++++
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-16.c | 9 ++
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.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 +
47 files changed, 723 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-2.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-16.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
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 6cf7614f682..2e09a36061f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1270,6 +1270,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_of_packed_member (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 d0d9c7894a8..43805b2f6df 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2587,3 +2587,120 @@ 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 (TREE_CODE (base) == ARRAY_REF)
+ 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;
+ unsigned int type_align, record_align;
+
+ /* Check alignment of the data member. */
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (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;
+}
+
+/* Warn 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. */
+
+void
+warn_for_address_of_packed_member (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;
+
+ /* Get the type of the pointer pointing to. */
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (rhs) == NOP_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ tree context;
+
+ 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);
+ }
+ }
+ else
+ 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);
+ }
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a4c8c8ffcb3..a347f5e42c4 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -599,6 +599,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 5b3ea28af06..3ed89e9c4b0 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6289,6 +6289,54 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum,
expected_type, actual_type);
}
+/* Warn if the right hand poiner value RHS isn't aligned to a
+ pointer type TYPE. ERRTYPE says whether it is argument passing,
+ assignment, initialization or return. PARMNUM is the number of
+ the argument, for printing in error messages. NAME is the name
+ of the function. */
+
+static void
+warn_for_pointer_of_packed_member (location_t location, tree type,
+ tree rhs)
+{
+ if (!warn_address_of_packed_member || !POINTER_TYPE_P (type))
+ return;
+
+ bool pointer_p;
+ tree rhstype;
+
+ /* Check the original type of LHS. */
+ switch (TREE_CODE (rhs))
+ {
+ case PARM_DECL:
+ case VAR_DECL:
+ rhstype = TREE_TYPE (rhs);
+ pointer_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);
+ pointer_p = TREE_CODE (rhstype) == ARRAY_TYPE;
+ break;
+ default:
+ return;
+ }
+
+ if (pointer_p
+ && TYPE_PACKED (TREE_TYPE (rhstype)))
+ {
+ unsigned int type_align = TYPE_ALIGN (TREE_TYPE (type));
+ unsigned int rhs_align = TYPE_ALIGN (TREE_TYPE (rhstype));
+ if ((rhs_align % type_align) != 0)
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "taking value of packed %qT may result in an "
+ "unaligned pointer value",
+ rhstype);
+ }
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -6499,7 +6547,10 @@ 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_of_packed_member (type, orig_rhs);
+ return rhs;
+ }
if (coder == VOID_TYPE)
{
@@ -6986,6 +7037,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
}
+ /* If LHS is't an address, check pointer or array of packed
+ struct or union. */
+ if (TREE_CODE (orig_rhs) != ADDR_EXPR)
+ warn_for_pointer_of_packed_member (location, type, orig_rhs);
+ else
+ warn_for_address_of_packed_member (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 fb6d71d260d..841a67ea007 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7446,6 +7446,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
maybe_warn_parm_abi (type, EXPR_LOC_OR_LOC (val, input_location));
}
+
+ warn_for_address_of_packed_member (type, val);
+
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 907d31d9786..2d3f78d2e8a 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8903,6 +8903,8 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
+ warn_for_address_of_packed_member (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 9c7fe187f48..cdd29c9ff0d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -260,8 +260,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 @gol
--Walloc-zero -Walloc-size-larger-than=@var{n}
+-w -Wextra -Wall -Waddress -Waddress-of-packed-member @gol
+-Waggregate-return -Walloc-zero -Walloc-size-larger-than=@var{n} @gol
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
@@ -6469,6 +6469,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-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-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-16.c b/gcc/testsuite/gcc.dg/pr51628-16.c
new file mode 100644
index 00000000000..94a3a8fbaf2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-16.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 result in an unaligned pointer value" "" { target *-*-* } .-1 } */
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..bcdbff1e554
--- /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 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..0c7fab75d8a
--- /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 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.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.14.3
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2018-04-26 2:54 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-14 15:02 [PATCH] C/C++: Add -Waddress-of-packed-member H.J. Lu
2018-01-15 9:47 ` Jakub Jelinek
2018-01-15 15:02 ` H.J. Lu
2018-01-17 11:44 ` H.J. Lu
2018-01-19 17:18 ` Martin Sebor
2018-01-20 6:17 ` Martin Sebor
2018-01-20 17:32 ` H.J. Lu
2018-01-20 20:28 ` H.J. Lu
2018-01-21 4:27 ` H.J. Lu
2018-04-26 3:49 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).