From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1930) id 9E6C03858402; Wed, 17 Nov 2021 22:10:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9E6C03858402 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Martin Sebor To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-5354] Avoid pathological function redeclarations when checking access sizes [PR102759]. X-Act-Checkin: gcc X-Git-Author: Martin Sebor X-Git-Refname: refs/heads/master X-Git-Oldrev: 53a643f8568067d7700a9f2facc8ba39974973d3 X-Git-Newrev: ea9e0d6c27405d256b4888e9e860e469037c911d Message-Id: <20211117221047.9E6C03858402@sourceware.org> Date: Wed, 17 Nov 2021 22:10:47 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Nov 2021 22:10:47 -0000 https://gcc.gnu.org/g:ea9e0d6c27405d256b4888e9e860e469037c911d commit r12-5354-gea9e0d6c27405d256b4888e9e860e469037c911d Author: Martin Sebor Date: Wed Nov 17 15:09:23 2021 -0700 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. Diff: --- gcc/gimple-array-bounds.cc | 25 --------------------- gcc/gimple-ssa-warn-access.cc | 33 +++++++++++++++++++--------- gcc/pointer-query.cc | 30 +++++++++++++++++++++++++ gcc/pointer-query.h | 3 +++ gcc/testsuite/gcc.dg/Warray-parameter-10.c | 20 +++++++++++++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-82.c | 29 ++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 35 deletions(-) diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index a3535598998..ddb99d263d1 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -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. diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 22c791d833a..48bf8aaff50 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -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. */ diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index a0e4543d8a3..2ead0271617 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -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; +} diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index c8215b681ef..fbea3316f14 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -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 diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-10.c b/gcc/testsuite/gcc.dg/Warray-parameter-10.c new file mode 100644 index 00000000000..378f8afbd34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-10.c @@ -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); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c new file mode 100644 index 00000000000..ee2693dcea9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c @@ -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 } +}