Hi, This is the 7th version of the patches for fixing PR109071.
Adding -fdiagnotics-show-context=N into GCC to provide context information to the end users on how the warnings come from, in order to help the user to locate the exact location in source code on the specific warnings due to compiler optimizations. 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(); +} -- 2.31.1