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>