diff options
author | Martin Sebor <msebor@redhat.com> | 2019-08-22 23:09:26 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-08-22 17:09:26 -0600 |
commit | 14b7950f126f84fa585e3a057940ff10d4c5b3f8 (patch) | |
tree | 12d343894aea62b7964a5f595ddfd3cac40750e6 /gcc/expr.c | |
parent | 1b1e13dbde7f3eef0f8356af05c5de1fb46cb31b (diff) | |
download | gcc-14b7950f126f84fa585e3a057940ff10d4c5b3f8.zip gcc-14b7950f126f84fa585e3a057940ff10d4c5b3f8.tar.gz gcc-14b7950f126f84fa585e3a057940ff10d4c5b3f8.tar.bz2 |
PR middle-end/91490 - bogus argument missing terminating nul warning on strlen of a flexible array member
gcc/c-family/ChangeLog:
PR middle-end/91490
* c-common.c (braced_list_to_string): Add argument and overload.
Handle flexible length arrays and unions.
gcc/testsuite/ChangeLog:
PR middle-end/91490
* c-c++-common/Warray-bounds-7.c: New test.
* gcc.dg/Warray-bounds-39.c: Expect either -Warray-bounds or
-Wstringop-overflow.
* gcc.dg/strlenopt-78.c: New test.
gcc/ChangeLog:
PR middle-end/91490
* builtins.c (c_strlen): Rename argument and introduce new local.
Set no-warning bit on original argument.
* expr.c (string_constant): Pass argument type to fold_ctor_reference.
Fold empty and zero constructors into empty strings.
* gimple-fold.c (fold_nonarray_ctor_reference): Return a STRING_CST
for missing initializers.
* tree.c (build_string_literal): Handle optional argument.
* tree.h (build_string_literal): Add defaulted argument.
* gimple-ssa-warn-restrict.c (maybe_diag_access_bounds): Check
no-warning bit on original expression.
From-SVN: r274837
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 64 |
1 files changed, 49 insertions, 15 deletions
@@ -11402,6 +11402,15 @@ is_aligning_offset (const_tree offset, const_tree exp) tree string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) { + tree dummy = NULL_TREE;; + if (!mem_size) + mem_size = &dummy; + + /* Store the type of the original expression before conversions + via NOP_EXPR or POINTER_PLUS_EXPR to other types have been + removed. */ + tree argtype = TREE_TYPE (arg); + tree array; STRIP_NOPS (arg); @@ -11464,7 +11473,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == ARRAY_TYPE && !(decl && !*decl) && !(decl && tree_fits_uhwi_p (DECL_SIZE_UNIT (*decl)) - && mem_size && tree_fits_uhwi_p (*mem_size) + && tree_fits_uhwi_p (*mem_size) && tree_int_cst_equal (*mem_size, DECL_SIZE_UNIT (*decl)))) return NULL_TREE; @@ -11496,7 +11505,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs1))) == ARRAY_TYPE && !(decl && !*decl) && !(decl && tree_fits_uhwi_p (DECL_SIZE_UNIT (*decl)) - && mem_size && tree_fits_uhwi_p (*mem_size) + && tree_fits_uhwi_p (*mem_size) && tree_int_cst_equal (*mem_size, DECL_SIZE_UNIT (*decl)))) return NULL_TREE; @@ -11530,8 +11539,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) if (TREE_CODE (array) == STRING_CST) { *ptr_offset = fold_convert (sizetype, offset); - if (mem_size) - *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (array)); + *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (array)); if (decl) *decl = NULL_TREE; gcc_checking_assert (tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (array))) @@ -11561,7 +11569,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) base_off = wioff.to_uhwi (); unsigned HOST_WIDE_INT fieldoff = 0; - init = fold_ctor_reference (NULL_TREE, init, base_off, 0, array, + init = fold_ctor_reference (TREE_TYPE (arg), init, base_off, 0, array, &fieldoff); HOST_WIDE_INT cstoff; if (!base_off.is_constant (&cstoff)) @@ -11580,17 +11588,11 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) *ptr_offset = offset; - tree eltype = TREE_TYPE (init); - tree initsize = TYPE_SIZE_UNIT (eltype); - if (mem_size) - *mem_size = initsize; - - if (decl) - *decl = array; + tree inittype = TREE_TYPE (init); if (TREE_CODE (init) == INTEGER_CST && (TREE_CODE (TREE_TYPE (array)) == INTEGER_TYPE - || TYPE_MAIN_VARIANT (eltype) == char_type_node)) + || TYPE_MAIN_VARIANT (inittype) == char_type_node)) { /* For a reference to (address of) a single constant character, store the native representation of the character in CHARBUF. @@ -11602,17 +11604,49 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl) int len = native_encode_expr (init, charbuf, sizeof charbuf, 0); if (len > 0) { - /* Construct a string literal with elements of ELTYPE and + /* Construct a string literal with elements of INITTYPE and the representation above. Then strip the ADDR_EXPR (ARRAY_REF (...)) around the STRING_CST. */ - init = build_string_literal (len, (char *)charbuf, eltype); + init = build_string_literal (len, (char *)charbuf, inittype); init = TREE_OPERAND (TREE_OPERAND (init, 0), 0); } } + tree initsize = TYPE_SIZE_UNIT (inittype); + + if (TREE_CODE (init) == CONSTRUCTOR && initializer_zerop (init)) + { + /* Fold an empty/zero constructor for an implicitly initialized + object or subobject into the empty string. */ + + /* Determine the character type from that of the original + expression. */ + tree chartype = argtype; + if (POINTER_TYPE_P (chartype)) + chartype = TREE_TYPE (chartype); + while (TREE_CODE (chartype) == ARRAY_TYPE) + chartype = TREE_TYPE (chartype); + /* Convert a char array to an empty STRING_CST having an array + of the expected type. */ + if (!initsize) + initsize = integer_zero_node; + + unsigned HOST_WIDE_INT size = tree_to_uhwi (initsize); + init = build_string_literal (size ? 1 : 0, "", chartype, size); + init = TREE_OPERAND (init, 0); + init = TREE_OPERAND (init, 0); + + *ptr_offset = integer_zero_node; + } + + if (decl) + *decl = array; + if (TREE_CODE (init) != STRING_CST) return NULL_TREE; + *mem_size = initsize; + gcc_checking_assert (tree_to_shwi (initsize) >= TREE_STRING_LENGTH (init)); return init; |