aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2019-01-18 13:05:18 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2019-01-18 05:05:18 -0800
commit420183d996f320dddb3d1094ae340c53719e0de3 (patch)
tree3606267c6b36098a85b4a09a3a0d4db540ce8c7b /gcc
parentcab81ec045acaaf6f4a562e212c6b8b95d98a3ea (diff)
downloadgcc-420183d996f320dddb3d1094ae340c53719e0de3.zip
gcc-420183d996f320dddb3d1094ae340c53719e0de3.tar.gz
gcc-420183d996f320dddb3d1094ae340c53719e0de3.tar.bz2
c-family: Update unaligned adress of packed member check
Check unaligned pointer conversion and strip NOPS. gcc/c-family/ PR c/51628 PR c/88664 * c-common.h (warn_for_address_or_pointer_of_packed_member): Remove the boolean argument. * c-warn.c (check_address_of_packed_member): Renamed to ... (check_address_or_pointer_of_packed_member): This. Also warn pointer conversion. (check_and_warn_address_of_packed_member): Renamed to ... (check_and_warn_address_or_pointer_of_packed_member): This. Also warn pointer conversion. (warn_for_address_or_pointer_of_packed_member): Remove the boolean argument. Don't check pointer conversion here. gcc/c PR c/51628 PR c/88664 * c-typeck.c (convert_for_assignment): Upate the warn_for_address_or_pointer_of_packed_member call. gcc/cp PR c/51628 PR c/88664 * call.c (convert_for_arg_passing): Upate the warn_for_address_or_pointer_of_packed_member call. * typeck.c (convert_for_assignment): Likewise. gcc/testsuite/ PR c/51628 PR c/88664 * c-c++-common/pr51628-33.c: New test. * c-c++-common/pr51628-35.c: New test. * c-c++-common/pr88664-1.c: Likewise. * c-c++-common/pr88664-2.c: Likewise. * gcc.dg/pr51628-34.c: Likewise. From-SVN: r268075
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog15
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c-family/c-warn.c177
-rw-r--r--gcc/c/ChangeLog7
-rw-r--r--gcc/c/c-typeck.c6
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/c-c++-common/pr51628-33.c19
-rw-r--r--gcc/testsuite/c-c++-common/pr51628-35.c23
-rw-r--r--gcc/testsuite/c-c++-common/pr88664-1.c20
-rw-r--r--gcc/testsuite/c-c++-common/pr88664-2.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr51628-34.c25
14 files changed, 250 insertions, 88 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 03ea65b..4aaf819 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,18 @@
+2019-01-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/51628
+ PR c/88664
+ * c-common.h (warn_for_address_or_pointer_of_packed_member):
+ Remove the boolean argument.
+ * c-warn.c (check_address_of_packed_member): Renamed to ...
+ (check_address_or_pointer_of_packed_member): This. Also
+ warn pointer conversion.
+ (check_and_warn_address_of_packed_member): Renamed to ...
+ (check_and_warn_address_or_pointer_of_packed_member): This.
+ Also warn pointer conversion.
+ (warn_for_address_or_pointer_of_packed_member): Remove the
+ boolean argument. Don't check pointer conversion here.
+
2019-01-15 Richard Sandiford <richard.sandiford@arm.com>
PR inline-asm/52813
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 9fe90f3..69cb76c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1293,7 +1293,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
bool);
extern void warn_for_omitted_condop (location_t, tree);
extern bool warn_for_restrict (unsigned, tree *, unsigned);
-extern void warn_for_address_or_pointer_of_packed_member (bool, tree, tree);
+extern void warn_for_address_or_pointer_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 79b2d8a..7821cc8 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -2713,12 +2713,14 @@ check_alignment_of_packed_member (tree type, tree field)
return NULL_TREE;
}
-/* Return struct or union type if the right hand value, RHS, takes the
- unaligned address of packed member of struct or union when assigning
- to TYPE. Otherwise, return NULL_TREE. */
+/* Return struct or union type if the right hand value, RHS:
+ 1. Is a pointer value which isn't aligned to a pointer type TYPE.
+ 2. Is an address which 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)
+check_address_or_pointer_of_packed_member (tree type, tree rhs)
{
if (INDIRECT_REF_P (rhs))
rhs = TREE_OPERAND (rhs, 0);
@@ -2726,6 +2728,46 @@ check_address_of_packed_member (tree type, tree rhs)
if (TREE_CODE (rhs) == ADDR_EXPR)
rhs = TREE_OPERAND (rhs, 0);
+ if (POINTER_TYPE_P (type))
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (rhs) == PARM_DECL
+ || VAR_P (rhs)
+ || TREE_CODE (rhs) == CALL_EXPR)
+ {
+ if (TREE_CODE (rhs) == CALL_EXPR)
+ {
+ rhs = CALL_EXPR_FN (rhs); /* Pointer expression. */
+ if (rhs == NULL_TREE)
+ return NULL_TREE;
+ rhs = TREE_TYPE (rhs); /* Pointer type. */
+ rhs = TREE_TYPE (rhs); /* Function type. */
+ }
+ tree rhstype = TREE_TYPE (rhs);
+ if ((POINTER_TYPE_P (rhstype)
+ || TREE_CODE (rhstype) == ARRAY_TYPE)
+ && TYPE_PACKED (TREE_TYPE (rhstype)))
+ {
+ unsigned int type_align = TYPE_ALIGN_UNIT (type);
+ unsigned int rhs_align = TYPE_ALIGN_UNIT (TREE_TYPE (rhstype));
+ if ((rhs_align % type_align) != 0)
+ {
+ location_t location = EXPR_LOC_OR_LOC (rhs, input_location);
+ warning_at (location, OPT_Waddress_of_packed_member,
+ "converting a packed %qT pointer (alignment %d) "
+ "to %qT (alignment %d) may result in an "
+ "unaligned pointer value",
+ rhstype, rhs_align, type, type_align);
+ tree decl = TYPE_STUB_DECL (TREE_TYPE (rhstype));
+ inform (DECL_SOURCE_LOCATION (decl), "defined here");
+ decl = TYPE_STUB_DECL (type);
+ if (decl)
+ inform (DECL_SOURCE_LOCATION (decl), "defined here");
+ }
+ }
+ return NULL_TREE;
+ }
+
tree context = NULL_TREE;
/* Check alignment of the object. */
@@ -2744,18 +2786,56 @@ check_address_of_packed_member (tree type, tree rhs)
return context;
}
-/* Check and warn if the right hand value, RHS, takes the unaligned
- address of packed member of struct or union when assigning to TYPE. */
+/* Check and warn if the right hand value, RHS:
+ 1. Is a pointer value which isn't aligned to a pointer type TYPE.
+ 2. Is an address which takes the unaligned address of packed member
+ of struct or union when assigning to TYPE.
+ */
static void
-check_and_warn_address_of_packed_member (tree type, tree rhs)
+check_and_warn_address_or_pointer_of_packed_member (tree type, tree rhs)
{
- if (TREE_CODE (rhs) != COND_EXPR)
+ bool nop_p;
+
+ while (TREE_CODE (rhs) == COMPOUND_EXPR)
+ rhs = TREE_OPERAND (rhs, 1);
+
+ tree orig_rhs = rhs;
+ STRIP_NOPS (rhs);
+ nop_p = orig_rhs != rhs;
+
+ if (TREE_CODE (rhs) == COND_EXPR)
{
- while (TREE_CODE (rhs) == COMPOUND_EXPR)
- rhs = TREE_OPERAND (rhs, 1);
+ /* Check the THEN path. */
+ check_and_warn_address_or_pointer_of_packed_member
+ (type, TREE_OPERAND (rhs, 1));
- tree context = check_address_of_packed_member (type, rhs);
+ /* Check the ELSE path. */
+ check_and_warn_address_or_pointer_of_packed_member
+ (type, TREE_OPERAND (rhs, 2));
+ }
+ else
+ {
+ if (nop_p)
+ {
+ switch (TREE_CODE (rhs))
+ {
+ case ADDR_EXPR:
+ /* Address is taken. */
+ case PARM_DECL:
+ case VAR_DECL:
+ /* Pointer conversion. */
+ break;
+ case CALL_EXPR:
+ /* Function call. */
+ break;
+ default:
+ return;
+ }
+ }
+
+ tree context
+ = check_address_or_pointer_of_packed_member (type, rhs);
if (context)
{
location_t loc = EXPR_LOC_OR_LOC (rhs, input_location);
@@ -2764,26 +2844,17 @@ check_and_warn_address_of_packed_member (tree type, tree rhs)
"in an unaligned pointer value",
context);
}
- return;
}
-
- /* Check the THEN path. */
- check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 1));
-
- /* Check the ELSE path. */
- check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 2));
}
/* Warn if the right hand value, RHS:
- 1. For CONVERT_P == true, is a pointer value which isn't aligned to a
- pointer type TYPE.
- 2. For CONVERT_P == false, is an address which takes the unaligned
- address of packed member of struct or union when assigning to TYPE.
+ 1. Is a pointer value which isn't aligned to a pointer type TYPE.
+ 2. Is an address which takes the unaligned address of packed member
+ of struct or union when assigning to TYPE.
*/
void
-warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type,
- tree rhs)
+warn_for_address_or_pointer_of_packed_member (tree type, tree rhs)
{
if (!warn_address_of_packed_member)
return;
@@ -2792,61 +2863,5 @@ warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type,
if (!POINTER_TYPE_P (type))
return;
- while (TREE_CODE (rhs) == COMPOUND_EXPR)
- rhs = TREE_OPERAND (rhs, 1);
-
- if (convert_p)
- {
- bool rhspointer_p;
- tree rhstype;
-
- /* Check the original type of RHS. */
- switch (TREE_CODE (rhs))
- {
- case PARM_DECL:
- case VAR_DECL:
- rhstype = TREE_TYPE (rhs);
- rhspointer_p = POINTER_TYPE_P (rhstype);
- break;
- case NOP_EXPR:
- rhs = TREE_OPERAND (rhs, 0);
- if (TREE_CODE (rhs) == ADDR_EXPR)
- rhs = TREE_OPERAND (rhs, 0);
- rhstype = TREE_TYPE (rhs);
- rhspointer_p = TREE_CODE (rhstype) == ARRAY_TYPE;
- break;
- default:
- return;
- }
-
- if (rhspointer_p && TYPE_PACKED (TREE_TYPE (rhstype)))
- {
- unsigned int type_align = TYPE_ALIGN_UNIT (TREE_TYPE (type));
- unsigned int rhs_align = TYPE_ALIGN_UNIT (TREE_TYPE (rhstype));
- if ((rhs_align % type_align) != 0)
- {
- location_t location = EXPR_LOC_OR_LOC (rhs, input_location);
- warning_at (location, OPT_Waddress_of_packed_member,
- "converting a packed %qT pointer (alignment %d) "
- "to %qT (alignment %d) may result in an "
- "unaligned pointer value",
- rhstype, rhs_align, type, type_align);
- tree decl = TYPE_STUB_DECL (TREE_TYPE (rhstype));
- inform (DECL_SOURCE_LOCATION (decl), "defined here");
- decl = TYPE_STUB_DECL (TREE_TYPE (type));
- if (decl)
- inform (DECL_SOURCE_LOCATION (decl), "defined here");
- }
- }
- }
- else
- {
- /* Get the type of the pointer pointing to. */
- type = TREE_TYPE (type);
-
- if (TREE_CODE (rhs) == NOP_EXPR)
- rhs = TREE_OPERAND (rhs, 0);
-
- check_and_warn_address_of_packed_member (type, rhs);
- }
+ check_and_warn_address_or_pointer_of_packed_member (type, rhs);
}
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 2accb8f..fe83d69 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,10 @@
+2019-01-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/51628
+ PR c/88664
+ * c-typeck.c (convert_for_assignment): Upate the
+ warn_for_address_or_pointer_of_packed_member call.
+
2019-01-16 Tom Honermann <tom@honermann.net>
Jason Merrill <jason@redhat.com>
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 6da1f32..cbd612c 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6729,8 +6729,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
- warn_for_address_or_pointer_of_packed_member (false, type,
- orig_rhs);
+ warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
return rhs;
}
@@ -7289,8 +7288,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
/* If RHS isn't an address, check pointer or array of packed
struct or union. */
- warn_for_address_or_pointer_of_packed_member
- (TREE_CODE (orig_rhs) != ADDR_EXPR, type, orig_rhs);
+ warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
return convert (type, rhs);
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3fb1a89..d224b72 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2019-01-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/51628
+ PR c/88664
+ * call.c (convert_for_arg_passing): Upate the
+ warn_for_address_or_pointer_of_packed_member call.
+ * typeck.c (convert_for_assignment): Likewise.
+
2019-01-17 Jason Merrill <jason@redhat.com>
PR c++/86205 - ICE with ?: of throw and template-id.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c639f5f..499894b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7644,7 +7644,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
}
if (complain & tf_warning)
- warn_for_address_or_pointer_of_packed_member (false, type, val);
+ warn_for_address_or_pointer_of_packed_member (type, val);
return val;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 2fff262..47e407d 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -9069,7 +9069,7 @@ convert_for_assignment (tree type, tree rhs,
}
if (complain & tf_warning)
- warn_for_address_or_pointer_of_packed_member (false, type, rhs);
+ warn_for_address_or_pointer_of_packed_member (type, rhs);
return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
complain, flags);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dbb02ba..88a590e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2019-01-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/51628
+ PR c/88664
+ * c-c++-common/pr51628-33.c: New test.
+ * c-c++-common/pr51628-35.c: New test.
+ * c-c++-common/pr88664-1.c: Likewise.
+ * c-c++-common/pr88664-2.c: Likewise.
+ * gcc.dg/pr51628-34.c: Likewise.
+
2019-01-18 Richard Earnshaw <rearnsha@arm.com>
PR target/88799
diff --git a/gcc/testsuite/c-c++-common/pr51628-33.c b/gcc/testsuite/c-c++-common/pr51628-33.c
new file mode 100644
index 0000000..0092f32
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr51628-33.c
@@ -0,0 +1,19 @@
+/* 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 void bar (int *);
+
+void
+foo (struct pair_t *p)
+{
+ bar (p ? p->i : (int *) 0);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/pr51628-35.c b/gcc/testsuite/c-c++-common/pr51628-35.c
new file mode 100644
index 0000000..2087779
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr51628-35.c
@@ -0,0 +1,23 @@
+/* PR c/51628. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct B { int i; };
+struct C { struct B b; } __attribute__ ((packed));
+
+extern struct C *p;
+extern struct C *bar (void);
+
+long *
+foo1 (void)
+{
+ return (long *) p;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+long *
+foo2 (void)
+{
+ return (long *) bar ();
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/pr88664-1.c b/gcc/testsuite/c-c++-common/pr88664-1.c
new file mode 100644
index 0000000..5e680b9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr88664-1.c
@@ -0,0 +1,20 @@
+/* PR c/88664. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct data
+{
+ void *ptr;
+} __attribute__((packed));
+
+int *
+fun1 (struct data *p)
+{
+ return (int *) p->ptr;
+}
+
+int *
+fun2 (struct data *p, int *x)
+{
+ return x ? (*x = 1, (int *) p->ptr) : (int *) 0;
+}
diff --git a/gcc/testsuite/c-c++-common/pr88664-2.c b/gcc/testsuite/c-c++-common/pr88664-2.c
new file mode 100644
index 0000000..d2d880a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr88664-2.c
@@ -0,0 +1,22 @@
+/* PR c/88664. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct data
+{
+ void *ptr;
+} __attribute__((packed));
+
+void **
+fun1 (struct data *p)
+{
+ return &p->ptr;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+int *
+fun2 (struct data *p, int *x)
+{
+ return p ? (*x = 1, (int *) &p->ptr) : (int *) 0;
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr51628-34.c b/gcc/testsuite/gcc.dg/pr51628-34.c
new file mode 100644
index 0000000..51d4b26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51628-34.c
@@ -0,0 +1,25 @@
+/* PR c/51628. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wno-incompatible-pointer-types" } */
+
+struct __attribute__((packed)) S { char p; int a, b, c; };
+
+short *
+baz (int x, struct S *p)
+{
+ return (x
+ ? &p->a
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+ : &p->b);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}
+
+short *
+qux (int x, struct S *p)
+{
+ return (short *) (x
+ ? &p->a
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+ : &p->b);
+/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */
+}