On Fri, Aug 15, 2025 at 5:56 PM Qing Zhao <qing.z...@oracle.com> wrote:
>
> Hi,
>
> This is the 9th version of the patch for fixing PR109071.
>
> Major changes compared to v8: (address all Richard's comments)
>
> https://gcc.gnu.org/pipermail/gcc-patches/2025-July/691198.html
>
> 1. Add a -fdiagnostics-show-context alias to -fdiagnostics-show-context=1.
>    -fno-diagnostics-show-context alias to -fno-diagnostics-show-context.
> update doc on this.
> add one more testing case for this.
>
> 2. Major changes in lazy_diagnostic_context_path::make_inner_path:
>
>    * More descriptive comments for the heuristic of the routine;
>    * Several small updates per Richard's suggestions;
>    * Change the 2-level nested loop to one-level loop by only back
>      trace the dominator chain through the CFG and identify single
>      predecessor edges in this dominator chain.
>
> 3. Add a flag in gimple-ssa-warn-restrict.cc for controlling when to free
> the cominance_info.
>
> bootstrapping and regression testing on both x86 and aarch64. No issues.
>
> Okay for trunk?

This is OK with one minor nit - I think the -fdiagnostic-show-context= option
needs a RejectNegative flag.  OK with that added.

Thanks,
Richard.

> thanks a lot.
>
> Qing
>
> ======================================================
> '-fdiagnostics-show-context[=DEPTH]'
> '-fno-diagnostics-show-context'
>      With this option, the compiler might print the interesting control
>      flow chain that guards the basic block of the statement which has
>      the warning.  DEPTH is the maximum depth of the control flow chain.
>      Currently, The list of the impacted warning options includes:
>      '-Warray-bounds', '-Wstringop-overflow', '-Wstringop-overread',
>      '-Wstringop-truncation'.  and '-Wrestrict'.  More warning options
>      might be added to this list in future releases.  The forms
>      '-fdiagnostics-show-context' and '-fno-diagnostics-show-context'
>      are aliases for '-fdiagnostics-show-context=1' and
>      '-fdiagnostics-show-context=0', respectively.
>
> For example:
>
> $ cat t.c
> extern void warn(void);
> static inline void assign(int val, int *regs, int *index)
> {
>   if (*index >= 4)
>     warn();
>   *regs = val;
> }
> struct nums {int vals[4];};
>
> void sparx5_set (int *ptr, struct nums *sg, int index)
> {
>   int *val = &sg->vals[index];
>
>   assign(0,    ptr, &index);
>   assign(*val, ptr, &index);
> }
>
> $ gcc -Wall -O2  -c -o t.o t.c
> t.c: In function ‘sparx5_set’:
> t.c:12:23: warning: array subscript 4 is above array bounds of ‘int[4]’ 
> [-Warray-bounds=]
>    12 |   int *val = &sg->vals[index];
>       |        ~~~~~~~~^~~~~~~
> t.c:8:18: note: while referencing ‘vals’
>     8 | struct nums {int vals[4];};
>       |           ^~~~
>
> In the above, Although the warning is correct in theory, the warning message
> itself is confusing to the end-user since there is information that cannot
> be connected to the source code directly.
>
> It will be a nice improvement to add more information in the warning message
> to report where such index value come from.
>
> With the new option -fdiagnostics-show-context=1, the warning message for
> the above testing case is now:
>
> $ gcc -Wall -O2 -fdiagnostics-show-context=1 -c -o t.o t.c
> t.c: In function ‘sparx5_set’:
> t.c:12:23: warning: array subscript 4 is above array bounds of ‘int[4]’ 
> [-Warray-bounds=]
>    12 |   int *val = &sg->vals[index];
>       |        ~~~~~~~~^~~~~~~
>   ‘sparx5_set’: events 1-2
>     4 |   if (*index >= 4)
>       |      ^
>       |      |
>       |      (1) when the condition is evaluated to true
> ......
>    12 |   int *val = &sg->vals[index];
>       |        ~~~~~~~~~~~~~~~
>       |                |
>       |                (2) warning happens here
> t.c:8:18: note: while referencing ‘vals’
>     8 | struct nums {int vals[4];};
>       |           ^~~~
>
>         PR tree-optimization/109071
>         PR tree-optimization/85788
>         PR tree-optimization/88771
>         PR tree-optimization/106762
>         PR tree-optimization/108770
>         PR tree-optimization/115274
>         PR tree-optimization/117179
>
> gcc/ChangeLog:
>
>         * Makefile.in (OBJS): Add diagnostic-context-rich-location.o.
>         * common.opt (fdiagnostics-show-context): New option.
>         (fdiagnostics-show-context=): New option.
>         * diagnostic-context-rich-location.cc: New file.
>         * diagnostic-context-rich-location.h: New file.
>         * doc/invoke.texi (fdiagnostics-details): Add
>         documentation for the new options.
>         * gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add
>         one new parameter. Use rich location with details for warning_at.
>         (array_bounds_checker::check_array_ref): Use rich location with
>         ditails for warning_at.
>         (array_bounds_checker::check_mem_ref): Add one new parameter.
>         Use rich location with details for warning_at.
>         (array_bounds_checker::check_addr_expr): Use rich location with
>         move_history_diagnostic_path for warning_at.
>         (array_bounds_checker::check_array_bounds): Call check_mem_ref with
>         one more parameter.
>         * gimple-array-bounds.h: Update prototype for check_mem_ref.
>         * gimple-ssa-warn-access.cc (warn_string_no_nul): Use rich location
>         with details for warning_at.
>         (maybe_warn_nonstring_arg): Likewise.
>         (maybe_warn_for_bound): Likewise.
>         (warn_for_access): Likewise.
>         (check_access): Likewise.
>         (pass_waccess::check_strncat): Likewise.
>         (pass_waccess::maybe_check_access_sizes): Likewise.
>         * gimple-ssa-warn-restrict.cc (pass_wrestrict::execute): Calculate
>         dominance info for diagnostics show context.
>         (maybe_diag_overlap): Use rich location with details for warning_at.
>         (maybe_diag_access_bounds): Use rich location with details for
>         warning_at.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/pr109071.c: New test.
>         * gcc.dg/pr109071_1.c: New test.
>         * gcc.dg/pr109071_10.c: New test.
>         * gcc.dg/pr109071_11.c: New test.
>         * gcc.dg/pr109071_12.c: New test.
>         * gcc.dg/pr109071_2.c: New test.
>         * gcc.dg/pr109071_3.c: New test.
>         * gcc.dg/pr109071_4.c: New test.
>         * gcc.dg/pr109071_5.c: New test.
>         * gcc.dg/pr109071_6.c: New test.
>         * gcc.dg/pr109071_7.c: New test.
>         * gcc.dg/pr109071_8.c: New test.
>         * gcc.dg/pr109071_9.c: New test.
>         * gcc.dg/pr117375.c: New test.
> ---
>  gcc/Makefile.in                         |   1 +
>  gcc/common.opt                          |   7 +
>  gcc/diagnostic-context-rich-location.cc | 175 ++++++++++++++++++++++++
>  gcc/diagnostic-context-rich-location.h  |  73 ++++++++++
>  gcc/doc/invoke.texi                     |  19 ++-
>  gcc/gimple-array-bounds.cc              |  38 ++---
>  gcc/gimple-array-bounds.h               |   2 +-
>  gcc/gimple-ssa-warn-access.cc           | 131 ++++++++++--------
>  gcc/gimple-ssa-warn-restrict.cc         |  71 ++++++----
>  gcc/testsuite/gcc.dg/pr109071.c         |  43 ++++++
>  gcc/testsuite/gcc.dg/pr109071_1.c       |  36 +++++
>  gcc/testsuite/gcc.dg/pr109071_10.c      |  85 ++++++++++++
>  gcc/testsuite/gcc.dg/pr109071_11.c      |  89 ++++++++++++
>  gcc/testsuite/gcc.dg/pr109071_12.c      |  44 ++++++
>  gcc/testsuite/gcc.dg/pr109071_2.c       |  50 +++++++
>  gcc/testsuite/gcc.dg/pr109071_3.c       |  42 ++++++
>  gcc/testsuite/gcc.dg/pr109071_4.c       |  41 ++++++
>  gcc/testsuite/gcc.dg/pr109071_5.c       |  33 +++++
>  gcc/testsuite/gcc.dg/pr109071_6.c       |  49 +++++++
>  gcc/testsuite/gcc.dg/pr109071_7.c       |  44 ++++++
>  gcc/testsuite/gcc.dg/pr109071_8.c       |  51 +++++++
>  gcc/testsuite/gcc.dg/pr109071_9.c       |  61 +++++++++
>  gcc/testsuite/gcc.dg/pr117375.c         |  13 ++
>  23 files changed, 1098 insertions(+), 100 deletions(-)
>  create mode 100644 gcc/diagnostic-context-rich-location.cc
>  create mode 100644 gcc/diagnostic-context-rich-location.h
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_1.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_10.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_11.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_12.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_2.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_3.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_4.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_5.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_6.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_7.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_8.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr109071_9.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr117375.c
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index f21d6929874..d2744db843d 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1620,6 +1620,7 @@ OBJS = \
>         mcf.o \
>         mode-switching.o \
>         modulo-sched.o \
> +       diagnostic-context-rich-location.o \
>         multiple_target.o \
>         omp-offload.o \
>         omp-expand.o \
> diff --git a/gcc/common.opt b/gcc/common.opt
> index c58ac135ff7..2ba508e84f8 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -1632,6 +1632,13 @@ fdiagnostics-show-nesting-levels
>  Common Var(flag_diagnostics_show_nesting_levels) Init(0)
>  Show nesting levels as numbers when showing nested diagnostics.
>
> +fdiagnostics-show-context
> +Common Alias(fdiagnostics-show-context=,1,0)
> +
> +fdiagnostics-show-context=
> +Common Joined UInteger Var(flag_diagnostics_show_context) Init(0)
> +Collect and print more context information for diagnostics.
> +
>  fdisable-
>  Common Joined RejectNegative Var(common_deferred_options) Defer
>  -fdisable-[tree|rtl|ipa]-<pass>=range1+range2  Disable an optimization pass.
> diff --git a/gcc/diagnostic-context-rich-location.cc 
> b/gcc/diagnostic-context-rich-location.cc
> new file mode 100644
> index 00000000000..a1eb349c34b
> --- /dev/null
> +++ b/gcc/diagnostic-context-rich-location.cc
> @@ -0,0 +1,175 @@
> +/* A rich_location subclass that lazily populates a diagnostic_path
> +   with diagnostic context events, but only if the path is actually to be
> +   used.
> +
> +   Copyright (C) 2025 Free Software Foundation, Inc.
> +   Contributed by Qing Zhao<qing.z...@oracle.com>
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#define INCLUDE_MEMORY
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "backend.h"
> +#include "tree.h"
> +#include "gimple.h"
> +#include "gimple-iterator.h"
> +#include "cfganal.h"
> +#include "tree-cfg.h"
> +#include "simple-diagnostic-path.h"
> +#include "diagnostic-context-rich-location.h"
> +
> +/* Implemenation of the method make_inner_path of the class
> +   lazy_diagnostic_context_path.  */
> +
> +std::unique_ptr<diagnostics::paths::path>
> +lazy_diagnostic_context_path::make_inner_path () const
> +{
> +  auto path = std::make_unique<simple_diagnostic_path>
> +               (m_logical_loc_mgr,
> +                global_dc->get_reference_printer ());
> +  if (!flag_diagnostics_show_context)
> +    return path;
> +  if (!m_stmt)
> +    return path;
> +
> +  /* For the following more complicated code:
> +  if (i < 10)                          // B2
> +    {
> +      if (is_day)                      // B3
> +       __builtin_printf ("day");       // B4
> +      else
> +       __builtin_printf ("night");     // B5
> +
> +      if (i == -1)                     // B6
> +       {
> +         if (is_dollar)                // B7
> +           __builtin_printf ("dollar");// B8
> +         else
> +           __builtin_printf ("euro");  // B9
> +         a[i] = -1;                    // B10 (warning here)
> +       }
> +      else
> +       a[i] = i;                       // B11
> +    }
> +  else
> +    a[i] = i + 1;                      // B12
> +
> +  it has the following CFG:
> +
> +           B2
> +          / \
> +         V   \
> +        B3    \
> +       / \     \
> +       V   V     \
> +      B4  B5      V
> +       \ /      B12
> +        V
> +        B6
> +       / \
> +       V   V
> +      B7  B11
> +     / \
> +    V   V
> +   B8   B9
> +     \ /
> +      V
> +     B10 (warning here)
> +
> +  If the STMT that has warning is in B10, the interesting conditions for
> +  the diagnostic are:
> +  depth=1: the condition stmt at B6, the edge from B6->B7;
> +  depth=2: the condition stmt at B2, the edge from B2->B3;
> +
> +  In order to get the interesting conditions, the key to the heuristic
> +  is to backtrace the immediate dominator block chain of the current
> +  block B10, such as, B7, then B6, B3, B2.
> +
> +  In this basic block dominator chain, identify the single predecessor
> +  edges, such as B6->B7, and B2->B3.
> +
> +  For each of the single predecessor edge, the interesting condition is
> +  embedded in the single predecessor block, and the TRUE/FALSE of this
> +  condition is embedded in the edge.
> +
> +  FIXME: We currently only handle GIMPLE_COND, might extend to GIMPLE_SWITCH
> +  later.  */
> +
> +  basic_block cur_bb = gimple_bb (m_stmt);
> +  if (!cur_bb)
> +    return path;
> +  basic_block cond_bb = NULL;
> +  int depth = 0;
> +  do
> +    {
> +      /* Step 1. locate the immediate dominator of cur_bb.  */
> +      if (dom_info_available_p (cfun, CDI_DOMINATORS))
> +       cond_bb = get_immediate_dominator (CDI_DOMINATORS, cur_bb);
> +
> +      if (!cond_bb)
> +       return path;
> +
> +      /* Step 2. identify the single predecessor edge to locate the
> +        conditional statement.  */
> +      if (single_pred_p (cur_bb))
> +       {
> +         gcc_assert (cond_bb == single_pred (cur_bb));
> +         gimple *cond_stmt = NULL;
> +         gimple_stmt_iterator gsi = gsi_last_bb (cond_bb);
> +
> +         /* Currently, we only hanlde GIMPLE_COND.
> +            FIXME, will handle GIMPLE_SWITCH and other ctrl stmt later.  */
> +         if (gsi_stmt (gsi) && stmt_ends_bb_p (gsi_stmt (gsi)))
> +           if (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND)
> +             cond_stmt = gsi_stmt (gsi);
> +
> +         /* If there is no conditional statement in the cond_bb, continue.  
> */
> +         if (!cond_stmt)
> +           {
> +             cur_bb = cond_bb;
> +             continue;
> +           }
> +
> +         /* if there is no location information for the cond_stmt, we should
> +            not add this event to confuse end user.  */
> +         if (cond_stmt
> +             && LOCATION_LOCUS (gimple_location (cond_stmt))
> +                != UNKNOWN_LOCATION)
> +           {
> +             depth++;
> +             /* Get the edge from the cond_bb to cur_bb, to determine whether
> +                the stmt is on the taken path of the conditional statement.  
> */
> +             edge e = find_edge (cond_bb, cur_bb);
> +             bool is_branch_taken = e->flags & EDGE_TRUE_VALUE;
> +             path->add_event (gimple_location (cond_stmt), cfun->decl, 1,
> +                              "when the condition is evaluated to %s",
> +                              is_branch_taken ? "true" : "false");
> +           }
> +       }
> +       cur_bb = cond_bb;
> +    }
> +  while (cond_bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
> +        && depth < flag_diagnostics_show_context);
> +
> +  /* Add an end of path warning event in the end of the path.  */
> +  if (path->num_events () > 0)
> +    path->add_event (m_location, cfun->decl, 1,
> +                    "warning happens here");
> +  return path;
> +}
> diff --git a/gcc/diagnostic-context-rich-location.h 
> b/gcc/diagnostic-context-rich-location.h
> new file mode 100644
> index 00000000000..676b9d23b05
> --- /dev/null
> +++ b/gcc/diagnostic-context-rich-location.h
> @@ -0,0 +1,73 @@
> +/* A rich_location subclass that lazily populates a diagnostic_path
> +   with diagnostic context events, but only if the path is actually to be
> +   used.
> +   Copyright (C) 2025 Free Software Foundation, Inc.
> +   Contributed by Qing Zhao<qing.z...@oracle.com>
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
> +#define GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
> +
> +#include "gcc-rich-location.h"
> +#include "diagnostics/lazy-paths.h"
> +#include "tree-logical-location.h"
> +
> +class lazy_diagnostic_context_path : public diagnostics::paths::lazy_path
> +{
> +public:
> +  lazy_diagnostic_context_path (const tree_logical_location_manager
> +                               &logical_loc_mgr,
> +                               location_t location, gimple *stmt)
> +  : diagnostics::paths::lazy_path (logical_loc_mgr),
> +    m_logical_loc_mgr (logical_loc_mgr),
> +    m_location (location), m_stmt (stmt)
> +  {
> +  }
> +
> +  std::unique_ptr<diagnostics::paths::path>
> +  make_inner_path () const final override;
> +  /* This method will be called on demand if a diagnostic is actually
> +     emitted for this rich_location.  */
> +
> +  const tree_logical_location_manager &m_logical_loc_mgr;
> +  location_t m_location;
> +  gimple *m_stmt;
> +};
> +
> +class rich_location_with_details : public gcc_rich_location
> +{
> +public:
> +  rich_location_with_details (location_t location, gimple *stmt)
> +  : gcc_rich_location (location),
> +    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, stmt)
> +  {
> +    set_path (&m_lazy_diagnostic_context_path);
> +  }
> +
> +  rich_location_with_details (location_t location, tree exp ATTRIBUTE_UNUSED)
> +  : gcc_rich_location (location),
> +    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, nullptr)
> +  {
> +  }
> +
> +private:
> +  const tree_logical_location_manager m_logical_loc_mgr;
> +  lazy_diagnostic_context_path m_lazy_diagnostic_context_path;
> +};
> +
> +#endif // GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 28466c449b9..af8483f437f 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -334,7 +334,8 @@ Objective-C and Objective-C++ Dialects}.
>  -fdiagnostics-column-unit=@r{[}display@r{|}byte@r{]}
>  -fdiagnostics-column-origin=@var{origin}
>  -fdiagnostics-escape-format=@r{[}unicode@r{|}bytes@r{]}
> --fdiagnostics-text-art-charset=@r{[}none@r{|}ascii@r{|}unicode@r{|}emoji@r{]}}
> +-fdiagnostics-text-art-charset=@r{[}none@r{|}ascii@r{|}unicode@r{|}emoji@r{]}
> +-fdiagnostics-show-context@r{[}=@var{depth}@r{]}}
>
>  @item Warning Options
>  @xref{Warning Options,,Options to Request or Suppress Warnings}.
> @@ -5770,6 +5771,22 @@ left margin.
>  This option controls the minimum width of the left margin printed by
>  @option{-fdiagnostics-show-line-numbers}.  It defaults to 6.
>
> +@opindex fdiagnostics-show-context
> +@item -fdiagnostics-show-context[=@var{depth}]
> +@itemx -fno-diagnostics-show-context
> +With this option, the compiler might print the interesting control flow
> +chain that guards the basic block of the statement which has the warning.
> +@var{depth} is the maximum depth of the control flow chain.
> +Currently, The list of the impacted warning options includes:
> +@option{-Warray-bounds}, @option{-Wstringop-overflow},
> +@option{-Wstringop-overread}, @option{-Wstringop-truncation}.
> +and @option{-Wrestrict}.
> +More warning options might be added to this list in future releases.
> +The forms @option{-fdiagnostics-show-context} and
> +@option{-fno-diagnostics-show-context} are aliases for
> +@option{-fdiagnostics-show-context=1} and
> +@option{-fdiagnostics-show-context=0}, respectively.
> +
>  @opindex fdiagnostics-parseable-fixits
>  @item -fdiagnostics-parseable-fixits
>  Emit fix-it hints in a machine-parseable format, suitable for consumption
> diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
> index 22286cbb4cc..b62eb192b0a 100644
> --- a/gcc/gimple-array-bounds.cc
> +++ b/gcc/gimple-array-bounds.cc
> @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-dfa.h"
>  #include "fold-const.h"
>  #include "diagnostic-core.h"
> +#include "diagnostic-context-rich-location.h"
>  #include "intl.h"
>  #include "tree-vrp.h"
>  #include "alloc-pool.h"
> @@ -262,6 +263,7 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>
>  static bool
>  check_out_of_bounds_and_warn (location_t location, tree ref,
> +                             gimple *stmt,
>                               tree low_sub_org, tree low_sub, tree up_sub,
>                               tree up_bound, tree up_bound_p1,
>                               const irange *vr,
> @@ -275,12 +277,13 @@ check_out_of_bounds_and_warn (location_t location, tree 
> ref,
>    bool warned = false;
>    *out_of_bound = false;
>
> +  rich_location_with_details richloc (location, stmt);
>    /* Empty array.  */
>    if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
>      {
>        *out_of_bound = true;
>        if (for_array_bound)
> -       warned = warning_at (location, OPT_Warray_bounds_,
> +       warned = warning_at (&richloc, OPT_Warray_bounds_,
>                              "array subscript %E is outside array"
>                              " bounds of %qT", low_sub_org, artype);
>      }
> @@ -299,7 +302,7 @@ check_out_of_bounds_and_warn (location_t location, tree 
> ref,
>         {
>           *out_of_bound = true;
>           if (for_array_bound)
> -           warned = warning_at (location, OPT_Warray_bounds_,
> +           warned = warning_at (&richloc, OPT_Warray_bounds_,
>                                  "array subscript [%E, %E] is outside "
>                                  "array bounds of %qT",
>                                  low_sub, up_sub, artype);
> @@ -313,7 +316,7 @@ check_out_of_bounds_and_warn (location_t location, tree 
> ref,
>      {
>        *out_of_bound = true;
>        if (for_array_bound)
> -       warned = warning_at (location, OPT_Warray_bounds_,
> +       warned = warning_at (&richloc, OPT_Warray_bounds_,
>                              "array subscript %E is above array bounds of 
> %qT",
>                              up_sub, artype);
>      }
> @@ -322,7 +325,7 @@ check_out_of_bounds_and_warn (location_t location, tree 
> ref,
>      {
>        *out_of_bound = true;
>        if (for_array_bound)
> -       warned = warning_at (location, OPT_Warray_bounds_,
> +       warned = warning_at (&richloc, OPT_Warray_bounds_,
>                              "array subscript %E is below array bounds of 
> %qT",
>                              low_sub, artype);
>      }
> @@ -388,15 +391,16 @@ array_bounds_checker::check_array_ref (location_t 
> location, tree ref,
>         }
>      }
>
> -  warned = check_out_of_bounds_and_warn (location, ref,
> +  warned = check_out_of_bounds_and_warn (location, ref, stmt,
>                                          low_sub_org, low_sub, up_sub,
>                                          up_bound, up_bound_p1, &vr,
>                                          ignore_off_by_one, warn_array_bounds,
>                                          &out_of_bound);
>
> +  rich_location_with_details richloc (location, stmt);
>
>    if (!warned && sam == special_array_member::int_0)
> -    warned = warning_at (location, OPT_Wzero_length_bounds,
> +    warned = warning_at (&richloc, OPT_Wzero_length_bounds,
>                          (TREE_CODE (low_sub) == INTEGER_CST
>                           ? G_("array subscript %E is outside the bounds "
>                                "of an interior zero-length array %qT")
> @@ -420,7 +424,7 @@ array_bounds_checker::check_array_ref (location_t 
> location, tree ref,
>        && DECL_NOT_FLEXARRAY (afield_decl))
>      {
>        bool warned1
> -       = warning_at (location, OPT_Wstrict_flex_arrays,
> +       = warning_at (&richloc, OPT_Wstrict_flex_arrays,
>                       "trailing array %qT should not be used as "
>                       "a flexible array member",
>                       artype);
> @@ -478,6 +482,7 @@ array_bounds_checker::check_array_ref (location_t 
> location, tree ref,
>
>  bool
>  array_bounds_checker::check_mem_ref (location_t location, tree ref,
> +                                    gimple *stmt,
>                                      bool ignore_off_by_one)
>  {
>    if (warning_suppressed_p (ref, OPT_Warray_bounds_))
> @@ -576,16 +581,17 @@ array_bounds_checker::check_mem_ref (location_t 
> location, tree ref,
>         }
>      }
>
> +  rich_location_with_details richloc (location, stmt);
>    bool warned = false;
>    if (lboob)
>      {
>        if (offrange[0] == offrange[1])
> -       warned = warning_at (location, OPT_Warray_bounds_,
> +       warned = warning_at (&richloc, OPT_Warray_bounds_,
>                              "array subscript %wi is outside array bounds "
>                              "of %qT",
>                              offrange[0].to_shwi (), reftype);
>        else
> -       warned = warning_at (location, OPT_Warray_bounds_,
> +       warned = warning_at (&richloc, OPT_Warray_bounds_,
>                              "array subscript [%wi, %wi] is outside "
>                              "array bounds of %qT",
>                              offrange[0].to_shwi (),
> @@ -599,8 +605,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
>            it were an untyped array of bytes.  */
>         backtype = build_array_type_nelts (unsigned_char_type_node,
>                                            aref.sizrng[1].to_uhwi ());
> -
> -      warned = warning_at (location, OPT_Warray_bounds_,
> +      warned = warning_at (&richloc, OPT_Warray_bounds_,
>                            "array subscript %<%T[%wi]%> is partly "
>                            "outside array bounds of %qT",
>                            axstype, offrange[0].to_shwi (), backtype);
> @@ -623,7 +628,7 @@ array_bounds_checker::check_mem_ref (location_t location, 
> tree ref,
>      {
>        HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi ();
>
> -      if (warning_at (location, OPT_Warray_bounds_,
> +      if (warning_at (&richloc, OPT_Warray_bounds_,
>                       "intermediate array offset %wi is outside array bounds "
>                       "of %qT", tmpidx, reftype))
>         {
> @@ -656,7 +661,7 @@ array_bounds_checker::check_addr_expr (location_t 
> location, tree t,
>           ignore_off_by_one = false;
>         }
>        else if (TREE_CODE (t) == MEM_REF)
> -       warned = check_mem_ref (location, t, ignore_off_by_one);
> +       warned = check_mem_ref (location, t, stmt, ignore_off_by_one);
>
>        if (warned)
>         suppress_warning (t, OPT_Warray_bounds_);
> @@ -692,6 +697,7 @@ array_bounds_checker::check_addr_expr (location_t 
> location, tree t,
>    if (!mem_ref_offset (t).is_constant (&idx))
>      return;
>
> +  rich_location_with_details richloc (location, stmt);
>    bool warned = false;
>    idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
>    if (idx < 0)
> @@ -702,7 +708,7 @@ array_bounds_checker::check_addr_expr (location_t 
> location, tree t,
>           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
>           fprintf (dump_file, "\n");
>         }
> -      warned = warning_at (location, OPT_Warray_bounds_,
> +      warned = warning_at (&richloc, OPT_Warray_bounds_,
>                            "array subscript %wi is below "
>                            "array bounds of %qT",
>                            idx.to_shwi (), TREE_TYPE (tem));
> @@ -716,7 +722,7 @@ array_bounds_checker::check_addr_expr (location_t 
> location, tree t,
>           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
>           fprintf (dump_file, "\n");
>         }
> -      warned = warning_at (location, OPT_Warray_bounds_,
> +      warned = warning_at (&richloc, OPT_Warray_bounds_,
>                            "array subscript %wu is above "
>                            "array bounds of %qT",
>                            idx.to_uhwi (), TREE_TYPE (tem));
> @@ -811,7 +817,7 @@ array_bounds_checker::check_array_bounds (tree *tp, int 
> *walk_subtree,
>      warned = checker->check_array_ref (location, t, wi->stmt,
>                                        false/*ignore_off_by_one*/);
>    else if (TREE_CODE (t) == MEM_REF)
> -    warned = checker->check_mem_ref (location, t,
> +    warned = checker->check_mem_ref (location, t, wi->stmt,
>                                      false /*ignore_off_by_one*/);
>    else if (TREE_CODE (t) == ADDR_EXPR)
>      {
> diff --git a/gcc/gimple-array-bounds.h b/gcc/gimple-array-bounds.h
> index bdf8a3428a6..611bcdf17e3 100644
> --- a/gcc/gimple-array-bounds.h
> +++ b/gcc/gimple-array-bounds.h
> @@ -33,7 +33,7 @@ public:
>  private:
>    static tree check_array_bounds (tree *tp, int *walk_subtree, void *data);
>    bool check_array_ref (location_t, tree, gimple *, bool ignore_off_by_one);
> -  bool check_mem_ref (location_t, tree, bool ignore_off_by_one);
> +  bool check_mem_ref (location_t, tree, gimple *, bool ignore_off_by_one);
>    void check_addr_expr (location_t, tree, gimple *);
>    void get_value_range (irange &r, const_tree op, gimple *);
>
> diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
> index 0f4aff6b59b..abfb8685ce7 100644
> --- a/gcc/gimple-ssa-warn-access.cc
> +++ b/gcc/gimple-ssa-warn-access.cc
> @@ -57,6 +57,7 @@
>  #include "pointer-query.h"
>  #include "pretty-print-markup.h"
>  #include "gcc-urlifier.h"
> +#include "diagnostic-context-rich-location.h"
>
>  /* Return true if tree node X has an associated location.  */
>
> @@ -169,17 +170,19 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, 
> const char *fname,
>    if (expr)
>      {
>        tree func = get_callee_fndecl (expr);
> +      rich_location_with_details richloc (loc, expr);
> +
>        if (bndrng)
>         {
>           if (wi::ltu_p (maxsiz, bndrng[0]))
> -           warned = warning_at (loc, opt,
> +           warned = warning_at (&richloc, opt,
>                                  "%qD specified bound %s exceeds "
>                                  "maximum object size %E",
>                                  func, bndstr, maxobjsize);
>           else
>             {
>               bool maybe = wi::to_wide (size) == bndrng[0];
> -             warned = warning_at (loc, opt,
> +             warned = warning_at (&richloc, opt,
>                                    exact
>                                    ? G_("%qD specified bound %s exceeds "
>                                         "the size %E of unterminated array")
> @@ -194,7 +197,7 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, 
> const char *fname,
>             }
>         }
>        else
> -       warned = warning_at (loc, opt,
> +       warned = warning_at (&richloc, opt,
>                              "%qD argument missing terminating nul",
>                              func);
>      }
> @@ -486,14 +489,16 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
>        tree maxobjsize = max_object_size ();
>        if (tree_int_cst_lt (maxobjsize, bndrng[0]))
>         {
> +         rich_location_with_details richloc (loc, exp);
> +
>           bool warned = false;
>           if (tree_int_cst_equal (bndrng[0], bndrng[1]))
> -           warned = warning_at (loc, OPT_Wstringop_overread,
> +           warned = warning_at (&richloc, OPT_Wstringop_overread,
>                                  "%qD specified bound %E "
>                                  "exceeds maximum object size %E",
>                                  fndecl, bndrng[0], maxobjsize);
>           else
> -           warned = warning_at (loc, OPT_Wstringop_overread,
> +           warned = warning_at (&richloc, OPT_Wstringop_overread,
>                                  "%qD specified bound [%E, %E] "
>                                  "exceeds maximum object size %E",
>                                  fndecl, bndrng[0], bndrng[1],
> @@ -645,20 +650,21 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
>        auto_diagnostic_group d;
>        if (wi::ltu_p (asize, wibnd))
>         {
> +         rich_location_with_details richloc (loc, exp);
>           if (bndrng[0] == bndrng[1])
> -           warned = warning_at (loc, OPT_Wstringop_overread,
> +           warned = warning_at (&richloc, OPT_Wstringop_overread,
>                                  "%qD argument %i declared attribute "
>                                  "%<nonstring%> is smaller than the specified 
> "
>                                  "bound %wu",
>                                  fndecl, argno + 1, wibnd.to_uhwi ());
>           else if (wi::ltu_p (asize, wi::to_offset (bndrng[0])))
> -           warned = warning_at (loc, OPT_Wstringop_overread,
> +           warned = warning_at (&richloc, OPT_Wstringop_overread,
>                                  "%qD argument %i declared attribute "
>                                  "%<nonstring%> is smaller than "
>                                  "the specified bound [%E, %E]",
>                                  fndecl, argno + 1, bndrng[0], bndrng[1]);
>           else
> -           warned = warning_at (loc, OPT_Wstringop_overread,
> +           warned = warning_at (&richloc, OPT_Wstringop_overread,
>                                  "%qD argument %i declared attribute "
>                                  "%<nonstring%> may be smaller than "
>                                  "the specified bound [%E, %E]",
> @@ -730,16 +736,17 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>        auto_diagnostic_group d;
>        if (tree_int_cst_lt (maxobjsize, bndrng[0]))
>         {
> +         rich_location_with_details richloc (loc, exp);
>           if (bndrng[0] == bndrng[1])
>             warned = (func
> -                     ? warning_at (loc, opt,
> +                     ? warning_at (&richloc, opt,
>                                     (maybe
>                                      ? G_("%qD specified bound %E may "
>                                           "exceed maximum object size %E")
>                                      : G_("%qD specified bound %E "
>                                           "exceeds maximum object size %E")),
>                                     func, bndrng[0], maxobjsize)
> -                     : warning_at (loc, opt,
> +                     : warning_at (&richloc, opt,
>                                     (maybe
>                                      ? G_("specified bound %E may "
>                                           "exceed maximum object size %E")
> @@ -748,7 +755,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>                                     bndrng[0], maxobjsize));
>           else
>             warned = (func
> -                     ? warning_at (loc, opt,
> +                     ? warning_at (&richloc, opt,
>                                     (maybe
>                                      ? G_("%qD specified bound [%E, %E] may "
>                                           "exceed maximum object size %E")
> @@ -756,7 +763,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>                                           "exceeds maximum object size %E")),
>                                     func,
>                                     bndrng[0], bndrng[1], maxobjsize)
> -                     : warning_at (loc, opt,
> +                     : warning_at (&richloc, opt,
>                                     (maybe
>                                      ? G_("specified bound [%E, %E] may "
>                                           "exceed maximum object size %E")
> @@ -767,37 +774,43 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>        else if (!size || tree_int_cst_le (bndrng[0], size))
>         return false;
>        else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
> -       warned = (func
> -                 ? warning_at (loc, opt,
> +       {
> +         rich_location_with_details richloc (loc, exp);
> +         warned = (func
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD specified bound %E may exceed "
>                                       "source size %E")
>                                  : G_("%qD specified bound %E exceeds "
>                                       "source size %E")),
>                                 func, bndrng[0], size)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("specified bound %E may exceed "
>                                       "source size %E")
>                                  : G_("specified bound %E exceeds "
>                                       "source size %E")),
>                                 bndrng[0], size));
> +       }
>        else
> -       warned = (func
> -                 ? warning_at (loc, opt,
> +       {
> +         rich_location_with_details richloc (loc, exp);
> +         warned = (func
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD specified bound [%E, %E] may "
>                                       "exceed source size %E")
>                                  : G_("%qD specified bound [%E, %E] exceeds "
>                                       "source size %E")),
>                                 func, bndrng[0], bndrng[1], size)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("specified bound [%E, %E] may exceed "
>                                       "source size %E")
>                                  : G_("specified bound [%E, %E] exceeds "
>                                       "source size %E")),
>                                 bndrng[0], bndrng[1], size));
> +       }
>        if (warned)
>         {
>           if (pad && pad->src.ref
> @@ -811,6 +824,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>      }
>
>    bool maybe = pad && pad->dst.phi ();
> +  rich_location_with_details richloc (loc, exp);
>    if (maybe)
>      {
>        /* Issue a "maybe" warning only if the PHI refers to objects
> @@ -824,14 +838,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>      {
>        if (bndrng[0] == bndrng[1])
>         warned = (func
> -                 ? warning_at (loc, opt,
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD specified size %E may "
>                                       "exceed maximum object size %E")
>                                  : G_("%qD specified size %E "
>                                       "exceeds maximum object size %E")),
>                                 func, bndrng[0], maxobjsize)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("specified size %E may exceed "
>                                       "maximum object size %E")
> @@ -840,14 +854,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>                                 bndrng[0], maxobjsize));
>        else
>         warned = (func
> -                 ? warning_at (loc, opt,
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD specified size between %E and %E "
>                                       "may exceed maximum object size %E")
>                                  : G_("%qD specified size between %E and %E "
>                                       "exceeds maximum object size %E")),
>                                 func, bndrng[0], bndrng[1], maxobjsize)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("specified size between %E and %E "
>                                       "may exceed maximum object size %E")
> @@ -859,14 +873,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>      return false;
>    else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
>      warned = (func
> -             ? warning_at (loc, opt,
> +             ? warning_at (&richloc, opt,
>                             (maybe
>                              ? G_("%qD specified bound %E may exceed "
>                                   "destination size %E")
>                              : G_("%qD specified bound %E exceeds "
>                                   "destination size %E")),
>                             func, bndrng[0], size)
> -             : warning_at (loc, opt,
> +             : warning_at (&richloc, opt,
>                             (maybe
>                              ? G_("specified bound %E may exceed "
>                                   "destination size %E")
> @@ -875,14 +889,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
> GimpleOrTree exp, tree func,
>                             bndrng[0], size));
>    else
>      warned = (func
> -             ? warning_at (loc, opt,
> +             ? warning_at (&richloc, opt,
>                             (maybe
>                              ? G_("%qD specified bound [%E, %E] may exceed "
>                                   "destination size %E")
>                              : G_("%qD specified bound [%E, %E] exceeds "
>                                   "destination size %E")),
>                             func, bndrng[0], bndrng[1], size)
> -             : warning_at (loc, opt,
> +             : warning_at (&richloc, opt,
>                             (maybe
>                              ? G_("specified bound [%E, %E] exceeds "
>                                   "destination size %E")
> @@ -933,11 +947,13 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>  {
>    bool warned = false;
>
> +  rich_location_with_details richloc (loc, exp);
> +
>    if (write && read)
>      {
>        if (tree_int_cst_equal (range[0], range[1]))
>         warned = (func
> -                 ? warning_n (loc, opt, tree_to_uhwi (range[0]),
> +                 ? warning_n (&richloc, opt, tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("%qD may access %E byte in a region "
>                                      "of size %E")
> @@ -949,7 +965,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree 
> exp, int opt,
>                                  : G_ ("%qD accessing %E bytes in a region "
>                                        "of size %E")),
>                                func, range[0], size)
> -                 : warning_n (loc, opt, tree_to_uhwi (range[0]),
> +                 : warning_n (&richloc, opt, tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("may access %E byte in a region "
>                                      "of size %E")
> @@ -965,14 +981,14 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         {
>           /* Avoid printing the upper bound if it's invalid.  */
>           warned = (func
> -                   ? warning_at (loc, opt,
> +                   ? warning_at (&richloc, opt,
>                                   (maybe
>                                    ? G_("%qD may access %E or more bytes "
>                                         "in a region of size %E")
>                                    : G_("%qD accessing %E or more bytes "
>                                         "in a region of size %E")),
>                                   func, range[0], size)
> -                   : warning_at (loc, opt,
> +                   : warning_at (&richloc, opt,
>                                   (maybe
>                                    ? G_("may access %E or more bytes "
>                                         "in a region of size %E")
> @@ -982,14 +998,14 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         }
>        else
>         warned = (func
> -                 ? warning_at (loc, opt,
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD may access between %E and %E "
>                                       "bytes in a region of size %E")
>                                  : G_("%qD accessing between %E and %E "
>                                       "bytes in a region of size %E")),
>                                 func, range[0], range[1], size)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("may access between %E and %E bytes "
>                                       "in a region of size %E")
> @@ -1003,7 +1019,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>      {
>        if (tree_int_cst_equal (range[0], range[1]))
>         warned = (func
> -                 ? warning_n (loc, opt, tree_to_uhwi (range[0]),
> +                 ? warning_n (&richloc, opt, tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("%qD may write %E byte into a region "
>                                      "of size %E")
> @@ -1015,7 +1031,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>                                 : G_("%qD writing %E bytes into a region "
>                                      "of size %E overflows the destination")),
>                                func, range[0], size)
> -                 : warning_n (loc, opt, tree_to_uhwi (range[0]),
> +                 : warning_n (&richloc, opt, tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("may write %E byte into a region "
>                                      "of size %E")
> @@ -1031,7 +1047,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         {
>           /* Avoid printing the upper bound if it's invalid.  */
>           warned = (func
> -                   ? warning_at (loc, opt,
> +                   ? warning_at (&richloc, opt,
>                                   (maybe
>                                    ? G_("%qD may write %E or more bytes "
>                                         "into a region of size %E")
> @@ -1039,7 +1055,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>                                         "into a region of size %E overflows "
>                                         "the destination")),
>                                   func, range[0], size)
> -                   : warning_at (loc, opt,
> +                   : warning_at (&richloc, opt,
>                                   (maybe
>                                    ? G_("may write %E or more bytes into "
>                                         "a region of size %E")
> @@ -1050,7 +1066,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         }
>        else
>         warned = (func
> -                 ? warning_at (loc, opt,
> +                 ? warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("%qD may write between %E and %E bytes "
>                                       "into a region of size %E")
> @@ -1058,7 +1074,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>                                       "into a region of size %E overflows "
>                                       "the destination")),
>                                 func, range[0], range[1], size)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("may write between %E and %E bytes "
>                                       "into a region of size %E")
> @@ -1073,7 +1089,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>      {
>        if (tree_int_cst_equal (range[0], range[1]))
>         warned = (func
> -                 ? warning_n (loc, OPT_Wstringop_overread,
> +                 ? warning_n (&richloc, OPT_Wstringop_overread,
>                                tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("%qD may read %E byte from a region "
> @@ -1086,7 +1102,7 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>                                 : G_("%qD reading %E bytes from a region "
>                                      "of size %E")),
>                                func, range[0], size)
> -                 : warning_n (loc, OPT_Wstringop_overread,
> +                 : warning_n (&richloc, OPT_Wstringop_overread,
>                                tree_to_uhwi (range[0]),
>                                (maybe
>                                 ? G_("may read %E byte from a region "
> @@ -1103,14 +1119,14 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         {
>           /* Avoid printing the upper bound if it's invalid.  */
>           warned = (func
> -                   ? warning_at (loc, OPT_Wstringop_overread,
> +                   ? warning_at (&richloc, OPT_Wstringop_overread,
>                                   (maybe
>                                    ? G_("%qD may read %E or more bytes "
>                                         "from a region of size %E")
>                                    : G_("%qD reading %E or more bytes "
>                                         "from a region of size %E")),
>                                   func, range[0], size)
> -                   : warning_at (loc, OPT_Wstringop_overread,
> +                   : warning_at (&richloc, OPT_Wstringop_overread,
>                                   (maybe
>                                    ? G_("may read %E or more bytes "
>                                         "from a region of size %E")
> @@ -1120,14 +1136,14 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>         }
>        else
>         warned = (func
> -                 ? warning_at (loc, OPT_Wstringop_overread,
> +                 ? warning_at (&richloc, OPT_Wstringop_overread,
>                                 (maybe
>                                  ? G_("%qD may read between %E and %E bytes "
>                                       "from a region of size %E")
>                                  : G_("%qD reading between %E and %E bytes "
>                                       "from a region of size %E")),
>                                 func, range[0], range[1], size)
> -                 : warning_at (loc, opt,
> +                 : warning_at (&richloc, opt,
>                                 (maybe
>                                  ? G_("may read between %E and %E bytes "
>                                       "from a region of size %E")
> @@ -1144,12 +1160,12 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>    if (tree_int_cst_equal (range[0], range[1])
>        || tree_int_cst_sign_bit (range[1]))
>      warned = (func
> -             ? warning_n (loc, OPT_Wstringop_overread,
> +             ? warning_n (&richloc, OPT_Wstringop_overread,
>                            tree_to_uhwi (range[0]),
>                            "%qD expecting %E byte in a region of size %E",
>                            "%qD expecting %E bytes in a region of size %E",
>                            func, range[0], size)
> -             : warning_n (loc, OPT_Wstringop_overread,
> +             : warning_n (&richloc, OPT_Wstringop_overread,
>                            tree_to_uhwi (range[0]),
>                            "expecting %E byte in a region of size %E",
>                            "expecting %E bytes in a region of size %E",
> @@ -1158,22 +1174,22 @@ warn_for_access (location_t loc, tree func, 
> GimpleOrTree exp, int opt,
>      {
>        /* Avoid printing the upper bound if it's invalid.  */
>        warned = (func
> -               ? warning_at (loc, OPT_Wstringop_overread,
> +               ? warning_at (&richloc, OPT_Wstringop_overread,
>                               "%qD expecting %E or more bytes in a region "
>                               "of size %E",
>                               func, range[0], size)
> -               : warning_at (loc, OPT_Wstringop_overread,
> +               : warning_at (&richloc, OPT_Wstringop_overread,
>                               "expecting %E or more bytes in a region "
>                               "of size %E",
>                               range[0], size));
>      }
>    else
>      warned = (func
> -             ? warning_at (loc, OPT_Wstringop_overread,
> +             ? warning_at (&richloc, OPT_Wstringop_overread,
>                             "%qD expecting between %E and %E bytes in "
>                             "a region of size %E",
>                             func, range[0], range[1], size)
> -             : warning_at (loc, OPT_Wstringop_overread,
> +             : warning_at (&richloc, OPT_Wstringop_overread,
>                             "expecting between %E and %E bytes in "
>                             "a region of size %E",
>                             range[0], range[1], size));
> @@ -1404,6 +1420,8 @@ check_access (GimpleOrTree exp, tree dstwrite,
>
>           auto_diagnostic_group d;
>           location_t loc = get_location (exp);
> +         rich_location_with_details richloc (loc, exp);
> +
>           bool warned = false;
>           if (dstwrite == slen && at_least_one)
>             {
> @@ -1411,12 +1429,12 @@ check_access (GimpleOrTree exp, tree dstwrite,
>                  and a source of unknown length.  The call will write
>                  at least one byte past the end of the destination.  */
>               warned = (func
> -                       ? warning_at (loc, opt,
> +                       ? warning_at (&richloc, opt,
>                                       "%qD writing %E or more bytes into "
>                                       "a region of size %E overflows "
>                                       "the destination",
>                                       func, range[0], dstsize)
> -                       : warning_at (loc, opt,
> +                       : warning_at (&richloc, opt,
>                                       "writing %E or more bytes into "
>                                       "a region of size %E overflows "
>                                       "the destination",
> @@ -2583,7 +2601,9 @@ pass_waccess::check_strncat (gcall *stmt)
>        && tree_int_cst_equal (destsize, maxread))
>      {
>        location_t loc = get_location (stmt);
> -      warning_at (loc, OPT_Wstringop_overflow_,
> +      rich_location_with_details richloc (loc, stmt);
> +
> +      warning_at (&richloc, OPT_Wstringop_overflow_,
>                   "%qD specified bound %E equals destination size",
>                   get_callee_fndecl (stmt), maxread);
>
> @@ -3464,13 +3484,14 @@ pass_waccess::maybe_check_access_sizes (rdwr_map 
> *rwm, tree fndecl, tree fntype,
>           && tree_int_cst_sgn (sizrng[0]) < 0
>           && tree_int_cst_sgn (sizrng[1]) < 0)
>         {
> +         rich_location_with_details richloc (loc, stmt);
>           /* Warn about negative sizes.  */
>           if (access.second.internal_p)
>             {
>               const std::string argtypestr
>                 = access.second.array_as_string (ptrtype);
>
> -             if (warning_at (loc, OPT_Wstringop_overflow_,
> +             if (warning_at (&richloc, OPT_Wstringop_overflow_,
>                               "bound argument %i value %s is "
>                               "negative for a variable length array "
>                               "argument %i of type %s",
> @@ -3478,7 +3499,7 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, 
> tree fndecl, tree fntype,
>                               ptridx + 1, argtypestr.c_str ()))
>                 arg_warned = OPT_Wstringop_overflow_;
>             }
> -         else if (warning_at (loc, OPT_Wstringop_overflow_,
> +         else if (warning_at (&richloc, OPT_Wstringop_overflow_,
>                                "argument %i value %s is negative",
>                                sizidx + 1, sizstr))
>             arg_warned = OPT_Wstringop_overflow_;
> diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
> index 47263aa4d34..e48fe1eb841 100644
> --- a/gcc/gimple-ssa-warn-restrict.cc
> +++ b/gcc/gimple-ssa-warn-restrict.cc
> @@ -40,6 +40,7 @@
>  #include "tree-object-size.h"
>  #include "calls.h"
>  #include "cfgloop.h"
> +#include "diagnostic-context-rich-location.h"
>  #include "intl.h"
>  #include "gimple-range.h"
>
> @@ -106,11 +107,23 @@ pass_wrestrict::execute (function *fun)
>  {
>    /* Create a new ranger instance and associate it with FUN.  */
>    m_ptr_qry.rvals = enable_ranger (fun);
> +  bool new_dominance_for_diagnostics = false;
> +
> +  if (flag_diagnostics_show_context
> +      && !dom_info_available_p (fun, CDI_DOMINATORS))
> +    {
> +      calculate_dominance_info (CDI_DOMINATORS);
> +      new_dominance_for_diagnostics = true;
> +    }
>
>    basic_block bb;
>    FOR_EACH_BB_FN (bb, fun)
>      check_block (bb);
>
> +  if (new_dominance_for_diagnostics
> +      && dom_info_available_p (fun, CDI_DOMINATORS))
> +    free_dominance_info (fun, CDI_DOMINATORS);
> +
>    m_ptr_qry.flush_cache ();
>
>    /* Release the ranger instance and replace it with a global ranger.
> @@ -1447,6 +1460,8 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>
>    tree func = gimple_call_fndecl (call);
>
> +  rich_location_with_details richloc (loc, call);
> +
>    /* To avoid a combinatorial explosion of diagnostics format the offsets
>       or their ranges as strings and use them in the warning calls below.  */
>    char offstr[3][64];
> @@ -1492,7 +1507,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>        if (sizrange[0] == sizrange[1])
>         {
>           if (ovlsiz[0] == ovlsiz[1])
> -           warning_at (loc, OPT_Wrestrict,
> +           warning_at (&richloc, OPT_Wrestrict,
>                         sizrange[0] == 1
>                         ? (ovlsiz[0] == 1
>                            ? G_("%qD accessing %wu byte at offsets %s "
> @@ -1509,7 +1524,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>                         func, sizrange[0],
>                         offstr[0], offstr[1], ovlsiz[0], offstr[2]);
>           else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
> -           warning_n (loc, OPT_Wrestrict, sizrange[0],
> +           warning_n (&richloc, OPT_Wrestrict, sizrange[0],
>                        "%qD accessing %wu byte at offsets %s "
>                        "and %s overlaps between %wu and %wu bytes "
>                        "at offset %s",
> @@ -1519,7 +1534,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>                        func, sizrange[0], offstr[0], offstr[1],
>                        ovlsiz[0], ovlsiz[1], offstr[2]);
>           else
> -           warning_n (loc, OPT_Wrestrict, sizrange[0],
> +           warning_n (&richloc, OPT_Wrestrict, sizrange[0],
>                        "%qD accessing %wu byte at offsets %s and "
>                        "%s overlaps %wu or more bytes at offset %s",
>                        "%qD accessing %wu bytes at offsets %s and "
> @@ -1532,7 +1547,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>        if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
>         {
>           if (ovlsiz[0] == ovlsiz[1])
> -           warning_n (loc, OPT_Wrestrict, ovlsiz[0],
> +           warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
>                        "%qD accessing between %wu and %wu bytes "
>                        "at offsets %s and %s overlaps %wu byte at "
>                        "offset %s",
> @@ -1542,7 +1557,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>                        func, sizrange[0], sizrange[1],
>                        offstr[0], offstr[1], ovlsiz[0], offstr[2]);
>           else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
> -           warning_at (loc, OPT_Wrestrict,
> +           warning_at (&richloc, OPT_Wrestrict,
>                         "%qD accessing between %wu and %wu bytes at "
>                         "offsets %s and %s overlaps between %wu and %wu "
>                         "bytes at offset %s",
> @@ -1550,7 +1565,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>                         offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
>                         offstr[2]);
>           else
> -           warning_at (loc, OPT_Wrestrict,
> +           warning_at (&richloc, OPT_Wrestrict,
>                         "%qD accessing between %wu and %wu bytes at "
>                         "offsets %s and %s overlaps %wu or more bytes "
>                         "at offset %s",
> @@ -1563,7 +1578,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>         ovlsiz[1] = maxobjsize.to_shwi ();
>
>        if (ovlsiz[0] == ovlsiz[1])
> -       warning_n (loc, OPT_Wrestrict, ovlsiz[0],
> +       warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
>                    "%qD accessing %wu or more bytes at offsets "
>                    "%s and %s overlaps %wu byte at offset %s",
>                    "%qD accessing %wu or more bytes at offsets "
> @@ -1571,14 +1586,14 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>                    func, sizrange[0], offstr[0], offstr[1],
>                    ovlsiz[0], offstr[2]);
>        else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
> -       warning_at (loc, OPT_Wrestrict,
> +       warning_at (&richloc, OPT_Wrestrict,
>                     "%qD accessing %wu or more bytes at offsets %s "
>                     "and %s overlaps between %wu and %wu bytes "
>                     "at offset %s",
>                     func, sizrange[0], offstr[0], offstr[1],
>                     ovlsiz[0], ovlsiz[1], offstr[2]);
>        else
> -       warning_at (loc, OPT_Wrestrict,
> +       warning_at (&richloc, OPT_Wrestrict,
>                     "%qD accessing %wu or more bytes at offsets %s "
>                     "and %s overlaps %wu or more bytes at offset %s",
>                     func, sizrange[0], offstr[0], offstr[1],
> @@ -1606,14 +1621,14 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>        if (ovlsiz[1] == 1)
>         {
>           if (open_range)
> -           warning_n (loc, OPT_Wrestrict, sizrange[1],
> +           warning_n (&richloc, OPT_Wrestrict, sizrange[1],
>                        "%qD accessing %wu byte may overlap "
>                        "%wu byte",
>                        "%qD accessing %wu bytes may overlap "
>                        "%wu byte",
>                        func, sizrange[1], ovlsiz[1]);
>           else
> -           warning_n (loc, OPT_Wrestrict, sizrange[1],
> +           warning_n (&richloc, OPT_Wrestrict, sizrange[1],
>                        "%qD accessing %wu byte at offsets %s "
>                        "and %s may overlap %wu byte at offset %s",
>                        "%qD accessing %wu bytes at offsets %s "
> @@ -1624,14 +1639,14 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>         }
>
>        if (open_range)
> -       warning_n (loc, OPT_Wrestrict, sizrange[1],
> +       warning_n (&richloc, OPT_Wrestrict, sizrange[1],
>                    "%qD accessing %wu byte may overlap "
>                    "up to %wu bytes",
>                    "%qD accessing %wu bytes may overlap "
>                    "up to %wu bytes",
>                    func, sizrange[1], ovlsiz[1]);
>        else
> -       warning_n (loc, OPT_Wrestrict, sizrange[1],
> +       warning_n (&richloc, OPT_Wrestrict, sizrange[1],
>                    "%qD accessing %wu byte at offsets %s and "
>                    "%s may overlap up to %wu bytes at offset %s",
>                    "%qD accessing %wu bytes at offsets %s and "
> @@ -1644,14 +1659,14 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>    if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
>      {
>        if (open_range)
> -       warning_n (loc, OPT_Wrestrict, ovlsiz[1],
> +       warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
>                    "%qD accessing between %wu and %wu bytes "
>                    "may overlap %wu byte",
>                    "%qD accessing between %wu and %wu bytes "
>                    "may overlap up to %wu bytes",
>                    func, sizrange[0], sizrange[1], ovlsiz[1]);
>        else
> -       warning_n (loc, OPT_Wrestrict, ovlsiz[1],
> +       warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
>                    "%qD accessing between %wu and %wu bytes "
>                    "at offsets %s and %s may overlap %wu byte "
>                    "at offset %s",
> @@ -1663,7 +1678,7 @@ maybe_diag_overlap (location_t loc, gimple *call, 
> builtin_access &acs)
>        return true;
>      }
>
> -  warning_n (loc, OPT_Wrestrict, ovlsiz[1],
> +  warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
>              "%qD accessing %wu or more bytes at offsets %s "
>              "and %s may overlap %wu byte at offset %s",
>              "%qD accessing %wu or more bytes at offsets %s "
> @@ -1693,6 +1708,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>    location_t loc = gimple_location (call);
>    const offset_int maxobjsize = ref.maxobjsize;
>
> +  rich_location_with_details richloc (loc, call);
> +
>    /* Check for excessive size first and regardless of warning options
>       since the result is used to make codegen decisions.  */
>    if (ref.sizrange[0] > maxobjsize)
> @@ -1709,13 +1726,13 @@ maybe_diag_access_bounds (gimple *call, tree func, 
> int strict,
>        if (warn_stringop_overflow)
>         {
>           if (ref.sizrange[0] == ref.sizrange[1])
> -           warned = warning_at (loc, opt,
> +           warned = warning_at (&richloc, opt,
>                                  "%qD specified bound %wu "
>                                  "exceeds maximum object size %wu",
>                                  func, ref.sizrange[0].to_uhwi (),
>                                  maxobjsize.to_uhwi ());
>           else
> -           warned = warning_at (loc, opt,
> +           warned = warning_at (&richloc, opt,
>                                  "%qD specified bound between %wu and %wu "
>                                  "exceeds maximum object size %wu",
>                                  func, ref.sizrange[0].to_uhwi (),
> @@ -1776,7 +1793,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>           && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
>         {
>           auto_diagnostic_group d;
> -         if (warning_at (loc, opt,
> +         if (warning_at (&richloc, opt,
>                           "%qD pointer overflow between offset %s "
>                           "and size %s accessing array %qD with type %qT",
>                           func, rangestr[0], rangestr[1], ref.base, type))
> @@ -1786,13 +1803,13 @@ maybe_diag_access_bounds (gimple *call, tree func, 
> int strict,
>               warned = true;
>             }
>           else
> -           warned = warning_at (loc, opt,
> +           warned = warning_at (&richloc, opt,
>                                  "%qD pointer overflow between offset %s "
>                                  "and size %s",
>                                  func, rangestr[0], rangestr[1]);
>         }
>        else
> -       warned = warning_at (loc, opt,
> +       warned = warning_at (&richloc, opt,
>                              "%qD pointer overflow between offset %s "
>                              "and size %s",
>                              func, rangestr[0], rangestr[1]);
> @@ -1808,7 +1825,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>         {
>           auto_diagnostic_group d;
>           if ((ref.basesize < maxobjsize
> -              && warning_at (loc, opt,
> +              && warning_at (&richloc, opt,
>                               form
>                               ? G_("%qD forming offset %s is out of "
>                                    "the bounds [0, %wu] of object %qD with "
> @@ -1817,7 +1834,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>                                    "[0, %wu] of object %qD with type %qT"),
>                               func, rangestr[0], ref.basesize.to_uhwi (),
>                               ref.base, TREE_TYPE (ref.base)))
> -             || warning_at (loc, opt,
> +             || warning_at (&richloc, opt,
>                              form
>                              ? G_("%qD forming offset %s is out of "
>                                   "the bounds of object %qD with type %qT")
> @@ -1832,7 +1849,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>             }
>         }
>        else if (ref.basesize < maxobjsize)
> -       warned = warning_at (loc, opt,
> +       warned = warning_at (&richloc, opt,
>                              form
>                              ? G_("%qD forming offset %s is out "
>                                   "of the bounds [0, %wu]")
> @@ -1840,7 +1857,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>                                   "of the bounds [0, %wu]"),
>                              func, rangestr[0], ref.basesize.to_uhwi ());
>        else
> -       warned = warning_at (loc, opt,
> +       warned = warning_at (&richloc, opt,
>                              form
>                              ? G_("%qD forming offset %s is out of bounds")
>                              : G_("%qD offset %s is out of bounds"),
> @@ -1854,7 +1871,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>         type = TREE_TYPE (type);
>        type = TYPE_MAIN_VARIANT (type);
>
> -      if (warning_at (loc, opt,
> +      if (warning_at (&richloc, opt,
>                       "%qD offset %s from the object at %qE is out "
>                       "of the bounds of %qT",
>                       func, rangestr[0], ref.base, type))
> @@ -1872,7 +1889,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int 
> strict,
>        tree refop = TREE_OPERAND (ref.ref, 0);
>        tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
>
> -      if (warning_at (loc, opt,
> +      if (warning_at (&richloc, opt,
>                       "%qD offset %s from the object at %qE is out "
>                       "of the bounds of referenced subobject %qD with "
>                       "type %qT at offset %wi",
> diff --git a/gcc/testsuite/gcc.dg/pr109071.c b/gcc/testsuite/gcc.dg/pr109071.c
> new file mode 100644
> index 00000000000..74b7b46221e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071.c
> @@ -0,0 +1,43 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.  */
> +/* { dg-options "-O2 -Wall -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +
> +extern void warn(void);
> +static inline void assign(int val, int *regs, int index)
> +{
> +  if (index >= 4)
> +    warn();
> +  *regs = val;
> +}
> +struct nums {int vals[4];};
> +
> +void sparx5_set (int *ptr, struct nums *sg, int index)
> +{
> +  int *val = &sg->vals[index]; /* { dg-warning "is above array bounds" } */
> +
> +  assign(0,    ptr, index);
> +  assign(*val, ptr, index);
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |   int *val = &sg->vals[index];
> +      |               ~~~~~~~~^~~~~~~
> +  'sparx5_set': events 1-2
> +   NN |   if (index >= 4)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +      |               ~~~~~~~~~~~~~~~
> +      |                       |
> +      |                       (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | struct nums {int vals[4];};
> +      |                  ^~~~
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_1.c 
> b/gcc/testsuite/gcc.dg/pr109071_1.c
> new file mode 100644
> index 00000000000..592a9989752
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_1.c
> @@ -0,0 +1,36 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR88771, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +typedef struct {
> +  int a;
> +} * b;
> +
> +char *c, *x;
> +int f;
> +
> +void d() {
> +  b e;
> +  char a = f + 1 ?: f;
> +  __builtin_strncpy(c, x, f); /* { dg-warning "exceeds maximum object size" 
> } */
> +  if (a)
> +    e->a = 0;
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |   __builtin_strncpy(c, x, f);
> +      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~
> +  'd': events 1-2
> +   NN |   char a = f + 1 ?: f;
> +      |        ^
> +      |        |
> +      |        (1) when the condition is evaluated to false
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |   __builtin_strncpy(c, x, f);
> +      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~
> +      |   |
> +      |   (2) warning happens here
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_10.c 
> b/gcc/testsuite/gcc.dg/pr109071_10.c
> new file mode 100644
> index 00000000000..1fe7edc7ac9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_10.c
> @@ -0,0 +1,85 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to compiler optimization.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=3" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#define MAX_LENGTH 10
> +int a[MAX_LENGTH];
> +
> +void __attribute__ ((noinline))  foo (int i, bool is_dollar)
> +{
> +  if (i < MAX_LENGTH)
> +    {
> +      if (i == -1)
> +        {
> +          if (is_dollar)
> +            __builtin_printf ("dollar");
> +          else
> +            __builtin_printf ("euro");
> +          a[i] = -1; /* { dg-warning "is below array bounds of" } */
> +        }
> +      else
> +        a[i] = i;
> +    }
> +  else
> +    a[i] = i + 1; /* { dg-warning "is above array bounds of" } */
> +}
> +
> +int main ()
> +{
> +  for (int i = 0; i < MAX_LENGTH; i++)
> +    foo (i, true);
> +  return 0;
> +}
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = i + 1;
> +      |     ~^~~
> +  'foo': events 1-2
> +   NN |   if (i < MAX_LENGTH)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to false
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = i + 1;
> +      |     ~~~~
> +      |      |
> +      |      (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |           a[i] = -1;
> +      |           ~^~~
> +  'foo': events 1-3
> +   NN |   if (i < MAX_LENGTH)
> +      |      ~
> +      |      |
> +      |      (2) when the condition is evaluated to true
> +   NN |     {
> +   NN |       if (i == -1)
> +      |          ^
> +      |          |
> +      |          (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |           a[i] = -1;
> +      |           ~~~~
> +      |            |
> +      |            (3) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> +
> diff --git a/gcc/testsuite/gcc.dg/pr109071_11.c 
> b/gcc/testsuite/gcc.dg/pr109071_11.c
> new file mode 100644
> index 00000000000..b9973bd85da
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_11.c
> @@ -0,0 +1,89 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to compiler optimization.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=3" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#define MAX_LENGTH 10
> +int a[MAX_LENGTH];
> +
> +void __attribute__ ((noinline))  foo (int i, bool is_day, bool is_dollar)
> +{
> +  if (i < MAX_LENGTH)
> +    {
> +      if (is_day)
> +        __builtin_printf ("day");
> +      else
> +        __builtin_printf ("night");
> +      if (i == -1)
> +        {
> +          if (is_dollar)
> +            __builtin_printf ("dollar");
> +          else
> +            __builtin_printf ("euro");
> +          a[i] = -1; /* { dg-warning "is below array bounds of" } */
> +        }
> +      else
> +        a[i] = i;
> +    }
> +  else
> +    a[i] = i + 1; /* { dg-warning "is above array bounds of" } */
> +}
> +
> +int main ()
> +{
> +  for (int i = 0; i < MAX_LENGTH; i++)
> +    foo (i, false, true);
> +  return 0;
> +}
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = i + 1;
> +      |     ~^~~
> +  'foo': events 1-2
> +   NN |   if (i < MAX_LENGTH)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to false
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = i + 1;
> +      |     ~~~~
> +      |      |
> +      |      (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |           a[i] = -1;
> +      |           ~^~~
> +  'foo': events 1-3
> +   NN |   if (i < MAX_LENGTH)
> +      |      ~
> +      |      |
> +      |      (2) when the condition is evaluated to true
> +......
> +   NN |       if (i == -1)
> +      |          ^
> +      |          |
> +      |          (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |           a[i] = -1;
> +      |           ~~~~
> +      |            |
> +      |            (3) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> +
> diff --git a/gcc/testsuite/gcc.dg/pr109071_12.c 
> b/gcc/testsuite/gcc.dg/pr109071_12.c
> new file mode 100644
> index 00000000000..a77ae884ed7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_12.c
> @@ -0,0 +1,44 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   to test the alias option -fdiagnostics-show-context.  */
> +/* { dg-options "-O2 -Wall -fdiagnostics-show-context" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +
> +extern void warn(void);
> +static inline void assign(int val, int *regs, int index)
> +{
> +  if (index >= 4)
> +    warn();
> +  *regs = val;
> +}
> +struct nums {int vals[4];};
> +
> +void sparx5_set (int *ptr, struct nums *sg, int index)
> +{
> +  int *val = &sg->vals[index]; /* { dg-warning "is above array bounds" } */
> +
> +  assign(0,    ptr, index);
> +  assign(*val, ptr, index);
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |   int *val = &sg->vals[index];
> +      |               ~~~~~~~~^~~~~~~
> +  'sparx5_set': events 1-2
> +   NN |   if (index >= 4)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +      |               ~~~~~~~~~~~~~~~
> +      |                       |
> +      |                       (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | struct nums {int vals[4];};
> +      |                  ^~~~
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_2.c 
> b/gcc/testsuite/gcc.dg/pr109071_2.c
> new file mode 100644
> index 00000000000..549a8c4ed87
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_2.c
> @@ -0,0 +1,50 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR85788, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +int b=10;
> +int *d = &b, *e;
> +void a(void *k, long l) {
> +  long f = __builtin_object_size(k, 0);
> +  __builtin___memset_chk(k, b, l, f); /* { dg-warning "is out of the bounds" 
> } */
> +}
> +typedef struct {
> +  int g;
> +  int h;
> +  char i[8000 * 8];
> +} j;
> +static void make_str_raster(j *k) {
> +  int *c = d;
> +  for (; c; c = e)
> +    k->g = k->h = 32767;
> +
> +  a(k->i, k->g / 8 * k->h);
> +  for (; d;)
> +    ;
> +}
> +j m;
> +void n() { make_str_raster(&m); }
> +/* { dg-begin-multiline-output "" }
> +   NN |   __builtin___memset_chk(k, b, l, f);
> +      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +  'n': events 1-2
> +   NN |   __builtin___memset_chk(k, b, l, f);
> +      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +      |   |
> +      |   (2) warning happens here
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |   for (; c; c = e)
> +      |          ^
> +      |          |
> +      |          (1) when the condition is evaluated to false
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | j m;
> +      |   ^
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_3.c 
> b/gcc/testsuite/gcc.dg/pr109071_3.c
> new file mode 100644
> index 00000000000..c7b86ebd060
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_3.c
> @@ -0,0 +1,42 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR108770, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +extern void put(int i);
> +int check_idx(int i) {
> +  if (i > 1)
> +    put(i);
> +  return i;
> +}
> +const char *arr[] = {"A", 0};
> +void init() {
> +  int i = 0;
> +  while (arr[check_idx(i)] != 0) { /* { dg-warning "is above array bounds 
> of" } */
> +    if (arr[check_idx(i)]) {}
> +    i++;
> +  }
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |   while (arr[check_idx(i)] != 0) {
> +      |          ~~~^~~~~~~~~~~~~~
> +  'init': events 1-2
> +   NN |   if (i > 1)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |   while (arr[check_idx(i)] != 0) {
> +      |          ~~~~~~~~~~~~~~~~~
> +      |             |
> +      |             (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | const char *arr[] = {"A", 0};
> +      |             ^~~
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_4.c 
> b/gcc/testsuite/gcc.dg/pr109071_4.c
> new file mode 100644
> index 00000000000..308249ea674
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_4.c
> @@ -0,0 +1,41 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR106762, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +typedef long unsigned int size_t;
> +
> +struct obj_t { size_t field0; size_t field1; };
> +struct obj_array_t { size_t objcnt; struct obj_t* objary; };
> +
> +extern void *memset (void *__s, int __c, size_t __n) __attribute__ 
> ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__(1)));
> +
> +void bug(struct obj_array_t* ary)
> +{
> + size_t idx = 0;
> + struct obj_t* obj;
> + if (idx < ary->objcnt)
> +  obj = &ary->objary[idx];
> + else
> +  obj = 0;
> + memset(&obj->field1, 0xff, sizeof(obj->field1)); /* { dg-warning "is out of 
> the bounds" } */
> + obj->field0 = 0;
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |  memset(&obj->field1, 0xff, sizeof(obj->field1));
> +      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +  'bug': events 1-2
> +   NN |  if (idx < ary->objcnt)
> +      |     ^
> +      |     |
> +      |     (1) when the condition is evaluated to false
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |  memset(&obj->field1, 0xff, sizeof(obj->field1));
> +      |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +      |  |
> +      |  (2) warning happens here
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_5.c 
> b/gcc/testsuite/gcc.dg/pr109071_5.c
> new file mode 100644
> index 00000000000..466d5181dc7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_5.c
> @@ -0,0 +1,33 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR115274, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -Wstringop-overread -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#include <string.h>
> +char *c;
> +void a(long);
> +int b(char *d) { return strlen(d); } /* { dg-warning "or more bytes from a 
> region of size 0" } */
> +void e() {
> +  long f = 1;
> +  f = b(c + f);
> +  if (c == 0)
> +    a(f);
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN | int b(char *d) { return strlen(d); }
> +      |                         ^~~~~~~~~
> +  'e': events 1-2
> +   NN | int b(char *d) { return strlen(d); }
> +      |                         ~~~~~~~~~
> +      |                         |
> +      |                         (2) warning happens here
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |   if (c == 0)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_6.c 
> b/gcc/testsuite/gcc.dg/pr109071_6.c
> new file mode 100644
> index 00000000000..eddf15b350c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_6.c
> @@ -0,0 +1,49 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to code duplication from jump threading.
> +   test case is from PR117179, which is a duplication of PR109071.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +const char* commands[] = {"a", "b"};
> +
> +int setval_internal(int comind)
> +{
> +  if (comind > sizeof(commands)/sizeof(commands[0])) {
> +    return 0;
> +  }
> +
> +  return 1;
> +}
> +
> +_Bool setval_internal_tilde(int comind, const char *com,
> +                           const char *val)
> +{
> +  int ret = setval_internal(comind);
> +  if (commands[comind] == "b" && /* { dg-warning "is outside array bounds 
> of" } */
> +
> +      ret)
> +    return 1;
> +  return 0;
> +}
> +/* { dg-begin-multiline-output "" }
> +   NN |   if (commands[comind] == "b" &&
> +      |       ~~~~~~~~^~~~~~~~
> +  'setval_internal_tilde': events 1-2
> +   NN |   if (comind > sizeof(commands)/sizeof(commands[0])) {
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |   if (commands[comind] == "b" &&
> +      |       ~~~~~~~~~~~~~~~~
> +      |               |
> +      |               (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | const char* commands[] = {"a", "b"};
> +      |             ^~~~~~~~
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_7.c 
> b/gcc/testsuite/gcc.dg/pr109071_7.c
> new file mode 100644
> index 00000000000..a54a9f5dea5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_7.c
> @@ -0,0 +1,44 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to compiler optimization.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#define MAX_LENGTH 10
> +int a[MAX_LENGTH];
> +
> +void __attribute__ ((noinline))  foo (int i)
> +{
> +  if (i == 12)
> +    a[i] = -1; /* { dg-warning "is above array bounds of" } */
> +  else
> +    a[i] = i;
> +}
> +
> +int main ()
> +{
> +  for (int i = 0; i < MAX_LENGTH; i++)
> +    foo (i);
> +  return 0;
> +}
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = -1;
> +      |     ~^~~
> +  'foo': events 1-2
> +   NN |   if (i == 12)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |     a[i] = -1;
> +      |     ~~~~
> +      |      |
> +      |      (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_8.c 
> b/gcc/testsuite/gcc.dg/pr109071_8.c
> new file mode 100644
> index 00000000000..13af458e1b2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_8.c
> @@ -0,0 +1,51 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to compiler optimization.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#define MAX_LENGTH 10
> +int a[MAX_LENGTH];
> +
> +void __attribute__ ((noinline))  foo (int i, bool is_dollar)
> +{
> +  if (i == -1)
> +    {
> +      if (is_dollar)
> +       __builtin_printf ("dollar");
> +      else
> +       __builtin_printf ("euro");
> +      a[i] = -1; /* { dg-warning "is below array bounds of" } */
> +    }
> +  else
> +    a[i] = i;
> +}
> +
> +int main ()
> +{
> +  for (int i = 0; i < MAX_LENGTH; i++)
> +    foo (i, true);
> +  return 0;
> +}
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |       a[i] = -1;
> +      |       ~^~~
> +  'foo': events 1-2
> +   NN |   if (i == -1)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |       a[i] = -1;
> +      |       ~~~~
> +      |        |
> +      |        (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr109071_9.c 
> b/gcc/testsuite/gcc.dg/pr109071_9.c
> new file mode 100644
> index 00000000000..48925717692
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr109071_9.c
> @@ -0,0 +1,61 @@
> +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings
> +   due to compiler optimization.  */
> +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } */
> +/* { dg-additional-options "-fdiagnostics-show-line-numbers 
> -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
> +/* { dg-enable-nn-line-numbers "" } */
> +#define MAX_LENGTH 10
> +int a[MAX_LENGTH];
> +
> +void __attribute__ ((noinline))  foo (int i, bool is_dollar,
> +                                     bool is_hour, bool is_color)
> +{
> +  if (i == -1)
> +    {
> +      if (is_dollar)
> +       __builtin_printf ("dollar");
> +      else
> +       __builtin_printf ("euro");
> +      if (is_hour)
> +       __builtin_printf ("hour");
> +      else
> +       {
> +         if (is_color)
> +           __builtin_printf ("color minute");
> +         else
> +           __builtin_printf ("non minute");
> +       }
> +      a[i] = -1; /* { dg-warning "is below array bounds of" } */
> +    }
> +  else
> +    a[i] = i;
> +}
> +
> +int main ()
> +{
> +  for (int i = 0; i < MAX_LENGTH; i++)
> +    foo (i, true, false, true);
> +  return 0;
> +}
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |       a[i] = -1;
> +      |       ~^~~
> +  'foo': events 1-2
> +   NN |   if (i == -1)
> +      |      ^
> +      |      |
> +      |      (1) when the condition is evaluated to true
> +......
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN |       a[i] = -1;
> +      |       ~~~~
> +      |        |
> +      |        (2) warning happens here
> +   { dg-end-multiline-output "" } */
> +
> +/* { dg-begin-multiline-output "" }
> +   NN | int a[MAX_LENGTH];
> +      |     ^
> +   { dg-end-multiline-output "" } */
> diff --git a/gcc/testsuite/gcc.dg/pr117375.c b/gcc/testsuite/gcc.dg/pr117375.c
> new file mode 100644
> index 00000000000..9679a034d6d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr117375.c
> @@ -0,0 +1,13 @@
> +/* PR middle-end/117375 ICE with -fdiagnostics-show-context=1 patch in sink 
> pass.  */
> +/*    { dg-do compile }
> +      { dg-options "-O2 -Wall -fdiagnostics-show-context=1" } */
> +
> +int st, st_0;
> +int nbFilledBytes, max;
> +void ec_enc_shrink();
> +void max_allowed() {
> +  int nbAvailableBytes = nbFilledBytes;
> +  if (st && st_0)
> +    if (max < nbAvailableBytes)
> +      ec_enc_shrink();
> +}
> --
> 2.43.5
>

Reply via email to