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