Avoid pathological function redeclarations when checking access sizes [PR102759].

Resolves:
PR tree-optimization/102759 - ICE: Segmentation fault in maybe_check_access_sizes since r12-2976-gb48d4e6818674898

gcc/ChangeLog:

	PR tree-optimization/102759
	* gimple-array-bounds.cc (build_printable_array_type): Move...
	* gimple-ssa-warn-access.cc (build_printable_array_type): Avoid
	pathological function redeclarations that remove a previously
	declared prototype.
	Improve formatting of function arguments in informational notes.
	* pointer-query.cc (build_printable_array_type): ...to here.
	* pointer-query.h (build_printable_array_type): Declared.

gcc/testsuite/ChangeLog:

	PR tree-optimization/102759
	* gcc.dg/Warray-parameter-10.c: New test.
	* gcc.dg/Wstringop-overflow-82.c: New test.
This commit is contained in:
Martin Sebor 2021-11-17 15:09:23 -07:00
parent 53a643f856
commit ea9e0d6c27
6 changed files with 105 additions and 35 deletions

View File

@ -372,31 +372,6 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
return warned;
}
/* Wrapper around build_array_type_nelts that makes sure the array
can be created at all and handles zero sized arrays specially. */
static tree
build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
{
if (TYPE_SIZE_UNIT (eltype)
&& TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
&& !integer_zerop (TYPE_SIZE_UNIT (eltype))
&& TYPE_ALIGN_UNIT (eltype) > 1
&& wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
eltype = TYPE_MAIN_VARIANT (eltype);
if (nelts)
return build_array_type_nelts (eltype, nelts);
tree idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
tree arrtype = build_array_type (eltype, idxtype);
arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
TYPE_SIZE (arrtype) = bitsize_zero_node;
TYPE_SIZE_UNIT (arrtype) = size_zero_node;
return arrtype;
}
/* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
references to string constants. If VRP can determine that the array
subscript is a constant, check if it is outside valid range.

View File

@ -2978,10 +2978,16 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
continue;
tree ptrtype = fntype_argno_type (fntype, ptridx);
if (!ptrtype)
/* A function with a prototype was redeclared without one and
the protype has been lost. See pr102759. Avoid dealing
with this pathological case. */
return;
tree argtype = TREE_TYPE (ptrtype);
/* The size of the access by the call. */
tree access_size;
/* The size of the access by the call in elements. */
tree access_nelts;
if (sizidx == -1)
{
/* If only the pointer attribute operand was specified and
@ -2991,17 +2997,17 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
if the pointer is also declared with attribute nonnull. */
if (access.second.minsize
&& access.second.minsize != HOST_WIDE_INT_M1U)
access_size = build_int_cstu (sizetype, access.second.minsize);
access_nelts = build_int_cstu (sizetype, access.second.minsize);
else
access_size = size_one_node;
access_nelts = size_one_node;
}
else
access_size = rwm->get (sizidx)->size;
access_nelts = rwm->get (sizidx)->size;
/* Format the value or range to avoid an explosion of messages. */
char sizstr[80];
tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
if (get_size_range (m_ptr_qry.rvals, access_size, stmt, sizrng, 1))
if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1))
{
char *s0 = print_generic_expr_to_str (sizrng[0]);
if (tree_int_cst_equal (sizrng[0], sizrng[1]))
@ -3059,6 +3065,8 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
}
}
/* The size of the access by the call in bytes. */
tree access_size = NULL_TREE;
if (tree_int_cst_sgn (sizrng[0]) >= 0)
{
if (COMPLETE_TYPE_P (argtype))
@ -3075,9 +3083,9 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
access_size = wide_int_to_tree (sizetype, minsize);
}
}
else
access_size = access_nelts;
}
else
access_size = NULL_TREE;
if (integer_zerop (ptr))
{
@ -3172,8 +3180,13 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
if (opt_warned != no_warning)
{
if (access.second.internal_p)
inform (loc, "referencing argument %u of type %qT",
ptridx + 1, ptrtype);
{
unsigned HOST_WIDE_INT nelts =
access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U;
tree arrtype = build_printable_array_type (argtype, nelts);
inform (loc, "referencing argument %u of type %qT",
ptridx + 1, arrtype);
}
else
/* If check_access issued a warning above, append the relevant
attribute to the string. */

View File

@ -2358,3 +2358,33 @@ array_elt_at_offset (tree artype, HOST_WIDE_INT off,
return NULL_TREE;
}
/* Wrapper around build_array_type_nelts that makes sure the array
can be created at all and handles zero sized arrays specially. */
tree
build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
{
if (TYPE_SIZE_UNIT (eltype)
&& TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
&& !integer_zerop (TYPE_SIZE_UNIT (eltype))
&& TYPE_ALIGN_UNIT (eltype) > 1
&& wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
eltype = TYPE_MAIN_VARIANT (eltype);
/* Consider excessive NELTS an array of unknown bound. */
tree idxtype = NULL_TREE;
if (nelts < HOST_WIDE_INT_MAX)
{
if (nelts)
return build_array_type_nelts (eltype, nelts);
idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
}
tree arrtype = build_array_type (eltype, idxtype);
arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
TYPE_SIZE (arrtype) = bitsize_zero_node;
TYPE_SIZE_UNIT (arrtype) = size_zero_node;
return arrtype;
}

View File

@ -275,4 +275,7 @@ extern tree array_elt_at_offset (tree, HOST_WIDE_INT,
HOST_WIDE_INT * = nullptr,
HOST_WIDE_INT * = nullptr);
/* Helper to build an array type that can be printed. */
extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT);
#endif // GCC_POINTER_QUERY_H

View File

@ -0,0 +1,20 @@
/* PR c/102759 - ICE calling a function taking an argument redeclared
without a prototype.
{ dg-do compile }
{ dg-options "-Wall" } */
void f (void)
{
void gia (int[2]);
void g ();
}
/* Redeclaring the g(int[]) above without a prototype loses it. */
void gia ();
void g (int[2]);
void h (void )
{
gia (gia);
gia (g);
}

View File

@ -0,0 +1,29 @@
/* Verify that notes after warnings for array and VLA parameters show
the array form.
{ dg-do compile }
{ dg-options "-Wall" } */
void fia5 (int[5]);
void gia3_fia5 (void)
{
int a[3];
fia5 (a); // { dg-warning "-Wstringop-overflow" }
// { dg-message "argument 1 of type 'int\\\[5]'" "note" { target *-*-* } .-1 }
}
/* The type of the argument would ideall be 'int[n]' but the variable
bound is lost/cleared by free-lang-data and never makes it into
the middle end. An (inferior) alternative would be 'int[*]' but
the pretty printer doesn't know how to format the star. A better
solution might be to introduce a new notation, like 'int[$1]',
where the $1 refers to the VLA argument bound. */
void fvla (int n, int[n]);
void gia3_fvla (void)
{
int a[3];
fvla (sizeof a, a); // { dg-warning "-Wstringop-overflow" }
// { dg-message "argument 2 of type 'int\\\[]'" "note" { target *-*-* } .-1 }
}