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
This commit is contained in:
parent
cab81ec045
commit
420183d996
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
while (TREE_CODE (rhs) == COMPOUND_EXPR)
|
||||
rhs = TREE_OPERAND (rhs, 1);
|
||||
bool nop_p;
|
||||
|
||||
tree context = check_address_of_packed_member (type, rhs);
|
||||
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)
|
||||
{
|
||||
/* Check the THEN path. */
|
||||
check_and_warn_address_or_pointer_of_packed_member
|
||||
(type, TREE_OPERAND (rhs, 1));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 } */
|
||||
}
|
|
@ -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 } */
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 } */
|
||||
}
|
|
@ -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 } */
|
||||
}
|
Loading…
Reference in New Issue