https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105726

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #3)
> The following fixes the bogus diagnostic:
> 
> diff --git a/gcc/gimple-ssa-warn-restrict.cc
> b/gcc/gimple-ssa-warn-restrict.cc
> index b678e806da3..25c63f99c61 100644
> --- a/gcc/gimple-ssa-warn-restrict.cc
> +++ b/gcc/gimple-ssa-warn-restrict.cc
> @@ -539,13 +559,6 @@ builtin_memref::set_base_and_offset (tree expr)
>           offset_int off = tree_to_shwi (memrefoff);
>           refoff += off;
>         }
> -
> -      if (!integer_zerop (memrefoff))
> -       /* A non-zero offset into an array of struct with flexible array
> -          members implies that the array is empty because there is no
> -          way to initialize such a member when it belongs to an array.
> -          This must be some sort of a bug.  */
> -       refsize = 0;
>      }
>  
>    if (TREE_CODE (ref) == COMPONENT_REF)

It for example regresses gcc.dg/Warray-bounds-46.c which essentially does

struct X { char pad[4]; char ax[]; };

void foo (struct X *p, char *a)
{
  __builtin_strcpy (p[1].ax, a);
}

and the intent was to detect that p[1] implies a zero-size 'ax'.  That's
going to be interesting to distinguish from our case here with just
the MEM_REF - possibly the easiest heuristic is to trigger this only
for incomplete TREE_TYPE of the MEM_REF at least.  That will still
trigger in too many cases, requiring the MEM_REF offset to be a multiple
of the size of the struct will trigger in not enough cases (if there's
also an embedded offset into the array).  But maybe it's a good compromise:

diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
index b678e806da3..734cdd7f5b4 100644
--- a/gcc/gimple-ssa-warn-restrict.cc
+++ b/gcc/gimple-ssa-warn-restrict.cc
@@ -525,7 +525,6 @@ builtin_memref::set_base_and_offset (tree expr)
     {
       tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base,
1));
       extend_offset_range (memrefoff);
-      base = TREE_OPERAND (base, 0);

       if (refoff != HOST_WIDE_INT_MIN
          && TREE_CODE (expr) == COMPONENT_REF)
@@ -538,14 +537,19 @@ builtin_memref::set_base_and_offset (tree expr)
             REFOFF is set to s[1].b - (char*)s.  */
          offset_int off = tree_to_shwi (memrefoff);
          refoff += off;
-       }
-
-      if (!integer_zerop (memrefoff))
-       /* A non-zero offset into an array of struct with flexible array
-          members implies that the array is empty because there is no
-          way to initialize such a member when it belongs to an array.
-          This must be some sort of a bug.  */
-       refsize = 0;
+
+         if (!integer_zerop (memrefoff)
+             && !COMPLETE_TYPE_P (TREE_TYPE (expr))
+             && multiple_of_p (sizetype, memrefoff,
+                               TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
+           /* A non-zero offset into an array of struct with flexible array
+              members implies that the array is empty because there is no
+              way to initialize such a member when it belongs to an array.
+              This must be some sort of a bug.  */
+           refsize = 0;
+       }
+
+      base = TREE_OPERAND (base, 0);
     }

   if (TREE_CODE (ref) == COMPONENT_REF)

Reply via email to