Commit 8c3563f3 by Richard Biener Committed by Richard Biener

re PR tree-optimization/77291 (False positive for -Warray-bounds)

2017-12-18  Richard Biener  <rguenther@suse.de>

	PR middle-end/77291
	* tree.c (array_at_struct_end_p): Return true if the underlying
	object has space for at least one element in excess of what
	the array domain specifies.

	* gcc.dg/Warray-bounds-26.c: New testcase.

From-SVN: r255775
parent 040a4493
2017-12-18 Richard Biener <rguenther@suse.de>
PR middle-end/77291
* tree.c (array_at_struct_end_p): Return true if the underlying
object has space for at least one element in excess of what
the array domain specifies.
2017-12-17 Sandra Loosemore <sandra@codesourcery.com> 2017-12-17 Sandra Loosemore <sandra@codesourcery.com>
* doc/extend.texi (x86 Function Attributes): Reformat nocf_check * doc/extend.texi (x86 Function Attributes): Reformat nocf_check
2017-12-18 Richard Biener <rguenther@suse.de>
PR middle-end/77291
* gcc.dg/Warray-bounds-26.c: New testcase.
2017-12-17 Uros Bizjak <ubizjak@gmail.com> 2017-12-17 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/guality/guality.h (guality_check): Cast %lli arguments * gcc.dg/guality/guality.h (guality_check): Cast %lli arguments
......
/* { dg-do compile } */
/* { dg-options "-O2 -Warray-bounds" } */
struct Rec {
unsigned char data[1]; // actually variable length
};
union U {
unsigned char buf[42];
struct Rec rec;
};
int Load()
{
union U u;
return u.rec.data[1]; /* { dg-bogus "array bound" } */
}
...@@ -12644,6 +12644,7 @@ array_at_struct_end_p (tree ref) ...@@ -12644,6 +12644,7 @@ array_at_struct_end_p (tree ref)
if (TREE_CODE (ref) == STRING_CST) if (TREE_CODE (ref) == STRING_CST)
return false; return false;
tree ref_to_array = ref;
while (handled_component_p (ref)) while (handled_component_p (ref))
{ {
/* If the reference chain contains a component reference to a /* If the reference chain contains a component reference to a
...@@ -12682,35 +12683,43 @@ array_at_struct_end_p (tree ref) ...@@ -12682,35 +12683,43 @@ array_at_struct_end_p (tree ref)
/* The array now is at struct end. Treat flexible arrays as /* The array now is at struct end. Treat flexible arrays as
always subject to extend, even into just padding constrained by always subject to extend, even into just padding constrained by
an underlying decl. */ an underlying decl. */
if (! TYPE_SIZE (atype)) if (! TYPE_SIZE (atype)
|| ! TYPE_DOMAIN (atype)
|| ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
return true; return true;
tree size = NULL;
if (TREE_CODE (ref) == MEM_REF if (TREE_CODE (ref) == MEM_REF
&& TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR) && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
{ ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
size = TYPE_SIZE (TREE_TYPE (ref));
ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
}
/* If the reference is based on a declared entity, the size of the array /* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. (Do not trust commons PR/69368). */ is constrained by its given domain. (Do not trust commons PR/69368). */
if (DECL_P (ref) if (DECL_P (ref)
/* Be sure the size of MEM_REF target match. For example: && !(flag_unconstrained_commons
&& VAR_P (ref) && DECL_COMMON (ref))
char buf[10]; && DECL_SIZE_UNIT (ref)
struct foo *str = (struct foo *)&buf; && TREE_CODE (DECL_SIZE_UNIT (ref)) == INTEGER_CST)
{
str->trailin_array[2] = 1; /* Check whether the array domain covers all of the available
padding. */
HOST_WIDE_INT offset;
if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST)
return true;
if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
return true;
is valid because BUF allocate enough space. */ /* If at least one extra element fits it is a flexarray. */
if (wi::les_p ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
- wi::to_offset (TYPE_MIN_VALUE (TYPE_DOMAIN (atype)))
+ 2)
* wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
return true;
&& (!size || (DECL_SIZE (ref) != NULL return false;
&& operand_equal_p (DECL_SIZE (ref), size, 0))) }
&& !(flag_unconstrained_commons
&& VAR_P (ref) && DECL_COMMON (ref)))
return false;
return true; return true;
} }
......
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