Hi,

This is the 8th version of the patches for fixing PR109071.

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.

Compared to the 7th version of the patch:
https://gcc.gnu.org/pipermail/gcc-patches/2025-July/690407.html

there are two major changes:

1. Sam reported two hangs when he tested the v7 with glibc and tinc.
   fixed this issue.
2. David provided the patch for his latest change  r16-2520-g6d9152659f4f6a
   included in the 8th version.

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 event 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 | 189 ++++++++++++++++++++++++
 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, 1054 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 d7d5cbe7277..f57806163c3 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1622,6 +1622,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 70659fabebd..cf015a6e243 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..313266d2dc9
--- /dev/null
+++ b/gcc/diagnostic-context-rich-location.cc
@@ -0,0 +1,189 @@
+/* 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<diagnostics::paths::path>
+lazy_diagnostic_context_path::make_inner_path () const
+{
+  auto path = std::make_unique<simple_diagnostic_path>
+               (m_logical_loc_mgr,
+                global_dc->get_reference_printer ());
+  if (!flag_diagnostics_show_context)
+    return path;
+  if (!m_stmt)
+    return path;
+
+  /* For the following more complicated code:
+  if (i < 10)
+    {
+      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.
+    FIXME: We currently only handle GIMPLE_COND, might extend to GIMPLE_SWITCH
+    later.  */
+
+  basic_block cur_bb = gimple_bb (m_stmt);
+  if (!cur_bb)
+    return path;
+  basic_block prev_cond_bb = NULL;
+  int depth = 0;
+  bool should_terminate = false;
+
+  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
+        the prev_cond_bb has no single predecessor to backtrace, stop
+        completely.  */
+      if (!cond_stmt && !single_pred_p (prev_cond_bb))
+       {
+         should_terminate = true;
+         break;
+       }
+      /* if there is no location information for the cond_stmt, we should not
+        add this event to confuse end user.  */
+      else if (cond_stmt && gimple_location (cond_stmt) != UNKNOWN_LOCATION)
+       {
+         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);
+    if (should_terminate)
+      break;
+  }
+  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..676b9d23b05
--- /dev/null
+++ b/gcc/diagnostic-context-rich-location.h
@@ -0,0 +1,73 @@
+/* A rich_location subclass that lazily populates a diagnostic_path
+   with diagnostic context events, but only if the path is actually to be
+   used.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   Contributed by Qing Zhao<qing.z...@oracle.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
+#define GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
+
+#include "gcc-rich-location.h"
+#include "diagnostics/lazy-paths.h"
+#include "tree-logical-location.h"
+
+class lazy_diagnostic_context_path : public diagnostics::paths::lazy_path
+{
+public:
+  lazy_diagnostic_context_path (const tree_logical_location_manager
+                               &logical_loc_mgr,
+                               location_t location, gimple *stmt)
+  : diagnostics::paths::lazy_path (logical_loc_mgr),
+    m_logical_loc_mgr (logical_loc_mgr),
+    m_location (location), m_stmt (stmt)
+  {
+  }
+
+  std::unique_ptr<diagnostics::paths::path>
+  make_inner_path () const final override;
+  /* This method will be called on demand if a diagnostic is actually
+     emitted for this rich_location.  */
+
+  const tree_logical_location_manager &m_logical_loc_mgr;
+  location_t m_location;
+  gimple *m_stmt;
+};
+
+class rich_location_with_details : public gcc_rich_location
+{
+public:
+  rich_location_with_details (location_t location, gimple *stmt)
+  : gcc_rich_location (location),
+    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, stmt)
+  {
+    set_path (&m_lazy_diagnostic_context_path);
+  }
+
+  rich_location_with_details (location_t location, tree exp ATTRIBUTE_UNUSED)
+  : gcc_rich_location (location),
+    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, nullptr)
+  {
+  }
+
+private:
+  const tree_logical_location_manager m_logical_loc_mgr;
+  lazy_diagnostic_context_path m_lazy_diagnostic_context_path;
+};
+
+#endif // GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e442a9cb73e..9deb2ec37c0 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();
+}
-- 
2.31.1


Reply via email to