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/c-family | |
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/c-family')
-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 |
3 files changed, 112 insertions, 82 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); } |