diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2019-01-18 13:05:18 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2019-01-18 05:05:18 -0800 |
commit | 420183d996f320dddb3d1094ae340c53719e0de3 (patch) | |
tree | 3606267c6b36098a85b4a09a3a0d4db540ce8c7b /gcc | |
parent | cab81ec045acaaf6f4a562e212c6b8b95d98a3ea (diff) | |
download | gcc-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/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 2 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 177 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr51628-33.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr51628-35.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr88664-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr88664-2.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr51628-34.c | 25 |
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 } */ +} |