summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-08-22 23:09:26 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-08-22 17:09:26 -0600
commit14b7950f126f84fa585e3a057940ff10d4c5b3f8 (patch)
tree12d343894aea62b7964a5f595ddfd3cac40750e6 /gcc/expr.c
parent1b1e13dbde7f3eef0f8356af05c5de1fb46cb31b (diff)
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.c64
1 files changed, 49 insertions, 15 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 92979289e83..5ca0e20f14a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;