On 8/21/19 2:50 PM, Martin Sebor wrote:
> This patch is a subset of the solution for PR 91457 whose main
> goal is to eliminate inconsistencies in warnings issued for
> out-of-bounds accesses to the various flavors of flexible array
> members of constant objects.  That patch was posted here:
>   https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01202.html
> 
> Like PR 91457, this patch also relies on improving optimization
> to issue better quality warnings.  (I.e., with the latter being
> what motivated it.)
> 
> The optimization enhances string_constant to recognize empty
> CONSTRUCTORs returned by fold_ctor_reference for references
> to members of constant objects with either "insufficient"
> initializers (e.g., given struct S { char n, a[]; } s = { 0 };)
> or with braced-list initializers (e.g., given
> struct S s = { 3 { 1, 2, 3, 0 } };  The patch lets string_constant
> convert the CONSTRUCTOR for s.a into a STRING_CST, which in turn
> enables the folding of calls to built-ins like strlen, strchr, or
> strcmp with such arguments.
> 
> Exposing the strings to the folder then also lets it detect and
> issue warnings for out-of-bounds offsets in more instances of
> such references than before.
> 
> The remaining changes in the patch mostly enhance the places
> that use the no-warning bit to prevent redundant diagnostics.
> 
> Tested on x86_64-linux.
> 
> Martin
> 
> gcc-91490.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.
> 
> 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.
>       * 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.
> 

> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 2810867235d..ef942ffce57 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -8868,7 +8876,7 @@ braced_lists_to_strings (tree type, tree ctor)
>        unsigned HOST_WIDE_INT idx;
>        FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), idx, val)
>       {
> -       val = braced_lists_to_strings (ttp, val);
> +       val = braced_lists_to_strings (ttp, val, code == RECORD_TYPE);
Do you need to handle UNION_TYPE or QUAL_UNION_TYPE here too?  If so,
RECORD_OR_UNION_TYPE_P is a better test.


> diff --git a/gcc/expr.c b/gcc/expr.c
> index 92979289e83..d16e0982dcf 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -11402,6 +11402,16 @@ 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;
> +
> +  tree chartype = TREE_TYPE (arg);
> +  if (POINTER_TYPE_P (chartype))
> +    chartype = TREE_TYPE (chartype);
> +  while (TREE_CODE (chartype) == ARRAY_TYPE)
> +    chartype = TREE_TYPE (chartype);
I'm hesitant to ACK this bit.  I can understand that if we're given an
ADDR_EXPR, which should be a POINTER_TYPE_P, that we'll want to look at
what it's pointing to.  But shouldn't we verify that it's an ADDR_EXPR
before just blindly stripping away the outer type?

I also wonder if this (assuming we keep it in some form) belongs after
the STRIP_NOPs.


> @@ -11602,17 +11605,39 @@ 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 && !CONSTRUCTOR_ELTS (init))
Would initializer_zerop be better here?  That would catch
zero-initialized constructors as well.

If not, then you want to make sure to check !TREE_CLOBBER_P (init) since
that's something completely different than zero initialization.


>  
>    return init;
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index d576b0842f9..fcffb9802b7 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
[ ... ]
None of the gimple-fold stuff looked strictly necessary for this patch.
  But gimple-fold changes are OK.


I think you need to double-check your ChangeLog as well.  There's
changes in expr.c that aren't reflected in the ChangeLog.  The changes
to fold_nonarray_ctor_reference don't seem to match the ChangeLog either.

Mostly this looks OK.  I think we close on the issues above and this
will be ready for the trunk.

jeff


Reply via email to