Commit 420183d9 by H.J. Lu Committed by H.J. Lu

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
parent cab81ec0
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> 2019-01-15 Richard Sandiford <richard.sandiford@arm.com>
PR inline-asm/52813 PR inline-asm/52813
......
...@@ -1293,7 +1293,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool, ...@@ -1293,7 +1293,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
bool); bool);
extern void warn_for_omitted_condop (location_t, tree); extern void warn_for_omitted_condop (location_t, tree);
extern bool warn_for_restrict (unsigned, tree *, unsigned); 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. /* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and Used to select diagnostic messages in lvalue_error and
......
...@@ -2713,12 +2713,14 @@ check_alignment_of_packed_member (tree type, tree field) ...@@ -2713,12 +2713,14 @@ check_alignment_of_packed_member (tree type, tree field)
return NULL_TREE; return NULL_TREE;
} }
/* Return struct or union type if the right hand value, RHS, takes the /* Return struct or union type if the right hand value, RHS:
unaligned address of packed member of struct or union when assigning 1. Is a pointer value which isn't aligned to a pointer type TYPE.
to TYPE. Otherwise, return NULL_TREE. */ 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 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)) if (INDIRECT_REF_P (rhs))
rhs = TREE_OPERAND (rhs, 0); rhs = TREE_OPERAND (rhs, 0);
...@@ -2726,6 +2728,46 @@ check_address_of_packed_member (tree type, tree rhs) ...@@ -2726,6 +2728,46 @@ check_address_of_packed_member (tree type, tree rhs)
if (TREE_CODE (rhs) == ADDR_EXPR) if (TREE_CODE (rhs) == ADDR_EXPR)
rhs = TREE_OPERAND (rhs, 0); 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; tree context = NULL_TREE;
/* Check alignment of the object. */ /* Check alignment of the object. */
...@@ -2744,18 +2786,56 @@ check_address_of_packed_member (tree type, tree rhs) ...@@ -2744,18 +2786,56 @@ check_address_of_packed_member (tree type, tree rhs)
return context; return context;
} }
/* Check and warn if the right hand value, RHS, takes the unaligned /* Check and warn if the right hand value, RHS:
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.
*/
static void 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) /* Check the THEN path. */
rhs = TREE_OPERAND (rhs, 1); 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) if (context)
{ {
location_t loc = EXPR_LOC_OR_LOC (rhs, input_location); 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) ...@@ -2764,26 +2844,17 @@ check_and_warn_address_of_packed_member (tree type, tree rhs)
"in an unaligned pointer value", "in an unaligned pointer value",
context); 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: /* Warn if the right hand value, RHS:
1. For CONVERT_P == true, is a pointer value which isn't aligned to a 1. Is a pointer value which isn't aligned to a pointer type TYPE.
pointer type TYPE. 2. Is an address which takes the unaligned address of packed member
2. For CONVERT_P == false, is an address which takes the unaligned of struct or union when assigning to TYPE.
address of packed member of struct or union when assigning to TYPE.
*/ */
void void
warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type, warn_for_address_or_pointer_of_packed_member (tree type, tree rhs)
tree rhs)
{ {
if (!warn_address_of_packed_member) if (!warn_address_of_packed_member)
return; return;
...@@ -2792,61 +2863,5 @@ warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type, ...@@ -2792,61 +2863,5 @@ warn_for_address_or_pointer_of_packed_member (bool convert_p, tree type,
if (!POINTER_TYPE_P (type)) if (!POINTER_TYPE_P (type))
return; return;
while (TREE_CODE (rhs) == COMPOUND_EXPR) check_and_warn_address_or_pointer_of_packed_member (type, rhs);
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);
}
} }
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> 2019-01-16 Tom Honermann <tom@honermann.net>
Jason Merrill <jason@redhat.com> Jason Merrill <jason@redhat.com>
......
...@@ -6729,8 +6729,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ...@@ -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)) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{ {
warn_for_address_or_pointer_of_packed_member (false, type, warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
orig_rhs);
return rhs; return rhs;
} }
...@@ -7289,8 +7288,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ...@@ -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 /* If RHS isn't an address, check pointer or array of packed
struct or union. */ struct or union. */
warn_for_address_or_pointer_of_packed_member warn_for_address_or_pointer_of_packed_member (type, orig_rhs);
(TREE_CODE (orig_rhs) != ADDR_EXPR, type, orig_rhs);
return convert (type, rhs); return convert (type, rhs);
} }
......
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> 2019-01-17 Jason Merrill <jason@redhat.com>
PR c++/86205 - ICE with ?: of throw and template-id. 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) ...@@ -7644,7 +7644,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
} }
if (complain & tf_warning) 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; return val;
} }
......
...@@ -9069,7 +9069,7 @@ convert_for_assignment (tree type, tree rhs, ...@@ -9069,7 +9069,7 @@ convert_for_assignment (tree type, tree rhs,
} }
if (complain & tf_warning) 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, return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
complain, flags); complain, flags);
......
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> 2019-01-18 Richard Earnshaw <rearnsha@arm.com>
PR target/88799 PR target/88799
......
/* 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 } */
}
/* 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 } */
}
/* 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;
}
/* 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 } */
}
/* 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 } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment