On Wed, 2025-07-23 at 20:01 +0000, Qing Zhao wrote:
> Hi,
> 
> This is the 7th version of the patches for fixing PR109071.

I just pushed a big reorganization of GCC's diagnostics subsystem to
trunk as r16-2520-g6d9152659f4f6a through r16-2553-gbae1f7e29816b9: 

[PATCH 00/34] Introduce "gcc/diagnostics" subdirectory and
"diagnostics::" namespace
https://gcc.gnu.org/pipermail/gcc-patches/2025-July/690629.html

which moves various headers and symbols around, and this breaks the
build of Qing's patch; sorry about this.

However the fix is reasonably simple; I'm attaching it to this mail
(the attached applies cumulatively on top of the v7 patch, if you're
based on r16-2520-g6d9152659f4f6a or later).

FWIW I'm thinking about reworking diagnostic paths so that they're
always lazily created, using the lazily_created<T> template I just
added.  I'll take a look at what this does to the patch (given that
Qing's patch is the primary use-case for lazily-created diagnostic
paths).

Dave

> 
> Adding -fdiagnotics-show-context=N into GCC to provide context
> information
> to the end users on how the warnings come from, in order to help the
> user
> to locate the exact location in source code on the specific warnings
> due to compiler optimizations.
> 
> Richard reviewed the 6th version of the patches, and provided the
> following
> suggestions for the Middle end changes:
> 
> 1. Change the name of the option to -fdiagnostic-show-context=N.
> 2. The data structure "move_history" actually does not carry any new
> information
>    than the available control flow graph, no need to add it.
> 3. Display the control condition for the select diagnostics when
>    -fdiagnostic-show-context=N is specified.
> 4. Add the changes from Kees on gimple-ssa-warn-restrict.cc:
> https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684126.html
> 5. Add more testing cases. (Richard and Kees's):
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686323.html
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/685852.html
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/685854.html
> All the testing cases in 6th version are kept.
> And also some more compilcated testing cases.
>  
> 6. Bootstrap GCC with the new -fdiagnostics-show-context=1 on by
> default (Init (1)).
> fixed all the issues.
> 
> The diagnostic part of the changes keep the same as 6th version,
> which David
> has reviewed already.
> 
> In the new file "diagnostic-context-rich-location.cc", the routine
> "lazy_diagnostic_context_path::make_inner_path" is the one that back
> trace
> CFG to form the proper events for the path. that's the key for this
> whole
> change.
> 
> The comments for the routine should clearly describe the heuristic
> used to
> form the path.
> 
> bootstrapping and regression testing on both x86 and aarch64. No
> issues.
> 
> Okay for trunk?
> 
> thanks a lot.
> 
> Qing
> 
> ========================================
> 
> -fdiagnostics-show-context=N
> 
> With this option, the compiler might print the interesting control
> flow
> chain that guards the basic block of the statement which has the
> warning.
> N 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.
> 
> 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.
>       * diagnostic-context-rich-location.cc: New file.
>       * diagnostic-context-rich-location.h: New file.
>       * doc/invoke.texi (fdiagnostics-details): Add
>       documentation for the new option.
>       * 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_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                          |   4 +
>  gcc/diagnostic-context-rich-location.cc | 178
> ++++++++++++++++++++++++
>  gcc/diagnostic-context-rich-location.h  |  73 ++++++++++
>  gcc/doc/invoke.texi                     |  12 ++
>  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         |  66 +++++----
>  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_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 ++
>  22 files changed, 1043 insertions(+), 99 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_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 05dfa0871be..ea9263070dc 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1623,6 +1623,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 d68d7d8d914..be6a5e6c27f 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -1618,6 +1618,10 @@ fdiagnostics-minimum-margin-width=
>  Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
>  Set minimum width of left margin of source code when showing source.
>  
> +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..022fc960862
> --- /dev/null
> +++ b/gcc/diagnostic-context-rich-location.cc
> @@ -0,0 +1,178 @@
> +/* 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 "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<diagnostic_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)
> +    {
> +      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;    ===> warning here.
> +     }
> +      else
> +     a[i] = i;
> +    }
> +  else
> +    a[i] = i + 1;
> +
> +  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, and the interesting
> conditions for
> +  the diagnostic is in the edges B6->B7, and B2->B3, There are two
> steps to
> +  locate the interesting control flow chain:
> +
> +  depth = 0;
> +  cur_bb = B10;
> +  Step1: If cur_bb does not have any single predecessor, We should
> locate to
> +    its immediate dominator that has a single predecessor first.
> +    (B7 when cur_bb is B10).
> +  Step2: For this immediate dominator, backtrace the CFG to its
> single
> +    predecessor (B6 when cur_bb is B10), locate the conditional
> statement in
> +    the end of the block (B6), determine whether the immediate
> dominator block
> +    block (B7) is on the taken path of the condition.
> +    Add the conditional statement and whether the immediate
> dominator block is
> +    on the taken path to each event of the path.
> +    depth++;
> +
> +    then set cur_bb to B6, repeat step1 till the entry block of the
> function
> +    or the value of depth exceed flag_diagnostics_show_context.  */
> +
> +  basic_block cur_bb = gimple_bb (m_stmt);
> +  if (!cur_bb)
> +    return path;
> +  basic_block prev_cond_bb = NULL;
> +  int depth = 0;
> +
> +  do {
> +    /* Step 1: locate the immediate dominator that has a single
> predecessor of
> +       cur_bb.  */
> +    do {
> +      prev_cond_bb = single_pred_p (cur_bb)
> +                  ? single_pred (cur_bb) : NULL;
> +      if (!prev_cond_bb && dom_info_available_p (cfun,
> CDI_DOMINATORS))
> +     cur_bb = get_immediate_dominator (CDI_DOMINATORS, cur_bb);
> +      else
> +     break;
> +    }
> +    while (!prev_cond_bb && cur_bb != ENTRY_BLOCK_PTR_FOR_FN
> (cfun));
> +
> +    if (!prev_cond_bb)
> +      return path;
> +
> +    /* Step 2. backtrace the single predecessor chain to locate the
> conditional
> +       statement.  */
> +    do {
> +      /* If the prev_cond_bb ends with a conditional statement, get
> it.  */
> +      gimple *cond_stmt = NULL;
> +      gimple_stmt_iterator gsi = gsi_last_bb (prev_cond_bb);
> +      if (!gsi_end_p (gsi)
> +       && gsi_stmt (gsi)
> +       && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND))
> +     cond_stmt = gsi_stmt (gsi);
> +
> +      /* If there is no conditional statement in the prev_cond_bb
> and there
> +      is no single predecessor, stop.  */
> +      if (!cond_stmt && !single_pred_p (prev_cond_bb))
> +     break;
> +      else if (cond_stmt)
> +     {
> +       depth++;
> +
> +       /* Get the edge from the prev_cond_bb to cur_bb, to
> determine whether
> +          the stmt is on the taken path of the conditional
> statement.  */
> +       edge e = find_edge (prev_cond_bb, cur_bb);
> +       bool is_branch_taken = BRANCH_EDGE (prev_cond_bb) == e;
> +       path->add_event (gimple_location (cond_stmt), cfun->decl,
> 1,
> +                        "when the condition is evaluated to %s",
> +                        is_branch_taken ? "true" : "false");
> +     }
> +      cur_bb = prev_cond_bb;
> +      prev_cond_bb = single_pred_p (cur_bb)
> +                  ? single_pred (cur_bb) : NULL;
> +    }
> +    while (prev_cond_bb && depth < flag_diagnostics_show_context);
> +  }
> +  while (prev_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..075d2f7bed6
> --- /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 "lazy-diagnostic-path.h"
> +#include "tree-logical-location.h"
> +
> +class lazy_diagnostic_context_path : public lazy_diagnostic_path
> +{
> +public:
> +  lazy_diagnostic_context_path (const tree_logical_location_manager
> +                             &logical_loc_mgr,
> +                             location_t location, gimple *stmt)
> +  : lazy_diagnostic_path (logical_loc_mgr),
> +    m_logical_loc_mgr (logical_loc_mgr),
> +    m_location (location), m_stmt (stmt)
> +  {
> +  }
> +
> +  std::unique_ptr<diagnostic_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 09802303254..acba0569952 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -332,6 +332,7 @@ Objective-C and Objective-C++ Dialects}.
>  -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-show-context=@var{depth}
>  
>  @item Warning Options
>  @xref{Warning Options,,Options to Request or Suppress Warnings}.
> @@ -5764,6 +5765,17 @@ 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}
> +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.
> +
>  @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..6da89e50806 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"
>  
> @@ -107,10 +108,17 @@ pass_wrestrict::execute (function *fun)
>    /* Create a new ranger instance and associate it with FUN.  */
>    m_ptr_qry.rvals = enable_ranger (fun);
>  
> +  if (flag_diagnostics_show_context
> +      && !dom_info_available_p (fun, CDI_DOMINATORS))
> +    calculate_dominance_info (CDI_DOMINATORS);
> +
>    basic_block bb;
>    FOR_EACH_BB_FN (bb, fun)
>      check_block (bb);
>  
> +  if (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 +1455,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 +1502,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 +1519,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 +1529,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 +1542,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 +1552,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 +1560,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 +1573,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 +1581,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 +1616,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 +1634,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 +1654,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 +1673,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 +1703,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 +1721,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 +1788,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 +1798,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 +1820,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 +1829,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 +1844,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 +1852,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 +1866,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 +1884,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_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();
> +}

