Hi, David,

> On Jul 25, 2025, at 16:16, David Malcolm <dmalc...@redhat.com> wrote:
> 
> 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).

Thanks for the patch, I will add it to the next version of the patch. 
> 
> 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).

Okay, thanks a lot for the help.

Qing

> 
> 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();
>> +}
> 
> <0001-Fixups-to-v7-of-Qing-s-patch-for-r16-2520-g6d9152659.patch>

Reply via email to