Hi Martin,

[Looks like Linaro TCWG's CI finally works!]

It appears that bootstrap_debug on 32-bit ARM (or, likely, any 32-bit 
architecture) exposes a potential problem in gcc/tree.h.  Could you take a look 
at that?

Let us know if it appears specific to 32-bit ARM and we'll investigate on our 
side.

Regads,

--
Maxim Kuvyrkov
https://www.linaro.org




> On Jul 11, 2021, at 1:31 PM, ci_not...@linaro.org wrote:
> 
> Successfully identified regression in *gcc* in CI configuration 
> tcwg_gnu/gnu-master-arm-bootstrap_debug.  So far, this commit has regressed 
> CI configurations:
> - tcwg_gnu/gnu-master-arm-bootstrap_debug
> 
> Culprit:
> <cut>
> commit a110855667782dac7b674d3e328b253b3b3c919b
> Author: Martin Sebor <mse...@redhat.com>
> Date:   Wed Jul 7 14:05:25 2021 -0600
> 
>    Correct handling of variable offset minus constant in -Warray-bounds 
> [PR100137]
> 
>    Resolves:
>    PR tree-optimization/100137 - -Warray-bounds false positive on varying 
> offset plus negative
>    PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
>    PR tree-optimization/97027 - missing warning on buffer overflow storing a 
> larger scalar into a smaller array
> 
>    gcc/ChangeLog:
> 
>            PR tree-optimization/100137
>            PR tree-optimization/99121
>            PR tree-optimization/97027
>            * builtins.c (access_ref::access_ref): Also set offmax.
>            (access_ref::offset_in_range): Define new function.
>            (access_ref::add_offset): Set offmax.
>            (access_ref::inform_access): Handle access_none.
>            (handle_mem_ref): Clear ostype.
>            (compute_objsize_r): Handle ASSERT_EXPR.
>            * builtins.h (struct access_ref): Add offmax member.
>            * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use
>            compute_objsize() and simplify.
> 
>    gcc/testsuite/ChangeLog:
> 
>            PR tree-optimization/100137
>            PR tree-optimization/99121
>            PR tree-optimization/97027
>            * c-c++-common/Warray-bounds-3.c: Remove xfail
>            * c-c++-common/Warray-bounds-4.c: Add an expected warning.
>            * c-c++-common/Warray-bounds-9.c: New test.
>            * c-c++-common/Warray-bounds-10.c: New test.
>            * g++.dg/asan/asan_test.C: Suppress expected warnings.
>            * g++.dg/pr95768.C: Same.
>            * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages.
>            * g++.dg/warn/Warray-bounds-11.C: Same.
>            * g++.dg/warn/Warray-bounds-12.C: Same.
>            * g++.dg/warn/Warray-bounds-13.C: Same.
>            * g++.dg/warn/Warray-bounds-17.C: Same.
>            * g++.dg/warn/Warray-bounds-20.C: Same.
>            * gcc.dg/Warray-bounds-29.c: Same.
>            * gcc.dg/Warray-bounds-30.c: Add xfail.
>            * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages.
>            * gcc.dg/Warray-bounds-32.c: Same.
>            * gcc.dg/Warray-bounds-52.c: Same.
>            * gcc.dg/Warray-bounds-53.c: Same.
>            * gcc.dg/Warray-bounds-58.c: Remove xfail.
>            * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages.
>            * gcc.dg/Warray-bounds-66.c: Same.
>            * gcc.dg/Warray-bounds-69.c: Same.
>            * gcc.dg/Wstringop-overflow-34.c: Same.
>            * gcc.dg/Wstringop-overflow-47.c: Same.
>            * gcc.dg/Wstringop-overflow-61.c: Same.
>            * gcc.dg/Warray-bounds-77.c: New test.
>            * gcc.dg/Warray-bounds-78.c: New test.
>            * gcc.dg/Warray-bounds-79.c: New test.
> </cut>
> 
> Results regressed to (for first_bad == 
> a110855667782dac7b674d3e328b253b3b3c919b)
> # reset_artifacts:
> -10
> # true:
> 0
> # First few build errors in logs:
> # 00:05:59 make[3]: [armv8l-unknown-linux-gnueabihf/bits/largefile-config.h] 
> Error 1 (ignored)
> # 00:11:36 
> /home/tcwg-buildslave/workspace/tcwg_gnu_0/abe/snapshots/gcc.git~master/gcc/tree.h:1089:58:
>  error: array subscript -1 is outside array bounds of ‘cpp_hashnode 
> [89478485]’ [-Werror=array-bounds]
> # 00:11:37 
> /home/tcwg-buildslave/workspace/tcwg_gnu_0/abe/snapshots/gcc.git~master/gcc/tree.h:1089:58:
>  error: array subscript -1 is outside array bounds of ‘cpp_hashnode 
> [89478485]’ [-Werror=array-bounds]
> # 00:11:37 
> /home/tcwg-buildslave/workspace/tcwg_gnu_0/abe/snapshots/gcc.git~master/gcc/tree.h:1089:58:
>  error: array subscript -1 is outside array bounds of ‘cpp_hashnode 
> [89478485]’ [-Werror=array-bounds]
> # 00:12:06 make[3]: *** [cp/module.o] Error 1
> # 00:17:43 make[2]: *** [all-stage2-gcc] Error 2
> # 00:17:43 make[1]: *** [stage2-bubble] Error 2
> # 00:17:43 make: *** [all] Error 2
> 
> from (for last_good == 6278065af07634278ba30029d92a82b089969baa)
> # reset_artifacts:
> -10
> # true:
> 0
> # build_abe bootstrap_debug:
> 1
> 
> Artifacts of last_good build: 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/build-6278065af07634278ba30029d92a82b089969baa/
> Artifacts of first_bad build: 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/build-a110855667782dac7b674d3e328b253b3b3c919b/
> Build top page/logs: 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/
> 
> Configuration details:
> 
> 
> Reproduce builds:
> <cut>
> mkdir investigate-gcc-a110855667782dac7b674d3e328b253b3b3c919b
> cd investigate-gcc-a110855667782dac7b674d3e328b253b3b3c919b
> 
> git clone https://git.linaro.org/toolchain/jenkins-scripts
> 
> mkdir -p artifacts/manifests
> curl -o artifacts/manifests/build-baseline.sh 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/manifests/build-baseline.sh
>  --fail
> curl -o artifacts/manifests/build-parameters.sh 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/manifests/build-parameters.sh
>  --fail
> curl -o artifacts/test.sh 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/test.sh
>  --fail
> chmod +x artifacts/test.sh
> 
> # Reproduce the baseline build (build all pre-requisites)
> ./jenkins-scripts/tcwg_gnu-build.sh @@ artifacts/manifests/build-baseline.sh
> 
> cd gcc
> 
> # Reproduce first_bad build
> git checkout --detach a110855667782dac7b674d3e328b253b3b3c919b
> ../artifacts/test.sh
> 
> # Reproduce last_good build
> git checkout --detach 6278065af07634278ba30029d92a82b089969baa
> ../artifacts/test.sh
> 
> cd ..
> </cut>
> 
> History of pending regressions and results: 
> https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/ci/tcwg_gnu/gnu-master-arm-bootstrap_debug
> 
> Artifacts: 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/artifact/artifacts/
> Build log: 
> https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-bootstrap_debug/13/consoleText
> 
> Full commit (up to 1000 lines):
> <cut>
> commit a110855667782dac7b674d3e328b253b3b3c919b
> Author: Martin Sebor <mse...@redhat.com>
> Date:   Wed Jul 7 14:05:25 2021 -0600
> 
>    Correct handling of variable offset minus constant in -Warray-bounds 
> [PR100137]
> 
>    Resolves:
>    PR tree-optimization/100137 - -Warray-bounds false positive on varying 
> offset plus negative
>    PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
>    PR tree-optimization/97027 - missing warning on buffer overflow storing a 
> larger scalar into a smaller array
> 
>    gcc/ChangeLog:
> 
>            PR tree-optimization/100137
>            PR tree-optimization/99121
>            PR tree-optimization/97027
>            * builtins.c (access_ref::access_ref): Also set offmax.
>            (access_ref::offset_in_range): Define new function.
>            (access_ref::add_offset): Set offmax.
>            (access_ref::inform_access): Handle access_none.
>            (handle_mem_ref): Clear ostype.
>            (compute_objsize_r): Handle ASSERT_EXPR.
>            * builtins.h (struct access_ref): Add offmax member.
>            * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use
>            compute_objsize() and simplify.
> 
>    gcc/testsuite/ChangeLog:
> 
>            PR tree-optimization/100137
>            PR tree-optimization/99121
>            PR tree-optimization/97027
>            * c-c++-common/Warray-bounds-3.c: Remove xfail
>            * c-c++-common/Warray-bounds-4.c: Add an expected warning.
>            * c-c++-common/Warray-bounds-9.c: New test.
>            * c-c++-common/Warray-bounds-10.c: New test.
>            * g++.dg/asan/asan_test.C: Suppress expected warnings.
>            * g++.dg/pr95768.C: Same.
>            * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages.
>            * g++.dg/warn/Warray-bounds-11.C: Same.
>            * g++.dg/warn/Warray-bounds-12.C: Same.
>            * g++.dg/warn/Warray-bounds-13.C: Same.
>            * g++.dg/warn/Warray-bounds-17.C: Same.
>            * g++.dg/warn/Warray-bounds-20.C: Same.
>            * gcc.dg/Warray-bounds-29.c: Same.
>            * gcc.dg/Warray-bounds-30.c: Add xfail.
>            * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages.
>            * gcc.dg/Warray-bounds-32.c: Same.
>            * gcc.dg/Warray-bounds-52.c: Same.
>            * gcc.dg/Warray-bounds-53.c: Same.
>            * gcc.dg/Warray-bounds-58.c: Remove xfail.
>            * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages.
>            * gcc.dg/Warray-bounds-66.c: Same.
>            * gcc.dg/Warray-bounds-69.c: Same.
>            * gcc.dg/Wstringop-overflow-34.c: Same.
>            * gcc.dg/Wstringop-overflow-47.c: Same.
>            * gcc.dg/Wstringop-overflow-61.c: Same.
>            * gcc.dg/Warray-bounds-77.c: New test.
>            * gcc.dg/Warray-bounds-78.c: New test.
>            * gcc.dg/Warray-bounds-79.c: New test.
> ---
> gcc/builtins.c                                |  69 +++++-
> gcc/builtins.h                                |   5 +
> gcc/gimple-array-bounds.cc                    | 336 ++++----------------------
> gcc/testsuite/c-c++-common/Warray-bounds-10.c | 114 +++++++++
> gcc/testsuite/c-c++-common/Warray-bounds-3.c  |   4 +-
> gcc/testsuite/c-c++-common/Warray-bounds-4.c  |  12 +-
> gcc/testsuite/c-c++-common/Warray-bounds-9.c  | 144 +++++++++++
> gcc/testsuite/g++.dg/asan/asan_test.C         |   2 +-
> gcc/testsuite/g++.dg/pr95768.C                |   2 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-10.C  |   4 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-11.C  |   4 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-12.C  |   4 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-13.C  |   4 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-17.C  |   2 +-
> gcc/testsuite/g++.dg/warn/Warray-bounds-20.C  |   8 +-
> gcc/testsuite/gcc.dg/Warray-bounds-29.c       |  22 +-
> gcc/testsuite/gcc.dg/Warray-bounds-30.c       |   2 +-
> gcc/testsuite/gcc.dg/Warray-bounds-31.c       |   8 +-
> gcc/testsuite/gcc.dg/Warray-bounds-32.c       |  26 +-
> gcc/testsuite/gcc.dg/Warray-bounds-52.c       |   6 +-
> gcc/testsuite/gcc.dg/Warray-bounds-53.c       |   6 +-
> gcc/testsuite/gcc.dg/Warray-bounds-58.c       |   2 +-
> gcc/testsuite/gcc.dg/Warray-bounds-63.c       |   6 +-
> gcc/testsuite/gcc.dg/Warray-bounds-66.c       |  12 +-
> gcc/testsuite/gcc.dg/Warray-bounds-69.c       |   2 +-
> gcc/testsuite/gcc.dg/Warray-bounds-77.c       | 135 +++++++++++
> gcc/testsuite/gcc.dg/Warray-bounds-78.c       | 109 +++++++++
> gcc/testsuite/gcc.dg/Warray-bounds-79.c       | 112 +++++++++
> gcc/testsuite/gcc.dg/Wstringop-overflow-34.c  |   8 +-
> gcc/testsuite/gcc.dg/Wstringop-overflow-47.c  |  14 +-
> gcc/testsuite/gcc.dg/Wstringop-overflow-61.c  |   4 +-
> 31 files changed, 817 insertions(+), 371 deletions(-)
> 
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index e52fe4291c8..39ab139b7e1 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -206,6 +206,7 @@ access_ref::access_ref (tree bound /* = NULL_TREE */,
> {
>   /* Set to valid.  */
>   offrng[0] = offrng[1] = 0;
> +  offmax[0] = offmax[1] = 0;
>   /* Invalidate.   */
>   sizrng[0] = sizrng[1] = -1;
> 
> @@ -457,6 +458,21 @@ access_ref::size_remaining (offset_int *pmin /* = NULL 
> */) const
>   return sizrng[1] - or0;
> }
> 
> +/* Return true if the offset and object size are in range for SIZE.  */
> +
> +bool
> +access_ref::offset_in_range (const offset_int &size) const
> +{
> +  if (size_remaining () < size)
> +    return false;
> +
> +  if (base0)
> +    return offmax[0] >= 0 && offmax[1] <= sizrng[1];
> +
> +  offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
> +  return offmax[0] > -maxoff && offmax[1] < maxoff;
> +}
> +
> /* Add the range [MIN, MAX] to the offset range.  For known objects (with
>    zero-based offsets) at least one of whose offset's bounds is in range,
>    constrain the other (or both) to the bounds of the object (i.e., zero
> @@ -493,6 +509,8 @@ void access_ref::add_offset (const offset_int &min, const 
> offset_int &max)
>       if (max >= 0)
>       {
>         offrng[0] = 0;
> +       if (offmax[0] > 0)
> +         offmax[0] = 0;
>         return;
>       }
> 
> @@ -509,6 +527,12 @@ void access_ref::add_offset (const offset_int &min, 
> const offset_int &max)
>       offrng[0] = 0;
>     }
> 
> +  /* Set the minimum and maximmum computed so far. */
> +  if (offrng[1] < 0 && offrng[1] < offmax[0])
> +    offmax[0] = offrng[1];
> +  if (offrng[0] > 0 && offrng[0] > offmax[1])
> +    offmax[1] = offrng[0];
> +
>   if (!base0)
>     return;
> 
> @@ -4571,23 +4595,46 @@ access_ref::inform_access (access_mode mode) const
>       return;
>     }
> 
> +  if (mode == access_read_only)
> +    {
> +      if (allocfn == NULL_TREE)
> +     {
> +       if (*offstr)
> +         inform (loc, "at offset %s into source object %qE of size %s",
> +                 offstr, ref, sizestr);
> +       else
> +         inform (loc, "source object %qE of size %s", ref, sizestr);
> +
> +       return;
> +     }
> +
> +      if (*offstr)
> +     inform (loc,
> +             "at offset %s into source object of size %s allocated by %qE",
> +             offstr, sizestr, allocfn);
> +      else
> +     inform (loc, "source object of size %s allocated by %qE",
> +             sizestr, allocfn);
> +      return;
> +    }
> +
>   if (allocfn == NULL_TREE)
>     {
>       if (*offstr)
> -     inform (loc, "at offset %s into source object %qE of size %s",
> +     inform (loc, "at offset %s into object %qE of size %s",
>               offstr, ref, sizestr);
>       else
> -     inform (loc, "source object %qE of size %s", ref, sizestr);
> +     inform (loc, "object %qE of size %s", ref, sizestr);
> 
>       return;
>     }
> 
>   if (*offstr)
>     inform (loc,
> -         "at offset %s into source object of size %s allocated by %qE",
> +         "at offset %s into object of size %s allocated by %qE",
>           offstr, sizestr, allocfn);
>   else
> -    inform (loc, "source object of size %s allocated by %qE",
> +    inform (loc, "object of size %s allocated by %qE",
>           sizestr, allocfn);
> }
> 
> @@ -5433,16 +5480,16 @@ handle_mem_ref (tree mref, int ostype, access_ref 
> *pref,
> 
>   if (VECTOR_TYPE_P (TREE_TYPE (mref)))
>     {
> -      /* Hack: Give up for MEM_REFs of vector types; those may be
> -      synthesized from multiple assignments to consecutive data
> -      members (see PR 93200 and 96963).
> +      /* Hack: Handle MEM_REFs of vector types as those to complete
> +      objects; those may be synthesized from multiple assignments
> +      to consecutive data members (see PR 93200 and 96963).
>        FIXME: Vectorized assignments should only be present after
>        vectorization so this hack is only necessary after it has
>        run and could be avoided in calls from prior passes (e.g.,
>        tree-ssa-strlen.c).
>        FIXME: Deal with this more generally, e.g., by marking up
>        such MEM_REFs at the time they're created.  */
> -      return false;
> +      ostype = 0;
>     }
> 
>   tree mrefop = TREE_OPERAND (mref, 0);
> @@ -5796,6 +5843,12 @@ compute_objsize_r (tree ptr, int ostype, access_ref 
> *pref,
> 
>       tree rhs = gimple_assign_rhs1 (stmt);
> 
> +      if (code == ASSERT_EXPR)
> +     {
> +       rhs = TREE_OPERAND (rhs, 0);
> +       return compute_objsize_r (rhs, ostype, pref, snlim, qry);
> +     }
> +
>       if (code == POINTER_PLUS_EXPR
>         && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE)
>       {
> diff --git a/gcc/builtins.h b/gcc/builtins.h
> index e71f40c300a..a64ece3f1cd 100644
> --- a/gcc/builtins.h
> +++ b/gcc/builtins.h
> @@ -222,6 +222,9 @@ struct access_ref
>      argument to the minimum.  */
>   offset_int size_remaining (offset_int * = NULL) const;
> 
> +/* Return true if the offset and object size are in range for SIZE.  */
> +  bool offset_in_range (const offset_int &) const;
> +
>   /* Return true if *THIS is an access to a declared object.  */
>   bool ref_declared () const
>   {
> @@ -261,6 +264,8 @@ struct access_ref
>   /* Range of byte offsets into and sizes of the object(s).  */
>   offset_int offrng[2];
>   offset_int sizrng[2];
> +  /* The minimum and maximum offset computed.  */
> +  offset_int offmax[2];
>   /* Range of the bound of the access: denotes that the access
>      is at least BNDRNG[0] bytes but no more than BNDRNG[1].
>      For string functions the size of the actual access is
> diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
> index 13f08685f8f..83b8db9755e 100644
> --- a/gcc/gimple-array-bounds.cc
> +++ b/gcc/gimple-array-bounds.cc
> @@ -414,269 +414,72 @@ array_bounds_checker::check_mem_ref (location_t 
> location, tree ref,
>   if (warning_suppressed_p (ref, OPT_Warray_bounds))
>     return false;
> 
> -  tree arg = TREE_OPERAND (ref, 0);
> -  /* The constant and variable offset of the reference.  */
> -  tree cstoff = TREE_OPERAND (ref, 1);
> -  tree varoff = NULL_TREE;
> -
> -  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
> -
> -  /* The zero-based array or string constant bounds in bytes.  Initially
> -     set to [-MAXOBJSIZE - 1, MAXOBJSIZE]  until a tighter bound is
> -     determined.  */
> -  offset_int arrbounds[2] = { -maxobjsize - 1, maxobjsize };
> -
> -  /* The minimum and maximum intermediate offset.  For a reference
> -     to be valid, not only does the final offset/subscript must be
> -     in bounds but all intermediate offsets should be as well.
> -     GCC may be able to deal gracefully with such out-of-bounds
> -     offsets so the checking is only enabled at -Warray-bounds=2
> -     where it may help detect bugs in uses of the intermediate
> -     offsets that could otherwise not be detectable.  */
> -  offset_int ioff = wi::to_offset (fold_convert (ptrdiff_type_node, cstoff));
> -  offset_int extrema[2] = { 0, wi::abs (ioff) };
> -
> -  /* The range of the byte offset into the reference.  */
> -  offset_int offrange[2] = { 0, 0 };
> -
>   /* The statement used to allocate the array or null.  */
>   gimple *alloc_stmt = NULL;
>   /* For an allocation statement, the low bound of the size range.  */
>   offset_int minbound = 0;
> +  /* The type and size of the access.  */
> +  tree axstype = TREE_TYPE (ref);
> +  offset_int axssize = 0;
> +  if (TREE_CODE (axstype) != UNION_TYPE)
> +    if (tree access_size = TYPE_SIZE_UNIT (axstype))
> +      if (TREE_CODE (access_size) == INTEGER_CST)
> +     axssize = wi::to_offset (access_size);
> 
> -  /* Determine the offsets and increment OFFRANGE for the bounds of each.
> -     The loop computes the range of the final offset for expressions such
> -     as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in
> -     some range.  */
> -  const unsigned limit = param_ssa_name_def_chain_limit;
> -  for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n)
> -    {
> -      gimple *def = SSA_NAME_DEF_STMT (arg);
> -      if (is_gimple_call (def))
> -     {
> -       /* Determine the byte size of the array from an allocation call.  */
> -       wide_int sizrng[2];
> -       if (gimple_call_alloc_size (def, sizrng))
> -         {
> -           arrbounds[0] = 0;
> -           arrbounds[1] = offset_int::from (sizrng[1], UNSIGNED);
> -           minbound = offset_int::from (sizrng[0], UNSIGNED);
> -           alloc_stmt = def;
> -         }
> -       break;
> -     }
> -
> -      if (gimple_nop_p (def))
> -     {
> -       /* For a function argument try to determine the byte size
> -          of the array from the current function declaratation
> -          (e.g., attribute access or related).  */
> -       wide_int wr[2];
> -       tree ref = gimple_parm_array_size (arg, wr);
> -       if (!ref)
> -         break;
> -       arrbounds[0] = offset_int::from (wr[0], UNSIGNED);
> -       arrbounds[1] = offset_int::from (wr[1], UNSIGNED);
> -       arg = ref;
> -       break;
> -     }
> -
> -      if (!is_gimple_assign (def))
> -     break;
> -
> -      tree_code code = gimple_assign_rhs_code (def);
> -      if (code == POINTER_PLUS_EXPR)
> -     {
> -       arg = gimple_assign_rhs1 (def);
> -       varoff = gimple_assign_rhs2 (def);
> -     }
> -      else if (code == ASSERT_EXPR)
> -     {
> -       arg = TREE_OPERAND (gimple_assign_rhs1 (def), 0);
> -       continue;
> -     }
> -      else
> -     return false;
> -
> -      /* VAROFF should always be a SSA_NAME here (and not even
> -      INTEGER_CST) but there's no point in taking chances.  */
> -      if (TREE_CODE (varoff) != SSA_NAME)
> -     break;
> -
> -      const value_range* const vr = get_value_range (varoff);
> -      if (!vr || vr->undefined_p () || vr->varying_p ())
> -     break;
> -
> -      if (!vr->constant_p ())
> -     break;
> -
> -      if (vr->kind () == VR_RANGE)
> -     {
> -       offset_int min
> -         = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ()));
> -       offset_int max
> -         = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ()));
> -       if (min < max)
> -         {
> -           offrange[0] += min;
> -           offrange[1] += max;
> -         }
> -       else
> -         {
> -           /* When MIN >= MAX, the offset is effectively in a union
> -              of two ranges: [-MAXOBJSIZE -1, MAX] and [MIN, MAXOBJSIZE].
> -              Since there is no way to represent such a range across
> -              additions, conservatively add [-MAXOBJSIZE -1, MAXOBJSIZE]
> -              to OFFRANGE.  */
> -           offrange[0] += arrbounds[0];
> -           offrange[1] += arrbounds[1];
> -         }
> -     }
> -      else
> -     {
> -       /* For an anti-range, analogously to the above, conservatively
> -          add [-MAXOBJSIZE -1, MAXOBJSIZE] to OFFRANGE.  */
> -       offrange[0] += arrbounds[0];
> -       offrange[1] += arrbounds[1];
> -     }
> -
> -      /* Keep track of the minimum and maximum offset.  */
> -      if (offrange[1] < 0 && offrange[1] < extrema[0])
> -     extrema[0] = offrange[1];
> -      if (offrange[0] > 0 && offrange[0] > extrema[1])
> -     extrema[1] = offrange[0];
> -
> -      if (offrange[0] < arrbounds[0])
> -     offrange[0] = arrbounds[0];
> -
> -      if (offrange[1] > arrbounds[1])
> -     offrange[1] = arrbounds[1];
> -    }
> +  access_ref aref;
> +  if (!compute_objsize (ref, 1, &aref, ranges))
> +    return false;
> 
> -  tree reftype = NULL_TREE;
> -  offset_int eltsize = -1;
> -  if (arrbounds[0] >= 0)
> -    {
> -      /* The byte size of the array has already been determined above
> -      based on a pointer ARG.  Set ELTSIZE to the size of the type
> -      it points to and REFTYPE to the array with the size, rounded
> -      down as necessary.  */
> -      reftype = TREE_TYPE (TREE_TYPE (arg));
> -      if (TREE_CODE (reftype) == ARRAY_TYPE)
> -     reftype = TREE_TYPE (reftype);
> -      if (tree refsize = TYPE_SIZE_UNIT (reftype))
> -     if (TREE_CODE (refsize) == INTEGER_CST)
> -       eltsize = wi::to_offset (refsize);
> -
> -      if (eltsize < 0)
> -     return false;
> +  if (aref.offset_in_range (axssize))
> +    return false;
> 
> -      offset_int nelts = arrbounds[1] / eltsize;
> -      reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
> -    }
> -  else if (TREE_CODE (arg) == ADDR_EXPR)
> +  if (TREE_CODE (aref.ref) == SSA_NAME)
>     {
> -      arg = TREE_OPERAND (arg, 0);
> -      if (TREE_CODE (arg) != STRING_CST
> -       && TREE_CODE (arg) != PARM_DECL
> -       && TREE_CODE (arg) != VAR_DECL)
> -     return false;
> -
> -      /* The type of the object being referred to.  It can be an array,
> -      string literal, or a non-array type when the MEM_REF represents
> -      a reference/subscript via a pointer to an object that is not
> -      an element of an array.  Incomplete types are excluded as well
> -      because their size is not known.  */
> -      reftype = TREE_TYPE (arg);
> -      if (POINTER_TYPE_P (reftype)
> -       || !COMPLETE_TYPE_P (reftype)
> -       || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST)
> -     return false;
> -
> -      /* Except in declared objects, references to trailing array members
> -      of structs and union objects are excluded because MEM_REF doesn't
> -      make it possible to identify the member where the reference
> -      originated.  */
> -      if (RECORD_OR_UNION_TYPE_P (reftype)
> -       && (!VAR_P (arg)
> -           || (DECL_EXTERNAL (arg) && array_at_struct_end_p (ref))))
> -     return false;
> -
> -      /* FIXME: Should this be 1 for Fortran?  */
> -      arrbounds[0] = 0;
> -
> -      if (TREE_CODE (reftype) == ARRAY_TYPE)
> -     {
> -       /* Set to the size of the array element (and adjust below).  */
> -       eltsize = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (reftype)));
> -       /* Use log2 of size to convert the array byte size in to its
> -          upper bound in elements.  */
> -       const offset_int eltsizelog2 = wi::floor_log2 (eltsize);
> -       if (tree dom = TYPE_DOMAIN (reftype))
> -         {
> -           tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) };
> -           if (TREE_CODE (arg) == COMPONENT_REF)
> -             {
> -               offset_int size = maxobjsize;
> -               if (tree fldsize = component_ref_size (arg))
> -                 size = wi::to_offset (fldsize);
> -               arrbounds[1] = wi::lrshift (size, eltsizelog2);
> -             }
> -           else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1])
> -             arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
> -           else
> -             arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset 
> (bnds[0])
> -                             + 1) * eltsize;
> -         }
> -       else
> -         arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
> -
> -       /* Determine a tighter bound of the non-array element type.  */
> -       tree eltype = TREE_TYPE (reftype);
> -       while (TREE_CODE (eltype) == ARRAY_TYPE)
> -         eltype = TREE_TYPE (eltype);
> -       eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype));
> -     }
> -      else
> +      gimple *def = SSA_NAME_DEF_STMT (aref.ref);
> +      if (is_gimple_call (def))
>       {
> -       eltsize = 1;
> -       tree size = TYPE_SIZE_UNIT (reftype);
> -       if (VAR_P (arg))
> -         if (tree initsize = DECL_SIZE_UNIT (arg))
> -           if (tree_int_cst_lt (size, initsize))
> -             size = initsize;
> -
> -       arrbounds[1] = wi::to_offset (size);
> +       /* Save the allocation call and the low bound on the size.  */
> +       alloc_stmt = def;
> +       minbound = aref.sizrng[0];
>       }
>     }
> -  else
> -    return false;
> -
> -  offrange[0] += ioff;
> -  offrange[1] += ioff;
> +                     
> +  /* The range of the byte offset into the reference.  Adjusted below.  */
> +  offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };
> +
> +  /* The type of the referenced object.  */
> +  tree reftype = TREE_TYPE (aref.ref);
> +  /* The size of the referenced array element.  */
> +  offset_int eltsize = 1;
> +  /* The byte size of the array has already been determined above
> +     based on a pointer ARG.  Set ELTSIZE to the size of the type
> +     it points to and REFTYPE to the array with the size, rounded
> +     down as necessary.  */
> +  if (POINTER_TYPE_P (reftype))
> +    reftype = TREE_TYPE (reftype);
> +  if (TREE_CODE (reftype) == ARRAY_TYPE)
> +    reftype = TREE_TYPE (reftype);
> +  if (tree refsize = TYPE_SIZE_UNIT (reftype))
> +    if (TREE_CODE (refsize) == INTEGER_CST)
> +      eltsize = wi::to_offset (refsize);
> +
> +  const offset_int nelts = aref.sizrng[1] / eltsize;
> +  reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
> 
>   /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
>      is set (when taking the address of the one-past-last element
>      of an array) but always use the stricter bound in diagnostics. */
> -  offset_int ubound = arrbounds[1];
> +  offset_int ubound = aref.sizrng[1];
>   if (ignore_off_by_one)
>     ubound += eltsize;
> 
> -  bool warned = false;
>   /* Set if the lower bound of the subscript is out of bounds.  */
> -  const bool lboob = (arrbounds[0] == arrbounds[1]
> +  const bool lboob = (aref.sizrng[1] == 0
>                     || offrange[0] >= ubound
> -                   || offrange[1] < arrbounds[0]);
> +                   || offrange[1] < 0);
>   /* Set if only the upper bound of the subscript is out of bounds.
>      This can happen when using a bigger type to index into an array
>      of a smaller type, as is common with unsigned char.  */
> -  tree axstype = TREE_TYPE (ref);
> -  offset_int axssize = 0;
> -  if (TREE_CODE (axstype) != UNION_TYPE)
> -    if (tree access_size = TYPE_SIZE_UNIT (axstype))
> -      if (TREE_CODE (access_size) == INTEGER_CST)
> -     axssize = wi::to_offset (access_size);
> -
>   const bool uboob = !lboob && offrange[0] + axssize > ubound;
>   if (lboob || uboob)
>     {
> @@ -689,9 +492,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
>        to compute the index to print in the diagnostic; arrays
>        in MEM_REF don't mean anything.  A type with no size like
>        void is as good as having a size of 1.  */
> -      tree type = TREE_TYPE (ref);
> -      while (TREE_CODE (type) == ARRAY_TYPE)
> -     type = TREE_TYPE (type);
> +      tree type = strip_array_types (TREE_TYPE (ref));
>       if (tree size = TYPE_SIZE_UNIT (type))
>       {
>         offrange[0] = offrange[0] / wi::to_offset (size);
> @@ -699,6 +500,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
>       }
>     }
> 
> +  bool warned = false;
>   if (lboob)
>     {
>       if (offrange[0] == offrange[1])
> @@ -720,7 +522,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
>       /* If the memory was dynamically allocated refer to it as if
>          it were an untyped array of bytes.  */
>       backtype = build_array_type_nelts (unsigned_char_type_node,
> -                                        arrbounds[1].to_uhwi ());
> +                                        aref.sizrng[1].to_uhwi ());
> 
>       warned = warning_at (location, OPT_Warray_bounds,
>                          "array subscript %<%T[%wi]%> is partly "
> @@ -730,46 +532,8 @@ array_bounds_checker::check_mem_ref (location_t 
> location, tree ref,
> 
>   if (warned)
>     {
> -      if (DECL_P (arg))
> -     inform (DECL_SOURCE_LOCATION (arg), "while referencing %qD", arg);
> -      else if (alloc_stmt)
> -     {
> -       location_t loc = gimple_location (alloc_stmt);
> -       if (gimple_call_builtin_p (alloc_stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
> -         {
> -           if (minbound == arrbounds[1])
> -             inform (loc, "referencing a variable length array "
> -                     "of size %wu", minbound.to_uhwi ());
> -           else
> -             inform (loc, "referencing a variable length array "
> -                     "of size between %wu and %wu",
> -                     minbound.to_uhwi (), arrbounds[1].to_uhwi ());
> -         }
> -       else if (tree fndecl = gimple_call_fndecl (alloc_stmt))
> -         {
> -           if (minbound == arrbounds[1])
> -             inform (loc, "referencing an object of size %wu "
> -                     "allocated by %qD",
> -                     minbound.to_uhwi (), fndecl);
> -           else
> -             inform (loc, "referencing an object of size between "
> -                     "%wu and %wu allocated by %qD",
> -                     minbound.to_uhwi (), arrbounds[1].to_uhwi (), fndecl);
> -         }
> -       else
> -         {
> -           tree fntype = gimple_call_fntype (alloc_stmt);
> -           if (minbound == arrbounds[1])
> -             inform (loc, "referencing an object of size %wu "
> -                     "allocated by %qT",
> -                     minbound.to_uhwi (), fntype);
> -           else
> -             inform (loc, "referencing an object of size between "
> -                     "%wu and %wu allocated by %qT",
> -                     minbound.to_uhwi (), arrbounds[1].to_uhwi (), fntype);
> -         }
> -     }
> -
> +      /* TODO: Determine the access from the statement and use it.  */
> +      aref.inform_access (access_none);
>       suppress_warning (ref, OPT_Warray_bounds);
>       return true;
>     }
> @@ -779,9 +543,9 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
> 
>   /* At level 2 check also intermediate offsets.  */
>   int i = 0;
> -  if (extrema[i] < -arrbounds[1] || extrema[i = 1] > ubound)
> +  if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
>     {
> -      HOST_WIDE_INT tmpidx = extrema[i].to_shwi () / eltsize.to_shwi ();
> +      HOST_WIDE_INT tmpidx = aref.offmax[i].to_shwi () / eltsize.to_shwi ();
> 
>       if (warning_at (location, OPT_Warray_bounds,
>                     "intermediate array offset %wi is outside array bounds "
> diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-10.c 
> b/gcc/testsuite/c-c++-common/Warray-bounds-10.c
> new file mode 100644
> index 00000000000..cfe9a383410
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/Warray-bounds-10.c
> @@ -0,0 +1,114 @@
> +/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array
> +   element of empty structs
> +   { dg-do compile }
> +   { dg-options "-O2 -Wall" } */
> +
> +struct S
> +{
> +#if SOME_CONFIG_MACRO
> +  /* Suppose the contents are empty in the development configuration
> +     but non-empty in others.  Out of bounds accesses to elements of
> +     the arrays below should be diagnosed in all configurations,
> +     including when S is empty, even if they are folded away.  */
> +  int member;
> +#endif
> +};
> +
> +extern struct S sa3[3];
> +extern struct S sa2_3[2][3];
> +extern struct S sa3_4_5[3][4][5];
> +
> +void sink (void*);
> +
> +
> +void access_sa3 (struct S s)
> +{
> +  sa3[0] = s;
> +  sa3[1] = s;
> +  sa3[2] = s;
> +  sa3[3] = s;       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +}
> +
> +void access_sa3_ptr (struct S s)
> +{
> +  struct S *p = &sa3[0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[3] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +}
> +
> +void access_sa2_3_ptr (struct S s)
> +{
> +  struct S *p = &sa2_3[0][0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[6] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +}
> +
> +void access_sa3_4_5_ptr (struct S s, int i)
> +{
> +  struct S *p = &sa3_4_5[0][0][0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[60] = s;        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +}
> +
> +
> +void access_vla3 (struct S s, unsigned n)
> +{
> +  struct S vla3[3 < n ? 3 : n];
> +
> +  vla3[0] = s;
> +  vla3[1] = s;
> +  vla3[2] = s;
> +  vla3[3] = s;       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +
> +  sink (vla3);
> +}
> +
> +void access_vla3_ptr (struct S s, unsigned n)
> +{
> +  struct S vla3[3 < n ? 3 : n];
> +  struct S *p = &vla3[0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[3] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +
> +  sink (vla3);
> +}
> +
> +void access_vla2_3_ptr (struct S s, unsigned n)
> +{
> +  struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n];
> +  struct S *p = &vla2_3[0][0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[6] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +
> +  sink (vla2_3);
> +}
> +
> +void access_vla3_4_5_ptr (struct S s, unsigned n)
> +{
> +  struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n];
> +  struct S *p = &vla3_4_5[0][0][0];
> +
> +  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
> +  p[60] = s;        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail 
> *-*-* } }
> +
> +  sink (vla3_4_5);
> +}
> +
> +// { dg-prune-output "empty struct has size 0 in C" }
> diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c 
> b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
> index aae4999ea13..3d7c7687374 100644
> --- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c
> +++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
> @@ -158,7 +158,7 @@ void test_memcpy_overflow (char *d, const char *s, size_t 
> n)
>      but known access size is detected.  This works except with small
>      sizes that are powers of 2 due to bug .  */
>   T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1);
> -  T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2);  /* { dg-warning 
> "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 2 accessing 
> array " "bug " { xfail non_strict_align } } */
> +  T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2);  /* { dg-warning 
> "\\\[-Warray-bounds" } */
>   T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3);  /* { dg-warning 
> "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing 
> array " "memcpy" } */
>   T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5);  /* { dg-warning 
> "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing 
> array " "memcpy" } */
> }
> @@ -178,7 +178,7 @@ void test_memcpy_bounds_memarray_range (void)
> 
>   TM (ma.a5, ma.a5 + i, ma.a5, 1);
>   TM (ma.a5, ma.a5 + i, ma.a5, 3);
> -  TM (ma.a5, ma.a5 + i, ma.a5, 5);
> +  TM (ma.a5, ma.a5 + i, ma.a5, 5);     /* { dg-warning "\\\[-Warray-bounds" 
> } */
>   TM (ma.a5, ma.a5 + i, ma.a5, 7);     /* diagnosed with -Warray-bounds=2 */
> }
> 
> diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-4.c 
> b/gcc/testsuite/c-c++-common/Warray-bounds-4.c
> index 22a23a12651..1f73f11943f 100644
> --- a/gcc/testsuite/c-c++-common/Warray-bounds-4.c
> +++ b/gcc/testsuite/c-c++-common/Warray-bounds-4.c
> @@ -43,7 +43,17 @@ void test_memcpy_bounds_memarray_range (void)
> 
>   TM (ma.a5, ma.a5 + j, ma.a5, 1);
>   TM (ma.a5, ma.a5 + j, ma.a5, 3);
> -  TM (ma.a5, ma.a5 + j, ma.a5, 5);
> +
> +  /* The copy below is invalid for two reasons: 1) it overlaps and 2) it
> +     writes past the end of ma.a5.  The warning is a little cryptic here
> +     because the GIMPLE is:
> +       _4 = &ma.a5 + prephitmp_14;
> +       MEM <unsigned char[5]> [(char * {ref-all})_4]
> +         = MEM <unsigned char[5]> [(char * {ref-all})&ma];
> +     and could be improved.  Just verify that one is issued but not its
> +     full text.  */
> +  TM (ma.a5, ma.a5 + j, ma.a5, 5);        /* { dg-warning 
> "\\\[-Warray-bounds" } */
> +
>   TM (ma.a5, ma.a5 + j, ma.a5, 7);        /* { dg-warning "offset \\\[5, 7] 
> from the object at .ma. is out of the bounds of referenced subobject 
> .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */
>   TM (ma.a5, ma.a5 + j, ma.a5, 9);        /* { dg-warning "offset \\\[5, 9] 
> from the object at .ma. is out of the bounds of referenced subobject 
> .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */
> }
> diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-9.c 
> b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
> new file mode 100644
> index 00000000000..be05775fa91
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
> @@ -0,0 +1,144 @@
> +/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
> +   VLA
> +   { dg-do compile }
> +   { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
> +
> +#define NOIPA __attribute__ ((noipa))
> +
> +void sink (void*, ...);
> +#define T(a, x) sink (a, x)
> +
> +
> +NOIPA void a_0_n (int n)
> +{
> +  int a[0][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_n_0 (int n)
> +{
> +  int a[n][0];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +
> +NOIPA void a_1_n_0 (int n)
> +{
> +  int a[1][n][0];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_1_0_n (int n)
> +{
> +  int a[1][0][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_0_1_n (int n)
> +{
> +  int a[0][1][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_0_n_1 (int n)
> +{
> +  int a[0][n][1];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_n_0_n (int n)
> +{
> +  int a[n][0][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_n_n_0 (int n)
> +{
> +  int a[n][n][0];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_0_n_n (int n)
> +{
> +  int a[0][n][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_0_0_n (int n)
> +{
> +  int a[0][0][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_n_0_0 (int n)
> +{
> +  int a[n][0][0];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
> +  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +NOIPA void a_n_n_n (int n)
> +{
> +  int a[n][n][n];
> +
> +  sink (a);
> +
> +  T (a, ((int *) a)[-1]);     // { dg-warning "\\\[-Warray-bounds" "pr99140" 
> }
> +  T (a, ((int *) a)[0]);
> +  T (a, ((char *) a)[1]);
> +  T (a, ((float *) a)[n]);
> +}
> diff --git a/gcc/testsuite/g++.dg/asan/asan_test.C 
> b/gcc/testsuite/g++.dg/asan/asan_test.C
> index c62568f48ec..49933ab8e4d 100644
> --- a/gcc/testsuite/g++.dg/asan/asan_test.C
> +++ b/gcc/testsuite/g++.dg/asan/asan_test.C
> @@ -2,7 +2,7 @@
> // { dg-skip-if "" { *-*-* } { "*" } { "-O2" } }
> // { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
> // { dg-additional-sources "asan_globals_test-wrapper.cc" }
> -// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Werror 
> -Wno-alloc-size-larger-than -Wno-stringop-overflow -g -DASAN_UAR=0 
> -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 
> -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread" }
> +// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Werror 
> -Wno-alloc-size-larger-than -Wno-array-bounds -Wno-stringop-overflow -g 
> -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 
> -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread" }
> // { dg-additional-options "-ldl" { target { ! *-*-freebsd* } } }
> // { dg-additional-options "-DASAN_NEEDS_SEGV=1" { target { ! arm*-*-* } } }
> // { dg-additional-options "-DASAN_LOW_MEMORY=1 -DASAN_NEEDS_SEGV=0" { target 
> arm*-*-* } }
> diff --git a/gcc/testsuite/g++.dg/pr95768.C b/gcc/testsuite/g++.dg/pr95768.C
> index 5e2c8c44ad0..d34d5133134 100644
> --- a/gcc/testsuite/g++.dg/pr95768.C
> +++ b/gcc/testsuite/g++.dg/pr95768.C
> @@ -1,6 +1,6 @@
> /* PR c++/95768 - pretty-printer ICE on -Wuninitialized with allocated storage
>    { dg-do compile }
> -   { dg-options "-O2 -Wall" } */
> +   { dg-options "-O2 -Wall -Wno-array-bounds" } */
> </cut>

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to