aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/infinite-loop.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2024-05-17 14:51:47 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2024-05-17 14:51:47 -0400
commit770657d02c986c8724214dba51f21bb3c299ebae (patch)
treebf526b3e02309e78abf63aacadff15b50f938e7a /gcc/analyzer/infinite-loop.cc
parent6daed961542a9d5e83f9b94a3ee91f918f4268a5 (diff)
downloadgcc-770657d02c986c8724214dba51f21bb3c299ebae.zip
gcc-770657d02c986c8724214dba51f21bb3c299ebae.tar.gz
gcc-770657d02c986c8724214dba51f21bb3c299ebae.tar.bz2
diagnostics, analyzer: add CFG edge visualization to path-printing
This patch adds some ability for links between labelled ranges when quoting the user's source code, and uses this to add links between events when printing diagnostic_paths, chopping them up further into event ranges that can be printed together. It adds links to the various "from..." - "...to" events in the analyzer. For example, previously we emitted this for c-c++-common/analyzer/infinite-loop-linked-list.c's while_loop_missing_next': infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop] 30 | while (n) | ^ 'while_loop_missing_next': events 1-5 30 | while (n) | ^ | | | (1) infinite loop here | (2) when 'n' is non-NULL: always following 'true' branch... | (5) ...to here 31 | { 32 | sum += n->val; | ~~~~~~~~~~~~~ | | | | | (3) ...to here | (4) looping back... whereas with the patch we now emit: infinite-loop-linked-list.c:30:10: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop] 30 | while (n) | ^ 'while_loop_missing_next': events 1-3 30 | while (n) | ^ | | | (1) infinite loop here | (2) when 'n' is non-NULL: always following 'true' branch... ->-+ | | | | |+------------------------------------------------------------------------+ 31 || { 32 || sum += n->val; || ~~~~~~ || | |+------------->(3) ...to here 'while_loop_missing_next': event 4 32 | sum += n->val; | ~~~~^~~~~~~~~ | | | (4) looping back... ->-+ | | 'while_loop_missing_next': event 5 | | |+---------------------------------+ 30 || while (n) || ^ || | |+-------->(5) ...to here which I believe is easier to understand. The patch also implements the use of unicode characters and colorization for the lines (not shown in the above example). There is a new option -fno-diagnostics-show-event-links for getting back the old behavior (added to -fdiagnostics-plain-output). gcc/analyzer/ChangeLog: * checker-event.h (checker_event::connect_to_next_event_p): Implement new diagnostic_event::connect_to_next_event_p vfunc. (start_cfg_edge_event::connect_to_next_event_p): Likewise. (start_consolidated_cfg_edges_event::connect_to_next_event_p): Likewise. * infinite-loop.cc (class looping_back_event): New subclass. (infinite_loop_diagnostic::add_final_event): Use it. gcc/ChangeLog: * common.opt (fdiagnostics-show-event-links): New option. * diagnostic-label-effects.h: New file. * diagnostic-path.h (diagnostic_event::connect_to_next_event_p): New pure virtual function. (simple_diagnostic_event::connect_to_next_event_p): Implement it. (simple_diagnostic_event::connect_to_next_event): New. (simple_diagnostic_event::m_connected_to_next_event): New field. (simple_diagnostic_path::connect_to_next_event): New decl. * diagnostic-show-locus.cc: Include "text-art/theme.h" and "diagnostic-label-effects.h". (colorizer::set_cfg_edge): New. (layout::m_fallback_theme): New field. (layout::m_theme): New field. (layout::m_effect_info): New field. (layout::m_link_lhs_state): New enum and field. (layout::m_link_rhs_column): New field. (layout_range::has_in_edge): New. (layout_range::has_out_edge): New. (layout::layout): Add "effect_info" optional param. Initialize m_theme, m_link_lhs_state, and m_link_rhs_column. (layout::maybe_add_location_range): Remove stray "FIXME" from leading comment. (layout::print_source_line): Replace space after margin with a call to print_leftmost_column. (layout::print_leftmost_column): New. (layout::start_annotation_line): Make non-const. Gain responsibility for printing the leftmost column after the margin. (layout::print_annotation_line): Drop pp_space, as this is now added by start_annotation_line. (line_label::line_label): Add "has_in_edge" and "has_out_edge" params and initialize... (line_label::m_has_in_edge): New field. (line_label::m_has_out_edge): New field. (layout::print_any_labels): Pass edge information to line_label ctor. Keep track of in-edges and out-edges, adding visualizations of these links between labels. (layout::print_leading_fixits): Drop pp_character, as this is now added by start_annotation_line. (layout::print_trailing_fixits): Fix off-by-one errors in column calculation. (layout::move_to_column): Add comment about debugging. (layout::show_ruler): Make non-const. Drop pp_space calls, as this is now added by start_annotation_line. (layout::print_line): Call print_any_right_to_left_edge_lines. (layout::print_any_right_to_left_edge_lines): New. (layout::update_any_effects): New. (gcc_rich_location::add_location_if_nearby): Initialize loc_range.m_label. (diagnostic_context::maybe_show_locus): Add "effects" param and pass it to diagnostic_context::show_locus. (diagnostic_context::show_locus): Add "effects" param, passing it to layout's ctor. Call update_any_effects on the layout after printing the lines. (selftest::test_layout_x_offset_display_utf8): Update expected result for eliminated trailing newline. (selftest::test_layout_x_offset_display_utf8): Likewise. (selftest::test_layout_x_offset_display_tab): Likewise. * diagnostic.cc (diagnostic_context::initialize): Initialize m_source_printing.show_event_links_p. (simple_diagnostic_path::connect_to_next_event): New. (simple_diagnostic_event::simple_diagnostic_event): Initialize m_connected_to_next_event. * diagnostic.h (class diagnostic_source_effect_info): New forward decl. (diagnostic_source_printing_options::show_event_links_p): New field. (diagnostic_context::maybe_show_locus): Add optional "effect_info" param. (diagnostic_context::show_locus): Add "effect_info" param. (diagnostic_show_locus): Add optional "effect_info" param. * doc/invoke.texi: Add -fno-diagnostics-show-event-links. * lto-wrapper.cc (merge_and_complain): Add OPT_fdiagnostics_show_event_links to switch. (append_compiler_options): Likewise. (append_diag_options): Likewise. * opts-common.cc (decode_cmdline_options_to_array): Add "-fno-diagnostics-show-event-links" to -fdiagnostics-plain-output. * opts.cc (common_handle_option): Add case for OPT_fdiagnostics_show_event_links. * text-art/theme.cc (ascii_theme::get_cppchar): Handle cell_kind::CFG_*. (unicode_theme::get_cppchar): Likewise. * text-art/theme.h (theme::cell_kind): Add CFG_*. * toplev.cc (general_init): Initialize global_dc->m_source_printing.show_event_links_p. * tree-diagnostic-path.cc: Define INCLUDE_ALGORITHM, INCLUDE_MEMORY, and INCLUDE_STRING. Include "diagnostic-label-effects.h". (path_label::path_label): Initialize m_effects. (path_label::get_effects): New. (class path_label::path_label_effects): New. (path_label::m_effects): New field. (class per_thread_summary): Add "friend struct event_range;". (per_thread_summary::per_thread_summary): Initialize m_last_event. (per_thread_summary::m_last_event): New field. (struct event_range::per_source_line_info): New. (event_range::event_range): Make "t" non-const. Add "show_event_links" param and use it to initialize m_show_event_links. Add info for initial event. (event_range::get_per_source_line_info): New. (event_range::maybe_add_event): Verify compatibility of the new label and existing labels with respect to the link-printing code. Update per-source-line info when an event is added. (event_range::print): Add"effect_info" param and pass to diagnostic_show_locus. (event_range::m_per_thread_summary): Make non-const. (event_range::m_source_line_info_map): New field. (event_range::m_show_event_links): New field. (path_summary::path_summary): Add "show_event_links" optional param, passing it to event_range ctor calls. Update pts.m_last_event. (thread_event_printer::print_swimlane_for_event_range): Add "effect_info" param and pass it to range->print. (print_path_summary_as_text): Keep track of the column for any out-edges at the end of printing each event_range and use as the leading in-edge for the next event_range. (default_tree_diagnostic_path_printer): Pass in show_event_links_p to path_summary ctor. (selftest::path_events_have_column_data_p): New. (class selftest::control_flow_test): New. (selftest::test_control_flow_1): New. (selftest::test_control_flow_2): New. (selftest::test_control_flow_3): New. (selftest::assert_cfg_edge_path_streq): New. (ASSERT_CFG_EDGE_PATH_STREQ): New macro. (selftest::test_control_flow_4): New. (selftest::test_control_flow_5): New. (selftest::test_control_flow_6): New. (selftest::control_flow_tests): New. (selftest::tree_diagnostic_path_cc_tests): Disable colorization on global_dc's printer. Convert event_pp to a std::unique_ptr. Call control_flow_tests via for_each_line_table_case. (gen_command_line_string): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/event-links-ascii.c: New test. * gcc.dg/analyzer/event-links-color.c: New test. * gcc.dg/analyzer/event-links-disabled.c: New test. * gcc.dg/analyzer/event-links-unicode.c: New test. libcpp/ChangeLog: * include/rich-location.h (class label_effects): New forward decl. (range_label::get_effects): New vfunc. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer/infinite-loop.cc')
-rw-r--r--gcc/analyzer/infinite-loop.cc18
1 files changed, 16 insertions, 2 deletions
diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc
index e277a83..04346cd 100644
--- a/gcc/analyzer/infinite-loop.cc
+++ b/gcc/analyzer/infinite-loop.cc
@@ -162,6 +162,21 @@ public:
}
};
+class looping_back_event : public start_cfg_edge_event
+{
+public:
+ looping_back_event (const exploded_edge &eedge,
+ const event_loc_info &loc_info)
+ : start_cfg_edge_event (eedge, loc_info)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override
+ {
+ return label_text::borrow ("looping back...");
+ }
+};
+
/* A subclass of pending_diagnostic for complaining about suspected
infinite loops. */
@@ -300,8 +315,7 @@ public:
else if (cfg_sedge->back_edge_p ())
{
emission_path->add_event
- (make_unique<precanned_custom_event>
- (loc_info_from, "looping back..."));
+ (make_unique<looping_back_event> (*eedge, loc_info_from));
emission_path->add_event
(make_unique<end_cfg_edge_event>
(*eedge,