On Wed, 2025-07-23 at 20:01 +0000, Qing Zhao wrote: > Hi, > > This is the 7th version of the patches for fixing PR109071.
I just pushed a big reorganization of GCC's diagnostics subsystem to trunk as r16-2520-g6d9152659f4f6a through r16-2553-gbae1f7e29816b9: [PATCH 00/34] Introduce "gcc/diagnostics" subdirectory and "diagnostics::" namespace https://gcc.gnu.org/pipermail/gcc-patches/2025-July/690629.html which moves various headers and symbols around, and this breaks the build of Qing's patch; sorry about this. However the fix is reasonably simple; I'm attaching it to this mail (the attached applies cumulatively on top of the v7 patch, if you're based on r16-2520-g6d9152659f4f6a or later). FWIW I'm thinking about reworking diagnostic paths so that they're always lazily created, using the lazily_created<T> template I just added. I'll take a look at what this does to the patch (given that Qing's patch is the primary use-case for lazily-created diagnostic paths). Dave > > Adding -fdiagnotics-show-context=N into GCC to provide context > information > to the end users on how the warnings come from, in order to help the > user > to locate the exact location in source code on the specific warnings > due to compiler optimizations. > > Richard reviewed the 6th version of the patches, and provided the > following > suggestions for the Middle end changes: > > 1. Change the name of the option to -fdiagnostic-show-context=N. > 2. The data structure "move_history" actually does not carry any new > information > than the available control flow graph, no need to add it. > 3. Display the control condition for the select diagnostics when > -fdiagnostic-show-context=N is specified. > 4. Add the changes from Kees on gimple-ssa-warn-restrict.cc: > https://gcc.gnu.org/pipermail/gcc-patches/2025-May/684126.html > 5. Add more testing cases. (Richard and Kees's): > https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686323.html > https://gcc.gnu.org/pipermail/gcc-patches/2025-June/685852.html > https://gcc.gnu.org/pipermail/gcc-patches/2025-June/685854.html > All the testing cases in 6th version are kept. > And also some more compilcated testing cases. > > 6. Bootstrap GCC with the new -fdiagnostics-show-context=1 on by > default (Init (1)). > fixed all the issues. > > The diagnostic part of the changes keep the same as 6th version, > which David > has reviewed already. > > In the new file "diagnostic-context-rich-location.cc", the routine > "lazy_diagnostic_context_path::make_inner_path" is the one that back > trace > CFG to form the proper events for the path. that's the key for this > whole > change. > > The comments for the routine should clearly describe the heuristic > used to > form the path. > > bootstrapping and regression testing on both x86 and aarch64. No > issues. > > Okay for trunk? > > thanks a lot. > > Qing > > ======================================== > > -fdiagnostics-show-context=N > > With this option, the compiler might print the interesting control > flow > chain that guards the basic block of the statement which has the > warning. > N is the maximum depth of the control flow chain. > Currently, The list of the impacted warning options includes: > -Warray-bounds, -Wstringop-overflow, -Wstringop-overread, > -Wstringop-truncation, and -Wrestrict. > More warning options might be added to this list in future releases. > > For example: > > $ cat t.c > extern void warn(void); > static inline void assign(int val, int *regs, int *index) > { > if (*index >= 4) > warn(); > *regs = val; > } > struct nums {int vals[4];}; > > void sparx5_set (int *ptr, struct nums *sg, int index) > { > int *val = &sg->vals[index]; > > assign(0, ptr, &index); > assign(*val, ptr, &index); > } > > $ gcc -Wall -O2 -c -o t.o t.c > t.c: In function ‘sparx5_set’: > t.c:12:23: warning: array subscript 4 is above array bounds of > ‘int[4]’ [-Warray-bounds=] > 12 | int *val = &sg->vals[index]; > | ~~~~~~~~^~~~~~~ > t.c:8:18: note: while referencing ‘vals’ > 8 | struct nums {int vals[4];}; > | ^~~~ > > In the above, Although the warning is correct in theory, the warning > message > itself is confusing to the end-user since there is information that > cannot > be connected to the source code directly. > > It will be a nice improvement to add more information in the warning > message > to report where such index value come from. > > With the new option -fdiagnostics-show-context=1, the warning message > for > the above testing case is now: > > $ gcc -Wall -O2 -fdiagnostics-show-context=1 -c -o t.o t.c > t.c: In function ‘sparx5_set’: > t.c:12:23: warning: array subscript 4 is above array bounds of > ‘int[4]’ [-Warray-bounds=] > 12 | int *val = &sg->vals[index]; > | ~~~~~~~~^~~~~~~ > ‘sparx5_set’: events 1-2 > 4 | if (*index >= 4) > | ^ > | | > | (1) when the condition is evaluated to true > ...... > 12 | int *val = &sg->vals[index]; > | ~~~~~~~~~~~~~~~ > | | > | (2) warning happens here > t.c:8:18: note: while referencing ‘vals’ > 8 | struct nums {int vals[4];}; > | ^~~~ > > PR tree-optimization/109071 > PR tree-optimization/85788 > PR tree-optimization/88771 > PR tree-optimization/106762 > PR tree-optimization/108770 > PR tree-optimization/115274 > PR tree-optimization/117179 > > gcc/ChangeLog: > > * Makefile.in (OBJS): Add diagnostic-context-rich- > location.o. > * common.opt (fdiagnostics-show-context=): New option. > * diagnostic-context-rich-location.cc: New file. > * diagnostic-context-rich-location.h: New file. > * doc/invoke.texi (fdiagnostics-details): Add > documentation for the new option. > * gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add > one new parameter. Use rich location with details for > warning_at. > (array_bounds_checker::check_array_ref): Use rich location > with > ditails for warning_at. > (array_bounds_checker::check_mem_ref): Add one new > parameter. > Use rich location with details for warning_at. > (array_bounds_checker::check_addr_expr): Use rich location > with > move_history_diagnostic_path for warning_at. > (array_bounds_checker::check_array_bounds): Call > check_mem_ref with > one more parameter. > * gimple-array-bounds.h: Update prototype for check_mem_ref. > * gimple-ssa-warn-access.cc (warn_string_no_nul): Use rich > location > with details for warning_at. > (maybe_warn_nonstring_arg): Likewise. > (maybe_warn_for_bound): Likewise. > (warn_for_access): Likewise. > (check_access): Likewise. > (pass_waccess::check_strncat): Likewise. > (pass_waccess::maybe_check_access_sizes): Likewise. > * gimple-ssa-warn-restrict.cc (pass_wrestrict::execute): > Calculate > dominance info for diagnostics show context. > (maybe_diag_overlap): Use rich location with details for > warning_at. > (maybe_diag_access_bounds): Use rich location with details > for > warning_at. > > gcc/testsuite/ChangeLog: > > * gcc.dg/pr109071.c: New test. > * gcc.dg/pr109071_1.c: New test. > * gcc.dg/pr109071_10.c: New test. > * gcc.dg/pr109071_11.c: New test. > * gcc.dg/pr109071_2.c: New test. > * gcc.dg/pr109071_3.c: New test. > * gcc.dg/pr109071_4.c: New test. > * gcc.dg/pr109071_5.c: New test. > * gcc.dg/pr109071_6.c: New test. > * gcc.dg/pr109071_7.c: New test. > * gcc.dg/pr109071_8.c: New test. > * gcc.dg/pr109071_9.c: New test. > * gcc.dg/pr117375.c: New test. > --- > gcc/Makefile.in | 1 + > gcc/common.opt | 4 + > gcc/diagnostic-context-rich-location.cc | 178 > ++++++++++++++++++++++++ > gcc/diagnostic-context-rich-location.h | 73 ++++++++++ > gcc/doc/invoke.texi | 12 ++ > gcc/gimple-array-bounds.cc | 38 ++--- > gcc/gimple-array-bounds.h | 2 +- > gcc/gimple-ssa-warn-access.cc | 131 +++++++++-------- > gcc/gimple-ssa-warn-restrict.cc | 66 +++++---- > gcc/testsuite/gcc.dg/pr109071.c | 43 ++++++ > gcc/testsuite/gcc.dg/pr109071_1.c | 36 +++++ > gcc/testsuite/gcc.dg/pr109071_10.c | 85 +++++++++++ > gcc/testsuite/gcc.dg/pr109071_11.c | 89 ++++++++++++ > gcc/testsuite/gcc.dg/pr109071_2.c | 50 +++++++ > gcc/testsuite/gcc.dg/pr109071_3.c | 42 ++++++ > gcc/testsuite/gcc.dg/pr109071_4.c | 41 ++++++ > gcc/testsuite/gcc.dg/pr109071_5.c | 33 +++++ > gcc/testsuite/gcc.dg/pr109071_6.c | 49 +++++++ > gcc/testsuite/gcc.dg/pr109071_7.c | 44 ++++++ > gcc/testsuite/gcc.dg/pr109071_8.c | 51 +++++++ > gcc/testsuite/gcc.dg/pr109071_9.c | 61 ++++++++ > gcc/testsuite/gcc.dg/pr117375.c | 13 ++ > 22 files changed, 1043 insertions(+), 99 deletions(-) > create mode 100644 gcc/diagnostic-context-rich-location.cc > create mode 100644 gcc/diagnostic-context-rich-location.h > create mode 100644 gcc/testsuite/gcc.dg/pr109071.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_1.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_10.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_11.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_2.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_3.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_4.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_5.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_6.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_7.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_8.c > create mode 100644 gcc/testsuite/gcc.dg/pr109071_9.c > create mode 100644 gcc/testsuite/gcc.dg/pr117375.c > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 05dfa0871be..ea9263070dc 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1623,6 +1623,7 @@ OBJS = \ > mcf.o \ > mode-switching.o \ > modulo-sched.o \ > + diagnostic-context-rich-location.o \ > multiple_target.o \ > omp-offload.o \ > omp-expand.o \ > diff --git a/gcc/common.opt b/gcc/common.opt > index d68d7d8d914..be6a5e6c27f 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -1618,6 +1618,10 @@ fdiagnostics-minimum-margin-width= > Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6) > Set minimum width of left margin of source code when showing source. > > +fdiagnostics-show-context= > +Common Joined UInteger Var(flag_diagnostics_show_context) Init(0) > +Collect and print more context information for diagnostics. > + > fdisable- > Common Joined RejectNegative Var(common_deferred_options) Defer > -fdisable-[tree|rtl|ipa]-<pass>=range1+range2 Disable an > optimization pass. > diff --git a/gcc/diagnostic-context-rich-location.cc > b/gcc/diagnostic-context-rich-location.cc > new file mode 100644 > index 00000000000..022fc960862 > --- /dev/null > +++ b/gcc/diagnostic-context-rich-location.cc > @@ -0,0 +1,178 @@ > +/* A rich_location subclass that lazily populates a diagnostic_path > + with diagnostic context events, but only if the path is actually > to be > + used. > + > + Copyright (C) 2025 Free Software Foundation, Inc. > + Contributed by Qing Zhao<qing.z...@oracle.com> > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT > ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public > License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#define INCLUDE_MEMORY > +#include "config.h" > +#include "system.h" > +#include "coretypes.h" > +#include "backend.h" > +#include "tree.h" > +#include "gimple.h" > +#include "gimple-iterator.h" > +#include "cfganal.h" > +#include "simple-diagnostic-path.h" > +#include "diagnostic-context-rich-location.h" > + > +/* Implemenation of the method make_inner_path of the class > + lazy_diagnostic_context_path. */ > + > +std::unique_ptr<diagnostic_path> > +lazy_diagnostic_context_path::make_inner_path () const > +{ > + auto path = std::make_unique<simple_diagnostic_path> > + (m_logical_loc_mgr, > + global_dc->get_reference_printer ()); > + if (!flag_diagnostics_show_context) > + return path; > + if (!m_stmt) > + return path; > + > + /* For the following more complicated code: > + if (i < 10) > + { > + if (is_day) > + __builtin_printf ("day"); > + else > + __builtin_printf ("night"); > + > + if (i == -1) > + { > + if (is_dollar) > + __builtin_printf ("dollar"); > + else > + __builtin_printf ("euro"); > + a[i] = -1; ===> warning here. > + } > + else > + a[i] = i; > + } > + else > + a[i] = i + 1; > + > + it has the following CFG: > + > + B2 > + / \ > + V \ > + B3 \ > + / \ \ > + V V \ > + B4 B5 V > + \ / B12 > + V > + B6 > + / \ > + V V > + B7 B11 > + / \ > + V V > + B8 B9 > + \ / > + V > + B10 (warning here) > + > + If the STMT that has warning is in B10, and the interesting > conditions for > + the diagnostic is in the edges B6->B7, and B2->B3, There are two > steps to > + locate the interesting control flow chain: > + > + depth = 0; > + cur_bb = B10; > + Step1: If cur_bb does not have any single predecessor, We should > locate to > + its immediate dominator that has a single predecessor first. > + (B7 when cur_bb is B10). > + Step2: For this immediate dominator, backtrace the CFG to its > single > + predecessor (B6 when cur_bb is B10), locate the conditional > statement in > + the end of the block (B6), determine whether the immediate > dominator block > + block (B7) is on the taken path of the condition. > + Add the conditional statement and whether the immediate > dominator block is > + on the taken path to each event of the path. > + depth++; > + > + then set cur_bb to B6, repeat step1 till the entry block of the > function > + or the value of depth exceed flag_diagnostics_show_context. */ > + > + basic_block cur_bb = gimple_bb (m_stmt); > + if (!cur_bb) > + return path; > + basic_block prev_cond_bb = NULL; > + int depth = 0; > + > + do { > + /* Step 1: locate the immediate dominator that has a single > predecessor of > + cur_bb. */ > + do { > + prev_cond_bb = single_pred_p (cur_bb) > + ? single_pred (cur_bb) : NULL; > + if (!prev_cond_bb && dom_info_available_p (cfun, > CDI_DOMINATORS)) > + cur_bb = get_immediate_dominator (CDI_DOMINATORS, cur_bb); > + else > + break; > + } > + while (!prev_cond_bb && cur_bb != ENTRY_BLOCK_PTR_FOR_FN > (cfun)); > + > + if (!prev_cond_bb) > + return path; > + > + /* Step 2. backtrace the single predecessor chain to locate the > conditional > + statement. */ > + do { > + /* If the prev_cond_bb ends with a conditional statement, get > it. */ > + gimple *cond_stmt = NULL; > + gimple_stmt_iterator gsi = gsi_last_bb (prev_cond_bb); > + if (!gsi_end_p (gsi) > + && gsi_stmt (gsi) > + && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND)) > + cond_stmt = gsi_stmt (gsi); > + > + /* If there is no conditional statement in the prev_cond_bb > and there > + is no single predecessor, stop. */ > + if (!cond_stmt && !single_pred_p (prev_cond_bb)) > + break; > + else if (cond_stmt) > + { > + depth++; > + > + /* Get the edge from the prev_cond_bb to cur_bb, to > determine whether > + the stmt is on the taken path of the conditional > statement. */ > + edge e = find_edge (prev_cond_bb, cur_bb); > + bool is_branch_taken = BRANCH_EDGE (prev_cond_bb) == e; > + path->add_event (gimple_location (cond_stmt), cfun->decl, > 1, > + "when the condition is evaluated to %s", > + is_branch_taken ? "true" : "false"); > + } > + cur_bb = prev_cond_bb; > + prev_cond_bb = single_pred_p (cur_bb) > + ? single_pred (cur_bb) : NULL; > + } > + while (prev_cond_bb && depth < flag_diagnostics_show_context); > + } > + while (prev_cond_bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) > + && depth < flag_diagnostics_show_context); > + > + > + /* Add an end of path warning event in the end of the path. */ > + if (path->num_events () > 0) > + path->add_event (m_location, cfun->decl, 1, > + "warning happens here"); > + return path; > +} > diff --git a/gcc/diagnostic-context-rich-location.h b/gcc/diagnostic- > context-rich-location.h > new file mode 100644 > index 00000000000..075d2f7bed6 > --- /dev/null > +++ b/gcc/diagnostic-context-rich-location.h > @@ -0,0 +1,73 @@ > +/* A rich_location subclass that lazily populates a diagnostic_path > + with diagnostic context events, but only if the path is actually > to be > + used. > + Copyright (C) 2025 Free Software Foundation, Inc. > + Contributed by Qing Zhao<qing.z...@oracle.com> > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT > ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public > License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#ifndef GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H > +#define GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H > + > +#include "gcc-rich-location.h" > +#include "lazy-diagnostic-path.h" > +#include "tree-logical-location.h" > + > +class lazy_diagnostic_context_path : public lazy_diagnostic_path > +{ > +public: > + lazy_diagnostic_context_path (const tree_logical_location_manager > + &logical_loc_mgr, > + location_t location, gimple *stmt) > + : lazy_diagnostic_path (logical_loc_mgr), > + m_logical_loc_mgr (logical_loc_mgr), > + m_location (location), m_stmt (stmt) > + { > + } > + > + std::unique_ptr<diagnostic_path> > + make_inner_path () const final override; > + /* This method will be called on demand if a diagnostic is > actually > + emitted for this rich_location. */ > + > + const tree_logical_location_manager &m_logical_loc_mgr; > + location_t m_location; > + gimple *m_stmt; > +}; > + > +class rich_location_with_details : public gcc_rich_location > +{ > +public: > + rich_location_with_details (location_t location, gimple *stmt) > + : gcc_rich_location (location), > + m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, > stmt) > + { > + set_path (&m_lazy_diagnostic_context_path); > + } > + > + rich_location_with_details (location_t location, tree exp > ATTRIBUTE_UNUSED) > + : gcc_rich_location (location), > + m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, > nullptr) > + { > + } > + > +private: > + const tree_logical_location_manager m_logical_loc_mgr; > + lazy_diagnostic_context_path m_lazy_diagnostic_context_path; > +}; > + > +#endif // GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 09802303254..acba0569952 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -332,6 +332,7 @@ Objective-C and Objective-C++ Dialects}. > -fdiagnostics-column-origin=@var{origin} > -fdiagnostics-escape-format=@r{[}unicode@r{|}bytes@r{]} > > -fdiagnostics-text-art-charset=@r{[}none@r{|}ascii@r{|}unicode@r{|}emoji@r{ > ]}} > +-fdiagnostics-show-context=@var{depth} > > @item Warning Options > @xref{Warning Options,,Options to Request or Suppress Warnings}. > @@ -5764,6 +5765,17 @@ left margin. > This option controls the minimum width of the left margin printed by > @option{-fdiagnostics-show-line-numbers}. It defaults to 6. > > +@opindex fdiagnostics-show-context > +@item -fdiagnostics-show-context=@var{depth} > +With this option, the compiler might print the interesting control > flow > +chain that guards the basic block of the statement which has the > warning. > +@var{depth} is the maximum depth of the control flow chain. > +Currently, The list of the impacted warning options includes: > +@option{-Warray-bounds}, @option{-Wstringop-overflow}, > +@option{-Wstringop-overread}, @option{-Wstringop-truncation}. > +and @option{-Wrestrict}. > +More warning options might be added to this list in future releases. > + > @opindex fdiagnostics-parseable-fixits > @item -fdiagnostics-parseable-fixits > Emit fix-it hints in a machine-parseable format, suitable for > consumption > diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc > index 22286cbb4cc..b62eb192b0a 100644 > --- a/gcc/gimple-array-bounds.cc > +++ b/gcc/gimple-array-bounds.cc > @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree-dfa.h" > #include "fold-const.h" > #include "diagnostic-core.h" > +#include "diagnostic-context-rich-location.h" > #include "intl.h" > #include "tree-vrp.h" > #include "alloc-pool.h" > @@ -262,6 +263,7 @@ get_up_bounds_for_array_ref (tree ref, tree > *decl, > > static bool > check_out_of_bounds_and_warn (location_t location, tree ref, > + gimple *stmt, > tree low_sub_org, tree low_sub, tree > up_sub, > tree up_bound, tree up_bound_p1, > const irange *vr, > @@ -275,12 +277,13 @@ check_out_of_bounds_and_warn (location_t > location, tree ref, > bool warned = false; > *out_of_bound = false; > > + rich_location_with_details richloc (location, stmt); > /* Empty array. */ > if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1)) > { > *out_of_bound = true; > if (for_array_bound) > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %E is outside array" > " bounds of %qT", low_sub_org, artype); > } > @@ -299,7 +302,7 @@ check_out_of_bounds_and_warn (location_t > location, tree ref, > { > *out_of_bound = true; > if (for_array_bound) > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript [%E, %E] is > outside " > "array bounds of %qT", > low_sub, up_sub, artype); > @@ -313,7 +316,7 @@ check_out_of_bounds_and_warn (location_t > location, tree ref, > { > *out_of_bound = true; > if (for_array_bound) > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %E is above array > bounds of %qT", > up_sub, artype); > } > @@ -322,7 +325,7 @@ check_out_of_bounds_and_warn (location_t > location, tree ref, > { > *out_of_bound = true; > if (for_array_bound) > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %E is below array > bounds of %qT", > low_sub, artype); > } > @@ -388,15 +391,16 @@ array_bounds_checker::check_array_ref > (location_t location, tree ref, > } > } > > - warned = check_out_of_bounds_and_warn (location, ref, > + warned = check_out_of_bounds_and_warn (location, ref, stmt, > low_sub_org, low_sub, > up_sub, > up_bound, up_bound_p1, &vr, > ignore_off_by_one, > warn_array_bounds, > &out_of_bound); > > + rich_location_with_details richloc (location, stmt); > > if (!warned && sam == special_array_member::int_0) > - warned = warning_at (location, OPT_Wzero_length_bounds, > + warned = warning_at (&richloc, OPT_Wzero_length_bounds, > (TREE_CODE (low_sub) == INTEGER_CST > ? G_("array subscript %E is outside the > bounds " > "of an interior zero-length array > %qT") > @@ -420,7 +424,7 @@ array_bounds_checker::check_array_ref (location_t > location, tree ref, > && DECL_NOT_FLEXARRAY (afield_decl)) > { > bool warned1 > - = warning_at (location, OPT_Wstrict_flex_arrays, > + = warning_at (&richloc, OPT_Wstrict_flex_arrays, > "trailing array %qT should not be used as " > "a flexible array member", > artype); > @@ -478,6 +482,7 @@ array_bounds_checker::check_array_ref (location_t > location, tree ref, > > bool > array_bounds_checker::check_mem_ref (location_t location, tree ref, > + gimple *stmt, > bool ignore_off_by_one) > { > if (warning_suppressed_p (ref, OPT_Warray_bounds_)) > @@ -576,16 +581,17 @@ array_bounds_checker::check_mem_ref (location_t > location, tree ref, > } > } > > + rich_location_with_details richloc (location, stmt); > bool warned = false; > if (lboob) > { > if (offrange[0] == offrange[1]) > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %wi is outside array > bounds " > "of %qT", > offrange[0].to_shwi (), reftype); > else > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript [%wi, %wi] is outside > " > "array bounds of %qT", > offrange[0].to_shwi (), > @@ -599,8 +605,7 @@ array_bounds_checker::check_mem_ref (location_t > location, tree ref, > it were an untyped array of bytes. */ > backtype = build_array_type_nelts (unsigned_char_type_node, > aref.sizrng[1].to_uhwi > ()); > - > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %<%T[%wi]%> is partly " > "outside array bounds of %qT", > axstype, offrange[0].to_shwi (), > backtype); > @@ -623,7 +628,7 @@ array_bounds_checker::check_mem_ref (location_t > location, tree ref, > { > HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi (); > > - if (warning_at (location, OPT_Warray_bounds_, > + if (warning_at (&richloc, OPT_Warray_bounds_, > "intermediate array offset %wi is outside > array bounds " > "of %qT", tmpidx, reftype)) > { > @@ -656,7 +661,7 @@ array_bounds_checker::check_addr_expr (location_t > location, tree t, > ignore_off_by_one = false; > } > else if (TREE_CODE (t) == MEM_REF) > - warned = check_mem_ref (location, t, ignore_off_by_one); > + warned = check_mem_ref (location, t, stmt, > ignore_off_by_one); > > if (warned) > suppress_warning (t, OPT_Warray_bounds_); > @@ -692,6 +697,7 @@ array_bounds_checker::check_addr_expr (location_t > location, tree t, > if (!mem_ref_offset (t).is_constant (&idx)) > return; > > + rich_location_with_details richloc (location, stmt); > bool warned = false; > idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz)); > if (idx < 0) > @@ -702,7 +708,7 @@ array_bounds_checker::check_addr_expr (location_t > location, tree t, > dump_generic_expr (MSG_NOTE, TDF_SLIM, t); > fprintf (dump_file, "\n"); > } > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %wi is below " > "array bounds of %qT", > idx.to_shwi (), TREE_TYPE (tem)); > @@ -716,7 +722,7 @@ array_bounds_checker::check_addr_expr (location_t > location, tree t, > dump_generic_expr (MSG_NOTE, TDF_SLIM, t); > fprintf (dump_file, "\n"); > } > - warned = warning_at (location, OPT_Warray_bounds_, > + warned = warning_at (&richloc, OPT_Warray_bounds_, > "array subscript %wu is above " > "array bounds of %qT", > idx.to_uhwi (), TREE_TYPE (tem)); > @@ -811,7 +817,7 @@ array_bounds_checker::check_array_bounds (tree > *tp, int *walk_subtree, > warned = checker->check_array_ref (location, t, wi->stmt, > false/*ignore_off_by_one*/); > else if (TREE_CODE (t) == MEM_REF) > - warned = checker->check_mem_ref (location, t, > + warned = checker->check_mem_ref (location, t, wi->stmt, > false /*ignore_off_by_one*/); > else if (TREE_CODE (t) == ADDR_EXPR) > { > diff --git a/gcc/gimple-array-bounds.h b/gcc/gimple-array-bounds.h > index bdf8a3428a6..611bcdf17e3 100644 > --- a/gcc/gimple-array-bounds.h > +++ b/gcc/gimple-array-bounds.h > @@ -33,7 +33,7 @@ public: > private: > static tree check_array_bounds (tree *tp, int *walk_subtree, void > *data); > bool check_array_ref (location_t, tree, gimple *, bool > ignore_off_by_one); > - bool check_mem_ref (location_t, tree, bool ignore_off_by_one); > + bool check_mem_ref (location_t, tree, gimple *, bool > ignore_off_by_one); > void check_addr_expr (location_t, tree, gimple *); > void get_value_range (irange &r, const_tree op, gimple *); > > diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn- > access.cc > index 0f4aff6b59b..abfb8685ce7 100644 > --- a/gcc/gimple-ssa-warn-access.cc > +++ b/gcc/gimple-ssa-warn-access.cc > @@ -57,6 +57,7 @@ > #include "pointer-query.h" > #include "pretty-print-markup.h" > #include "gcc-urlifier.h" > +#include "diagnostic-context-rich-location.h" > > /* Return true if tree node X has an associated location. */ > > @@ -169,17 +170,19 @@ warn_string_no_nul (location_t loc, > GimpleOrTree expr, const char *fname, > if (expr) > { > tree func = get_callee_fndecl (expr); > + rich_location_with_details richloc (loc, expr); > + > if (bndrng) > { > if (wi::ltu_p (maxsiz, bndrng[0])) > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD specified bound %s exceeds " > "maximum object size %E", > func, bndstr, maxobjsize); > else > { > bool maybe = wi::to_wide (size) == bndrng[0]; > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > exact > ? G_("%qD specified bound %s > exceeds " > "the size %E of unterminated > array") > @@ -194,7 +197,7 @@ warn_string_no_nul (location_t loc, GimpleOrTree > expr, const char *fname, > } > } > else > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD argument missing terminating nul", > func); > } > @@ -486,14 +489,16 @@ maybe_warn_nonstring_arg (tree fndecl, > GimpleOrTree exp) > tree maxobjsize = max_object_size (); > if (tree_int_cst_lt (maxobjsize, bndrng[0])) > { > + rich_location_with_details richloc (loc, exp); > + > bool warned = false; > if (tree_int_cst_equal (bndrng[0], bndrng[1])) > - warned = warning_at (loc, OPT_Wstringop_overread, > + warned = warning_at (&richloc, OPT_Wstringop_overread, > "%qD specified bound %E " > "exceeds maximum object size %E", > fndecl, bndrng[0], maxobjsize); > else > - warned = warning_at (loc, OPT_Wstringop_overread, > + warned = warning_at (&richloc, OPT_Wstringop_overread, > "%qD specified bound [%E, %E] " > "exceeds maximum object size %E", > fndecl, bndrng[0], bndrng[1], > @@ -645,20 +650,21 @@ maybe_warn_nonstring_arg (tree fndecl, > GimpleOrTree exp) > auto_diagnostic_group d; > if (wi::ltu_p (asize, wibnd)) > { > + rich_location_with_details richloc (loc, exp); > if (bndrng[0] == bndrng[1]) > - warned = warning_at (loc, OPT_Wstringop_overread, > + warned = warning_at (&richloc, OPT_Wstringop_overread, > "%qD argument %i declared attribute > " > "%<nonstring%> is smaller than the > specified " > "bound %wu", > fndecl, argno + 1, wibnd.to_uhwi > ()); > else if (wi::ltu_p (asize, wi::to_offset (bndrng[0]))) > - warned = warning_at (loc, OPT_Wstringop_overread, > + warned = warning_at (&richloc, OPT_Wstringop_overread, > "%qD argument %i declared attribute > " > "%<nonstring%> is smaller than " > "the specified bound [%E, %E]", > fndecl, argno + 1, bndrng[0], > bndrng[1]); > else > - warned = warning_at (loc, OPT_Wstringop_overread, > + warned = warning_at (&richloc, OPT_Wstringop_overread, > "%qD argument %i declared attribute > " > "%<nonstring%> may be smaller than > " > "the specified bound [%E, %E]", > @@ -730,16 +736,17 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > auto_diagnostic_group d; > if (tree_int_cst_lt (maxobjsize, bndrng[0])) > { > + rich_location_with_details richloc (loc, exp); > if (bndrng[0] == bndrng[1]) > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound %E > may " > "exceed maximum object > size %E") > : G_("%qD specified bound %E " > "exceeds maximum object > size %E")), > func, bndrng[0], maxobjsize) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound %E may " > "exceed maximum object > size %E") > @@ -748,7 +755,7 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > bndrng[0], maxobjsize)); > else > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound [%E, > %E] may " > "exceed maximum object > size %E") > @@ -756,7 +763,7 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > "exceeds maximum object > size %E")), > func, > bndrng[0], bndrng[1], > maxobjsize) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound [%E, %E] > may " > "exceed maximum object > size %E") > @@ -767,37 +774,43 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > else if (!size || tree_int_cst_le (bndrng[0], size)) > return false; > else if (tree_int_cst_equal (bndrng[0], bndrng[1])) > - warned = (func > - ? warning_at (loc, opt, > + { > + rich_location_with_details richloc (loc, exp); > + warned = (func > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound %E may > exceed " > "source size %E") > : G_("%qD specified bound %E > exceeds " > "source size %E")), > func, bndrng[0], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound %E may exceed > " > "source size %E") > : G_("specified bound %E exceeds " > "source size %E")), > bndrng[0], size)); > + } > else > - warned = (func > - ? warning_at (loc, opt, > + { > + rich_location_with_details richloc (loc, exp); > + warned = (func > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound [%E, %E] > may " > "exceed source size %E") > : G_("%qD specified bound [%E, %E] > exceeds " > "source size %E")), > func, bndrng[0], bndrng[1], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound [%E, %E] may > exceed " > "source size %E") > : G_("specified bound [%E, %E] > exceeds " > "source size %E")), > bndrng[0], bndrng[1], size)); > + } > if (warned) > { > if (pad && pad->src.ref > @@ -811,6 +824,7 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > } > > bool maybe = pad && pad->dst.phi (); > + rich_location_with_details richloc (loc, exp); > if (maybe) > { > /* Issue a "maybe" warning only if the PHI refers to objects > @@ -824,14 +838,14 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > { > if (bndrng[0] == bndrng[1]) > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified size %E may " > "exceed maximum object size > %E") > : G_("%qD specified size %E " > "exceeds maximum object size > %E")), > func, bndrng[0], maxobjsize) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified size %E may exceed > " > "maximum object size %E") > @@ -840,14 +854,14 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > bndrng[0], maxobjsize)); > else > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified size between %E > and %E " > "may exceed maximum object > size %E") > : G_("%qD specified size between %E > and %E " > "exceeds maximum object size > %E")), > func, bndrng[0], bndrng[1], > maxobjsize) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified size between %E and > %E " > "may exceed maximum object > size %E") > @@ -859,14 +873,14 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > return false; > else if (tree_int_cst_equal (bndrng[0], bndrng[1])) > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound %E may exceed > " > "destination size %E") > : G_("%qD specified bound %E exceeds " > "destination size %E")), > func, bndrng[0], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound %E may exceed " > "destination size %E") > @@ -875,14 +889,14 @@ maybe_warn_for_bound (opt_code opt, location_t > loc, GimpleOrTree exp, tree func, > bndrng[0], size)); > else > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD specified bound [%E, %E] may > exceed " > "destination size %E") > : G_("%qD specified bound [%E, %E] > exceeds " > "destination size %E")), > func, bndrng[0], bndrng[1], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("specified bound [%E, %E] exceeds > " > "destination size %E") > @@ -933,11 +947,13 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > bool warned = false; > > + rich_location_with_details richloc (loc, exp); > + > if (write && read) > { > if (tree_int_cst_equal (range[0], range[1])) > warned = (func > - ? warning_n (loc, opt, tree_to_uhwi (range[0]), > + ? warning_n (&richloc, opt, tree_to_uhwi > (range[0]), > (maybe > ? G_("%qD may access %E byte in a > region " > "of size %E") > @@ -949,7 +965,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > : G_ ("%qD accessing %E bytes in a > region " > "of size %E")), > func, range[0], size) > - : warning_n (loc, opt, tree_to_uhwi (range[0]), > + : warning_n (&richloc, opt, tree_to_uhwi > (range[0]), > (maybe > ? G_("may access %E byte in a region > " > "of size %E") > @@ -965,14 +981,14 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > /* Avoid printing the upper bound if it's invalid. */ > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD may access %E or more > bytes " > "in a region of size %E") > : G_("%qD accessing %E or more > bytes " > "in a region of size %E")), > func, range[0], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("may access %E or more bytes > " > "in a region of size %E") > @@ -982,14 +998,14 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > } > else > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD may access between %E and > %E " > "bytes in a region of size > %E") > : G_("%qD accessing between %E and > %E " > "bytes in a region of size > %E")), > func, range[0], range[1], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("may access between %E and %E > bytes " > "in a region of size %E") > @@ -1003,7 +1019,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > if (tree_int_cst_equal (range[0], range[1])) > warned = (func > - ? warning_n (loc, opt, tree_to_uhwi (range[0]), > + ? warning_n (&richloc, opt, tree_to_uhwi > (range[0]), > (maybe > ? G_("%qD may write %E byte into a > region " > "of size %E") > @@ -1015,7 +1031,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > : G_("%qD writing %E bytes into a > region " > "of size %E overflows the > destination")), > func, range[0], size) > - : warning_n (loc, opt, tree_to_uhwi (range[0]), > + : warning_n (&richloc, opt, tree_to_uhwi > (range[0]), > (maybe > ? G_("may write %E byte into a > region " > "of size %E") > @@ -1031,7 +1047,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > /* Avoid printing the upper bound if it's invalid. */ > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD may write %E or more > bytes " > "into a region of size %E") > @@ -1039,7 +1055,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > "into a region of size %E > overflows " > "the destination")), > func, range[0], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("may write %E or more bytes > into " > "a region of size %E") > @@ -1050,7 +1066,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > } > else > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > (maybe > ? G_("%qD may write between %E and > %E bytes " > "into a region of size %E") > @@ -1058,7 +1074,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > "into a region of size %E > overflows " > "the destination")), > func, range[0], range[1], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("may write between %E and %E > bytes " > "into a region of size %E") > @@ -1073,7 +1089,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > if (tree_int_cst_equal (range[0], range[1])) > warned = (func > - ? warning_n (loc, OPT_Wstringop_overread, > + ? warning_n (&richloc, OPT_Wstringop_overread, > tree_to_uhwi (range[0]), > (maybe > ? G_("%qD may read %E byte from a > region " > @@ -1086,7 +1102,7 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > : G_("%qD reading %E bytes from a > region " > "of size %E")), > func, range[0], size) > - : warning_n (loc, OPT_Wstringop_overread, > + : warning_n (&richloc, OPT_Wstringop_overread, > tree_to_uhwi (range[0]), > (maybe > ? G_("may read %E byte from a region > " > @@ -1103,14 +1119,14 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > /* Avoid printing the upper bound if it's invalid. */ > warned = (func > - ? warning_at (loc, OPT_Wstringop_overread, > + ? warning_at (&richloc, OPT_Wstringop_overread, > (maybe > ? G_("%qD may read %E or more > bytes " > "from a region of size %E") > : G_("%qD reading %E or more > bytes " > "from a region of size > %E")), > func, range[0], size) > - : warning_at (loc, OPT_Wstringop_overread, > + : warning_at (&richloc, OPT_Wstringop_overread, > (maybe > ? G_("may read %E or more bytes " > "from a region of size %E") > @@ -1120,14 +1136,14 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > } > else > warned = (func > - ? warning_at (loc, OPT_Wstringop_overread, > + ? warning_at (&richloc, OPT_Wstringop_overread, > (maybe > ? G_("%qD may read between %E and > %E bytes " > "from a region of size %E") > : G_("%qD reading between %E and %E > bytes " > "from a region of size %E")), > func, range[0], range[1], size) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > (maybe > ? G_("may read between %E and %E > bytes " > "from a region of size %E") > @@ -1144,12 +1160,12 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > if (tree_int_cst_equal (range[0], range[1]) > || tree_int_cst_sign_bit (range[1])) > warned = (func > - ? warning_n (loc, OPT_Wstringop_overread, > + ? warning_n (&richloc, OPT_Wstringop_overread, > tree_to_uhwi (range[0]), > "%qD expecting %E byte in a region of > size %E", > "%qD expecting %E bytes in a region of > size %E", > func, range[0], size) > - : warning_n (loc, OPT_Wstringop_overread, > + : warning_n (&richloc, OPT_Wstringop_overread, > tree_to_uhwi (range[0]), > "expecting %E byte in a region of size > %E", > "expecting %E bytes in a region of size > %E", > @@ -1158,22 +1174,22 @@ warn_for_access (location_t loc, tree func, > GimpleOrTree exp, int opt, > { > /* Avoid printing the upper bound if it's invalid. */ > warned = (func > - ? warning_at (loc, OPT_Wstringop_overread, > + ? warning_at (&richloc, OPT_Wstringop_overread, > "%qD expecting %E or more bytes in a > region " > "of size %E", > func, range[0], size) > - : warning_at (loc, OPT_Wstringop_overread, > + : warning_at (&richloc, OPT_Wstringop_overread, > "expecting %E or more bytes in a > region " > "of size %E", > range[0], size)); > } > else > warned = (func > - ? warning_at (loc, OPT_Wstringop_overread, > + ? warning_at (&richloc, OPT_Wstringop_overread, > "%qD expecting between %E and %E bytes > in " > "a region of size %E", > func, range[0], range[1], size) > - : warning_at (loc, OPT_Wstringop_overread, > + : warning_at (&richloc, OPT_Wstringop_overread, > "expecting between %E and %E bytes in " > "a region of size %E", > range[0], range[1], size)); > @@ -1404,6 +1420,8 @@ check_access (GimpleOrTree exp, tree dstwrite, > > auto_diagnostic_group d; > location_t loc = get_location (exp); > + rich_location_with_details richloc (loc, exp); > + > bool warned = false; > if (dstwrite == slen && at_least_one) > { > @@ -1411,12 +1429,12 @@ check_access (GimpleOrTree exp, tree > dstwrite, > and a source of unknown length. The call will > write > at least one byte past the end of the destination. > */ > warned = (func > - ? warning_at (loc, opt, > + ? warning_at (&richloc, opt, > "%qD writing %E or more bytes > into " > "a region of size %E overflows > " > "the destination", > func, range[0], dstsize) > - : warning_at (loc, opt, > + : warning_at (&richloc, opt, > "writing %E or more bytes into > " > "a region of size %E overflows > " > "the destination", > @@ -2583,7 +2601,9 @@ pass_waccess::check_strncat (gcall *stmt) > && tree_int_cst_equal (destsize, maxread)) > { > location_t loc = get_location (stmt); > - warning_at (loc, OPT_Wstringop_overflow_, > + rich_location_with_details richloc (loc, stmt); > + > + warning_at (&richloc, OPT_Wstringop_overflow_, > "%qD specified bound %E equals destination size", > get_callee_fndecl (stmt), maxread); > > @@ -3464,13 +3484,14 @@ pass_waccess::maybe_check_access_sizes > (rdwr_map *rwm, tree fndecl, tree fntype, > && tree_int_cst_sgn (sizrng[0]) < 0 > && tree_int_cst_sgn (sizrng[1]) < 0) > { > + rich_location_with_details richloc (loc, stmt); > /* Warn about negative sizes. */ > if (access.second.internal_p) > { > const std::string argtypestr > = access.second.array_as_string (ptrtype); > > - if (warning_at (loc, OPT_Wstringop_overflow_, > + if (warning_at (&richloc, OPT_Wstringop_overflow_, > "bound argument %i value %s is " > "negative for a variable length array > " > "argument %i of type %s", > @@ -3478,7 +3499,7 @@ pass_waccess::maybe_check_access_sizes > (rdwr_map *rwm, tree fndecl, tree fntype, > ptridx + 1, argtypestr.c_str ())) > arg_warned = OPT_Wstringop_overflow_; > } > - else if (warning_at (loc, OPT_Wstringop_overflow_, > + else if (warning_at (&richloc, OPT_Wstringop_overflow_, > "argument %i value %s is negative", > sizidx + 1, sizstr)) > arg_warned = OPT_Wstringop_overflow_; > diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn- > restrict.cc > index 47263aa4d34..6da89e50806 100644 > --- a/gcc/gimple-ssa-warn-restrict.cc > +++ b/gcc/gimple-ssa-warn-restrict.cc > @@ -40,6 +40,7 @@ > #include "tree-object-size.h" > #include "calls.h" > #include "cfgloop.h" > +#include "diagnostic-context-rich-location.h" > #include "intl.h" > #include "gimple-range.h" > > @@ -107,10 +108,17 @@ pass_wrestrict::execute (function *fun) > /* Create a new ranger instance and associate it with FUN. */ > m_ptr_qry.rvals = enable_ranger (fun); > > + if (flag_diagnostics_show_context > + && !dom_info_available_p (fun, CDI_DOMINATORS)) > + calculate_dominance_info (CDI_DOMINATORS); > + > basic_block bb; > FOR_EACH_BB_FN (bb, fun) > check_block (bb); > > + if (dom_info_available_p (fun, CDI_DOMINATORS)) > + free_dominance_info (fun, CDI_DOMINATORS); > + > m_ptr_qry.flush_cache (); > > /* Release the ranger instance and replace it with a global > ranger. > @@ -1447,6 +1455,8 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > > tree func = gimple_call_fndecl (call); > > + rich_location_with_details richloc (loc, call); > + > /* To avoid a combinatorial explosion of diagnostics format the > offsets > or their ranges as strings and use them in the warning calls > below. */ > char offstr[3][64]; > @@ -1492,7 +1502,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > if (sizrange[0] == sizrange[1]) > { > if (ovlsiz[0] == ovlsiz[1]) > - warning_at (loc, OPT_Wrestrict, > + warning_at (&richloc, OPT_Wrestrict, > sizrange[0] == 1 > ? (ovlsiz[0] == 1 > ? G_("%qD accessing %wu byte at offsets > %s " > @@ -1509,7 +1519,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > func, sizrange[0], > offstr[0], offstr[1], ovlsiz[0], offstr[2]); > else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi > ()) > - warning_n (loc, OPT_Wrestrict, sizrange[0], > + warning_n (&richloc, OPT_Wrestrict, sizrange[0], > "%qD accessing %wu byte at offsets %s " > "and %s overlaps between %wu and %wu bytes " > "at offset %s", > @@ -1519,7 +1529,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > func, sizrange[0], offstr[0], offstr[1], > ovlsiz[0], ovlsiz[1], offstr[2]); > else > - warning_n (loc, OPT_Wrestrict, sizrange[0], > + warning_n (&richloc, OPT_Wrestrict, sizrange[0], > "%qD accessing %wu byte at offsets %s and " > "%s overlaps %wu or more bytes at offset %s", > "%qD accessing %wu bytes at offsets %s and " > @@ -1532,7 +1542,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ()) > { > if (ovlsiz[0] == ovlsiz[1]) > - warning_n (loc, OPT_Wrestrict, ovlsiz[0], > + warning_n (&richloc, OPT_Wrestrict, ovlsiz[0], > "%qD accessing between %wu and %wu bytes " > "at offsets %s and %s overlaps %wu byte at " > "offset %s", > @@ -1542,7 +1552,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > func, sizrange[0], sizrange[1], > offstr[0], offstr[1], ovlsiz[0], offstr[2]); > else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi > ()) > - warning_at (loc, OPT_Wrestrict, > + warning_at (&richloc, OPT_Wrestrict, > "%qD accessing between %wu and %wu bytes at > " > "offsets %s and %s overlaps between %wu and > %wu " > "bytes at offset %s", > @@ -1550,7 +1560,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], > offstr[2]); > else > - warning_at (loc, OPT_Wrestrict, > + warning_at (&richloc, OPT_Wrestrict, > "%qD accessing between %wu and %wu bytes at > " > "offsets %s and %s overlaps %wu or more > bytes " > "at offset %s", > @@ -1563,7 +1573,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > ovlsiz[1] = maxobjsize.to_shwi (); > > if (ovlsiz[0] == ovlsiz[1]) > - warning_n (loc, OPT_Wrestrict, ovlsiz[0], > + warning_n (&richloc, OPT_Wrestrict, ovlsiz[0], > "%qD accessing %wu or more bytes at offsets " > "%s and %s overlaps %wu byte at offset %s", > "%qD accessing %wu or more bytes at offsets " > @@ -1571,14 +1581,14 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > func, sizrange[0], offstr[0], offstr[1], > ovlsiz[0], offstr[2]); > else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) > - warning_at (loc, OPT_Wrestrict, > + warning_at (&richloc, OPT_Wrestrict, > "%qD accessing %wu or more bytes at offsets %s " > "and %s overlaps between %wu and %wu bytes " > "at offset %s", > func, sizrange[0], offstr[0], offstr[1], > ovlsiz[0], ovlsiz[1], offstr[2]); > else > - warning_at (loc, OPT_Wrestrict, > + warning_at (&richloc, OPT_Wrestrict, > "%qD accessing %wu or more bytes at offsets %s " > "and %s overlaps %wu or more bytes at offset > %s", > func, sizrange[0], offstr[0], offstr[1], > @@ -1606,14 +1616,14 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > if (ovlsiz[1] == 1) > { > if (open_range) > - warning_n (loc, OPT_Wrestrict, sizrange[1], > + warning_n (&richloc, OPT_Wrestrict, sizrange[1], > "%qD accessing %wu byte may overlap " > "%wu byte", > "%qD accessing %wu bytes may overlap " > "%wu byte", > func, sizrange[1], ovlsiz[1]); > else > - warning_n (loc, OPT_Wrestrict, sizrange[1], > + warning_n (&richloc, OPT_Wrestrict, sizrange[1], > "%qD accessing %wu byte at offsets %s " > "and %s may overlap %wu byte at offset %s", > "%qD accessing %wu bytes at offsets %s " > @@ -1624,14 +1634,14 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > } > > if (open_range) > - warning_n (loc, OPT_Wrestrict, sizrange[1], > + warning_n (&richloc, OPT_Wrestrict, sizrange[1], > "%qD accessing %wu byte may overlap " > "up to %wu bytes", > "%qD accessing %wu bytes may overlap " > "up to %wu bytes", > func, sizrange[1], ovlsiz[1]); > else > - warning_n (loc, OPT_Wrestrict, sizrange[1], > + warning_n (&richloc, OPT_Wrestrict, sizrange[1], > "%qD accessing %wu byte at offsets %s and " > "%s may overlap up to %wu bytes at offset %s", > "%qD accessing %wu bytes at offsets %s and " > @@ -1644,14 +1654,14 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ()) > { > if (open_range) > - warning_n (loc, OPT_Wrestrict, ovlsiz[1], > + warning_n (&richloc, OPT_Wrestrict, ovlsiz[1], > "%qD accessing between %wu and %wu bytes " > "may overlap %wu byte", > "%qD accessing between %wu and %wu bytes " > "may overlap up to %wu bytes", > func, sizrange[0], sizrange[1], ovlsiz[1]); > else > - warning_n (loc, OPT_Wrestrict, ovlsiz[1], > + warning_n (&richloc, OPT_Wrestrict, ovlsiz[1], > "%qD accessing between %wu and %wu bytes " > "at offsets %s and %s may overlap %wu byte " > "at offset %s", > @@ -1663,7 +1673,7 @@ maybe_diag_overlap (location_t loc, gimple > *call, builtin_access &acs) > return true; > } > > - warning_n (loc, OPT_Wrestrict, ovlsiz[1], > + warning_n (&richloc, OPT_Wrestrict, ovlsiz[1], > "%qD accessing %wu or more bytes at offsets %s " > "and %s may overlap %wu byte at offset %s", > "%qD accessing %wu or more bytes at offsets %s " > @@ -1693,6 +1703,8 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > location_t loc = gimple_location (call); > const offset_int maxobjsize = ref.maxobjsize; > > + rich_location_with_details richloc (loc, call); > + > /* Check for excessive size first and regardless of warning > options > since the result is used to make codegen decisions. */ > if (ref.sizrange[0] > maxobjsize) > @@ -1709,13 +1721,13 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > if (warn_stringop_overflow) > { > if (ref.sizrange[0] == ref.sizrange[1]) > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD specified bound %wu " > "exceeds maximum object size %wu", > func, ref.sizrange[0].to_uhwi (), > maxobjsize.to_uhwi ()); > else > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD specified bound between %wu > and %wu " > "exceeds maximum object size %wu", > func, ref.sizrange[0].to_uhwi (), > @@ -1776,7 +1788,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE) > { > auto_diagnostic_group d; > - if (warning_at (loc, opt, > + if (warning_at (&richloc, opt, > "%qD pointer overflow between offset %s " > "and size %s accessing array %qD with type > %qT", > func, rangestr[0], rangestr[1], ref.base, > type)) > @@ -1786,13 +1798,13 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > warned = true; > } > else > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD pointer overflow between > offset %s " > "and size %s", > func, rangestr[0], rangestr[1]); > } > else > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > "%qD pointer overflow between offset %s > " > "and size %s", > func, rangestr[0], rangestr[1]); > @@ -1808,7 +1820,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > { > auto_diagnostic_group d; > if ((ref.basesize < maxobjsize > - && warning_at (loc, opt, > + && warning_at (&richloc, opt, > form > ? G_("%qD forming offset %s is out of > " > "the bounds [0, %wu] of object > %qD with " > @@ -1817,7 +1829,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > "[0, %wu] of object %qD with type > %qT"), > func, rangestr[0], > ref.basesize.to_uhwi (), > ref.base, TREE_TYPE (ref.base))) > - || warning_at (loc, opt, > + || warning_at (&richloc, opt, > form > ? G_("%qD forming offset %s is out of " > "the bounds of object %qD with > type %qT") > @@ -1832,7 +1844,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > } > } > else if (ref.basesize < maxobjsize) > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > form > ? G_("%qD forming offset %s is out " > "of the bounds [0, %wu]") > @@ -1840,7 +1852,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > "of the bounds [0, %wu]"), > func, rangestr[0], ref.basesize.to_uhwi > ()); > else > - warned = warning_at (loc, opt, > + warned = warning_at (&richloc, opt, > form > ? G_("%qD forming offset %s is out of > bounds") > : G_("%qD offset %s is out of bounds"), > @@ -1854,7 +1866,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > type = TREE_TYPE (type); > type = TYPE_MAIN_VARIANT (type); > > - if (warning_at (loc, opt, > + if (warning_at (&richloc, opt, > "%qD offset %s from the object at %qE is out " > "of the bounds of %qT", > func, rangestr[0], ref.base, type)) > @@ -1872,7 +1884,7 @@ maybe_diag_access_bounds (gimple *call, tree > func, int strict, > tree refop = TREE_OPERAND (ref.ref, 0); > tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); > > - if (warning_at (loc, opt, > + if (warning_at (&richloc, opt, > "%qD offset %s from the object at %qE is out " > "of the bounds of referenced subobject %qD > with " > "type %qT at offset %wi", > diff --git a/gcc/testsuite/gcc.dg/pr109071.c > b/gcc/testsuite/gcc.dg/pr109071.c > new file mode 100644 > index 00000000000..74b7b46221e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071.c > @@ -0,0 +1,43 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. */ > +/* { dg-options "-O2 -Wall -fdiagnostics-show-context=1" } */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > + > +extern void warn(void); > +static inline void assign(int val, int *regs, int index) > +{ > + if (index >= 4) > + warn(); > + *regs = val; > +} > +struct nums {int vals[4];}; > + > +void sparx5_set (int *ptr, struct nums *sg, int index) > +{ > + int *val = &sg->vals[index]; /* { dg-warning "is above array > bounds" } */ > + > + assign(0, ptr, index); > + assign(*val, ptr, index); > +} > +/* { dg-begin-multiline-output "" } > + NN | int *val = &sg->vals[index]; > + | ~~~~~~~~^~~~~~~ > + 'sparx5_set': events 1-2 > + NN | if (index >= 4) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + | ~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | struct nums {int vals[4];}; > + | ^~~~ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_1.c > b/gcc/testsuite/gcc.dg/pr109071_1.c > new file mode 100644 > index 00000000000..592a9989752 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_1.c > @@ -0,0 +1,36 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR88771, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -fdiagnostics-show-context=1" } */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +typedef struct { > + int a; > +} * b; > + > +char *c, *x; > +int f; > + > +void d() { > + b e; > + char a = f + 1 ?: f; > + __builtin_strncpy(c, x, f); /* { dg-warning "exceeds maximum > object size" } */ > + if (a) > + e->a = 0; > +} > +/* { dg-begin-multiline-output "" } > + NN | __builtin_strncpy(c, x, f); > + | ^~~~~~~~~~~~~~~~~~~~~~~~~~ > + 'd': events 1-2 > + NN | char a = f + 1 ?: f; > + | ^ > + | | > + | (1) when the condition is evaluated to false > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | __builtin_strncpy(c, x, f); > + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_10.c > b/gcc/testsuite/gcc.dg/pr109071_10.c > new file mode 100644 > index 00000000000..1fe7edc7ac9 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_10.c > @@ -0,0 +1,85 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to compiler optimization. */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=3" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#define MAX_LENGTH 10 > +int a[MAX_LENGTH]; > + > +void __attribute__ ((noinline)) foo (int i, bool is_dollar) > +{ > + if (i < MAX_LENGTH) > + { > + if (i == -1) > + { > + if (is_dollar) > + __builtin_printf ("dollar"); > + else > + __builtin_printf ("euro"); > + a[i] = -1; /* { dg-warning "is below array bounds of" } */ > + } > + else > + a[i] = i; > + } > + else > + a[i] = i + 1; /* { dg-warning "is above array bounds of" } */ > +} > + > +int main () > +{ > + for (int i = 0; i < MAX_LENGTH; i++) > + foo (i, true); > + return 0; > +} > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = i + 1; > + | ~^~~ > + 'foo': events 1-2 > + NN | if (i < MAX_LENGTH) > + | ^ > + | | > + | (1) when the condition is evaluated to false > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = i + 1; > + | ~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~^~~ > + 'foo': events 1-3 > + NN | if (i < MAX_LENGTH) > + | ~ > + | | > + | (2) when the condition is evaluated to true > + NN | { > + NN | if (i == -1) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~~~~ > + | | > + | (3) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > + > diff --git a/gcc/testsuite/gcc.dg/pr109071_11.c > b/gcc/testsuite/gcc.dg/pr109071_11.c > new file mode 100644 > index 00000000000..b9973bd85da > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_11.c > @@ -0,0 +1,89 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to compiler optimization. */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=3" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#define MAX_LENGTH 10 > +int a[MAX_LENGTH]; > + > +void __attribute__ ((noinline)) foo (int i, bool is_day, bool > is_dollar) > +{ > + if (i < MAX_LENGTH) > + { > + if (is_day) > + __builtin_printf ("day"); > + else > + __builtin_printf ("night"); > + if (i == -1) > + { > + if (is_dollar) > + __builtin_printf ("dollar"); > + else > + __builtin_printf ("euro"); > + a[i] = -1; /* { dg-warning "is below array bounds of" } */ > + } > + else > + a[i] = i; > + } > + else > + a[i] = i + 1; /* { dg-warning "is above array bounds of" } */ > +} > + > +int main () > +{ > + for (int i = 0; i < MAX_LENGTH; i++) > + foo (i, false, true); > + return 0; > +} > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = i + 1; > + | ~^~~ > + 'foo': events 1-2 > + NN | if (i < MAX_LENGTH) > + | ^ > + | | > + | (1) when the condition is evaluated to false > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = i + 1; > + | ~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~^~~ > + 'foo': events 1-3 > + NN | if (i < MAX_LENGTH) > + | ~ > + | | > + | (2) when the condition is evaluated to true > +...... > + NN | if (i == -1) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~~~~ > + | | > + | (3) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > + > diff --git a/gcc/testsuite/gcc.dg/pr109071_2.c > b/gcc/testsuite/gcc.dg/pr109071_2.c > new file mode 100644 > index 00000000000..549a8c4ed87 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_2.c > @@ -0,0 +1,50 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR85788, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +int b=10; > +int *d = &b, *e; > +void a(void *k, long l) { > + long f = __builtin_object_size(k, 0); > + __builtin___memset_chk(k, b, l, f); /* { dg-warning "is out of the > bounds" } */ > +} > +typedef struct { > + int g; > + int h; > + char i[8000 * 8]; > +} j; > +static void make_str_raster(j *k) { > + int *c = d; > + for (; c; c = e) > + k->g = k->h = 32767; > + > + a(k->i, k->g / 8 * k->h); > + for (; d;) > + ; > +} > +j m; > +void n() { make_str_raster(&m); } > +/* { dg-begin-multiline-output "" } > + NN | __builtin___memset_chk(k, b, l, f); > + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + 'n': events 1-2 > + NN | __builtin___memset_chk(k, b, l, f); > + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | for (; c; c = e) > + | ^ > + | | > + | (1) when the condition is evaluated to false > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | j m; > + | ^ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_3.c > b/gcc/testsuite/gcc.dg/pr109071_3.c > new file mode 100644 > index 00000000000..c7b86ebd060 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_3.c > @@ -0,0 +1,42 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR108770, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +extern void put(int i); > +int check_idx(int i) { > + if (i > 1) > + put(i); > + return i; > +} > +const char *arr[] = {"A", 0}; > +void init() { > + int i = 0; > + while (arr[check_idx(i)] != 0) { /* { dg-warning "is above array > bounds of" } */ > + if (arr[check_idx(i)]) {} > + i++; > + } > +} > +/* { dg-begin-multiline-output "" } > + NN | while (arr[check_idx(i)] != 0) { > + | ~~~^~~~~~~~~~~~~~ > + 'init': events 1-2 > + NN | if (i > 1) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | while (arr[check_idx(i)] != 0) { > + | ~~~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | const char *arr[] = {"A", 0}; > + | ^~~ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_4.c > b/gcc/testsuite/gcc.dg/pr109071_4.c > new file mode 100644 > index 00000000000..308249ea674 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_4.c > @@ -0,0 +1,41 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR106762, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +typedef long unsigned int size_t; > + > +struct obj_t { size_t field0; size_t field1; }; > +struct obj_array_t { size_t objcnt; struct obj_t* objary; }; > + > +extern void *memset (void *__s, int __c, size_t __n) __attribute__ > ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__(1))); > + > +void bug(struct obj_array_t* ary) > +{ > + size_t idx = 0; > + struct obj_t* obj; > + if (idx < ary->objcnt) > + obj = &ary->objary[idx]; > + else > + obj = 0; > + memset(&obj->field1, 0xff, sizeof(obj->field1)); /* { dg-warning > "is out of the bounds" } */ > + obj->field0 = 0; > +} > +/* { dg-begin-multiline-output "" } > + NN | memset(&obj->field1, 0xff, sizeof(obj->field1)); > + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + 'bug': events 1-2 > + NN | if (idx < ary->objcnt) > + | ^ > + | | > + | (1) when the condition is evaluated to false > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | memset(&obj->field1, 0xff, sizeof(obj->field1)); > + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_5.c > b/gcc/testsuite/gcc.dg/pr109071_5.c > new file mode 100644 > index 00000000000..466d5181dc7 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_5.c > @@ -0,0 +1,33 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR115274, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -Wstringop-overread -fdiagnostics-show- > context=1" } */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#include <string.h> > +char *c; > +void a(long); > +int b(char *d) { return strlen(d); } /* { dg-warning "or more bytes > from a region of size 0" } */ > +void e() { > + long f = 1; > + f = b(c + f); > + if (c == 0) > + a(f); > +} > +/* { dg-begin-multiline-output "" } > + NN | int b(char *d) { return strlen(d); } > + | ^~~~~~~~~ > + 'e': events 1-2 > + NN | int b(char *d) { return strlen(d); } > + | ~~~~~~~~~ > + | | > + | (2) warning happens here > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | if (c == 0) > + | ^ > + | | > + | (1) when the condition is evaluated to true > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_6.c > b/gcc/testsuite/gcc.dg/pr109071_6.c > new file mode 100644 > index 00000000000..eddf15b350c > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_6.c > @@ -0,0 +1,49 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to code duplication from jump threading. > + test case is from PR117179, which is a duplication of PR109071. > */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +const char* commands[] = {"a", "b"}; > + > +int setval_internal(int comind) > +{ > + if (comind > sizeof(commands)/sizeof(commands[0])) { > + return 0; > + } > + > + return 1; > +} > + > +_Bool setval_internal_tilde(int comind, const char *com, > + const char *val) > +{ > + int ret = setval_internal(comind); > + if (commands[comind] == "b" && /* { dg-warning "is outside array > bounds of" } */ > + > + ret) > + return 1; > + return 0; > +} > +/* { dg-begin-multiline-output "" } > + NN | if (commands[comind] == "b" && > + | ~~~~~~~~^~~~~~~~ > + 'setval_internal_tilde': events 1-2 > + NN | if (comind > sizeof(commands)/sizeof(commands[0])) { > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | if (commands[comind] == "b" && > + | ~~~~~~~~~~~~~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | const char* commands[] = {"a", "b"}; > + | ^~~~~~~~ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_7.c > b/gcc/testsuite/gcc.dg/pr109071_7.c > new file mode 100644 > index 00000000000..a54a9f5dea5 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_7.c > @@ -0,0 +1,44 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to compiler optimization. */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#define MAX_LENGTH 10 > +int a[MAX_LENGTH]; > + > +void __attribute__ ((noinline)) foo (int i) > +{ > + if (i == 12) > + a[i] = -1; /* { dg-warning "is above array bounds of" } */ > + else > + a[i] = i; > +} > + > +int main () > +{ > + for (int i = 0; i < MAX_LENGTH; i++) > + foo (i); > + return 0; > +} > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~^~~ > + 'foo': events 1-2 > + NN | if (i == 12) > + | ^ > + | | > + | (1) when the condition is evaluated to true > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_8.c > b/gcc/testsuite/gcc.dg/pr109071_8.c > new file mode 100644 > index 00000000000..13af458e1b2 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_8.c > @@ -0,0 +1,51 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to compiler optimization. */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#define MAX_LENGTH 10 > +int a[MAX_LENGTH]; > + > +void __attribute__ ((noinline)) foo (int i, bool is_dollar) > +{ > + if (i == -1) > + { > + if (is_dollar) > + __builtin_printf ("dollar"); > + else > + __builtin_printf ("euro"); > + a[i] = -1; /* { dg-warning "is below array bounds of" } */ > + } > + else > + a[i] = i; > +} > + > +int main () > +{ > + for (int i = 0; i < MAX_LENGTH; i++) > + foo (i, true); > + return 0; > +} > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~^~~ > + 'foo': events 1-2 > + NN | if (i == -1) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr109071_9.c > b/gcc/testsuite/gcc.dg/pr109071_9.c > new file mode 100644 > index 00000000000..48925717692 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr109071_9.c > @@ -0,0 +1,61 @@ > +/* PR tree-optimization/109071 need more context for -Warray-bounds > warnings > + due to compiler optimization. */ > +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-show-context=1" } > */ > +/* { dg-additional-options "-fdiagnostics-show-line-numbers - > fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ > +/* { dg-enable-nn-line-numbers "" } */ > +#define MAX_LENGTH 10 > +int a[MAX_LENGTH]; > + > +void __attribute__ ((noinline)) foo (int i, bool is_dollar, > + bool is_hour, bool is_color) > +{ > + if (i == -1) > + { > + if (is_dollar) > + __builtin_printf ("dollar"); > + else > + __builtin_printf ("euro"); > + if (is_hour) > + __builtin_printf ("hour"); > + else > + { > + if (is_color) > + __builtin_printf ("color minute"); > + else > + __builtin_printf ("non minute"); > + } > + a[i] = -1; /* { dg-warning "is below array bounds of" } */ > + } > + else > + a[i] = i; > +} > + > +int main () > +{ > + for (int i = 0; i < MAX_LENGTH; i++) > + foo (i, true, false, true); > + return 0; > +} > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~^~~ > + 'foo': events 1-2 > + NN | if (i == -1) > + | ^ > + | | > + | (1) when the condition is evaluated to true > +...... > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | a[i] = -1; > + | ~~~~ > + | | > + | (2) warning happens here > + { dg-end-multiline-output "" } */ > + > +/* { dg-begin-multiline-output "" } > + NN | int a[MAX_LENGTH]; > + | ^ > + { dg-end-multiline-output "" } */ > diff --git a/gcc/testsuite/gcc.dg/pr117375.c > b/gcc/testsuite/gcc.dg/pr117375.c > new file mode 100644 > index 00000000000..9679a034d6d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr117375.c > @@ -0,0 +1,13 @@ > +/* PR middle-end/117375 ICE with -fdiagnostics-show-context=1 patch > in sink pass. */ > +/* { dg-do compile } > + { dg-options "-O2 -Wall -fdiagnostics-show-context=1" } */ > + > +int st, st_0; > +int nbFilledBytes, max; > +void ec_enc_shrink(); > +void max_allowed() { > + int nbAvailableBytes = nbFilledBytes; > + if (st && st_0) > + if (max < nbAvailableBytes) > + ec_enc_shrink(); > +}
From 4024c83a921fca5b4c838722fc789d042643576b Mon Sep 17 00:00:00 2001 From: David Malcolm <dmalc...@redhat.com> Date: Fri, 25 Jul 2025 16:08:40 -0400 Subject: [PATCH] Fixups to v7 of Qing's patch for r16-2520-g6d9152659f4f6a through r16-2553-gbae1f7e29816b9 --- gcc/diagnostic-context-rich-location.cc | 2 +- gcc/diagnostic-context-rich-location.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/diagnostic-context-rich-location.cc b/gcc/diagnostic-context-rich-location.cc index 022fc9608627..16d2f2069d19 100644 --- a/gcc/diagnostic-context-rich-location.cc +++ b/gcc/diagnostic-context-rich-location.cc @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see /* Implemenation of the method make_inner_path of the class lazy_diagnostic_context_path. */ -std::unique_ptr<diagnostic_path> +std::unique_ptr<diagnostics::paths::path> lazy_diagnostic_context_path::make_inner_path () const { auto path = std::make_unique<simple_diagnostic_path> diff --git a/gcc/diagnostic-context-rich-location.h b/gcc/diagnostic-context-rich-location.h index 075d2f7bed6c..676b9d23b05c 100644 --- a/gcc/diagnostic-context-rich-location.h +++ b/gcc/diagnostic-context-rich-location.h @@ -24,22 +24,22 @@ along with GCC; see the file COPYING3. If not see #define GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H #include "gcc-rich-location.h" -#include "lazy-diagnostic-path.h" +#include "diagnostics/lazy-paths.h" #include "tree-logical-location.h" -class lazy_diagnostic_context_path : public lazy_diagnostic_path +class lazy_diagnostic_context_path : public diagnostics::paths::lazy_path { public: lazy_diagnostic_context_path (const tree_logical_location_manager &logical_loc_mgr, location_t location, gimple *stmt) - : lazy_diagnostic_path (logical_loc_mgr), + : diagnostics::paths::lazy_path (logical_loc_mgr), m_logical_loc_mgr (logical_loc_mgr), m_location (location), m_stmt (stmt) { } - std::unique_ptr<diagnostic_path> + std::unique_ptr<diagnostics::paths::path> make_inner_path () const final override; /* This method will be called on demand if a diagnostic is actually emitted for this rich_location. */ -- 2.26.3