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:
parent
53a643f856
commit
ea9e0d6c27
6 changed files with 105 additions and 35 deletions
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
20
gcc/testsuite/gcc.dg/Warray-parameter-10.c
Normal file
20
gcc/testsuite/gcc.dg/Warray-parameter-10.c
Normal 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);
|
||||
}
|
29
gcc/testsuite/gcc.dg/Wstringop-overflow-82.c
Normal file
29
gcc/testsuite/gcc.dg/Wstringop-overflow-82.c
Normal 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 }
|
||||
}
|
Loading…
Add table
Reference in a new issue