From 4024c83a921fca5b4c838722fc789d042643576b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalc...@redhat.com>
Date: Fri, 25 Jul 2025 16:08:40 -0400
Subject: [PATCH] Fixups to v7 of Qing's patch for r16-2520-g6d9152659f4f6a
 through r16-2553-gbae1f7e29816b9

---
 gcc/diagnostic-context-rich-location.cc | 2 +-
 gcc/diagnostic-context-rich-location.h  | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/gcc/diagnostic-context-rich-location.cc b/gcc/diagnostic-context-rich-location.cc
index 022fc9608627..16d2f2069d19 100644
--- a/gcc/diagnostic-context-rich-location.cc
+++ b/gcc/diagnostic-context-rich-location.cc
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Implemenation of the method make_inner_path of the class
    lazy_diagnostic_context_path.  */
 
-std::unique_ptr<diagnostic_path>
+std::unique_ptr<diagnostics::paths::path>
 lazy_diagnostic_context_path::make_inner_path () const
 {
   auto path = std::make_unique<simple_diagnostic_path>
diff --git a/gcc/diagnostic-context-rich-location.h b/gcc/diagnostic-context-rich-location.h
index 075d2f7bed6c..676b9d23b05c 100644
--- a/gcc/diagnostic-context-rich-location.h
+++ b/gcc/diagnostic-context-rich-location.h
@@ -24,22 +24,22 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
 
 #include "gcc-rich-location.h"
-#include "lazy-diagnostic-path.h"
+#include "diagnostics/lazy-paths.h"
 #include "tree-logical-location.h"
 
-class lazy_diagnostic_context_path : public lazy_diagnostic_path
+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)
-  : lazy_diagnostic_path (logical_loc_mgr),
+  : diagnostics::paths::lazy_path (logical_loc_mgr),
     m_logical_loc_mgr (logical_loc_mgr),
     m_location (location), m_stmt (stmt)
   {
   }
 
-  std::unique_ptr<diagnostic_path>
+  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.  */
-- 
2.26.3

Reply via email to