/* Classes for representing locations within the program.
- Copyright (C) 2019-2023 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
#include "config.h"
#define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "shortest-paths.h"
#include "analyzer/exploded-graph.h"
#include "analyzer/analysis-plan.h"
+#include "analyzer/inlining-iterator.h"
#if ENABLE_ANALYZER
/* Create a function_point representing the entrypoint of function FUN. */
function_point
-function_point::from_function_entry (const supergraph &sg, function *fun)
+function_point::from_function_entry (const supergraph &sg, const function &fun)
{
return before_supernode (sg.get_node_for_function_entry (fun), NULL);
}
debug_diagnostic_context ()
{
diagnostic_initialize (this, 0);
- show_line_numbers_p = true;
- show_caret = true;
+ m_source_printing.show_line_numbers_p = true;
+ m_source_printing.enabled = true;
}
~debug_diagnostic_context ()
{
{
pretty_printer pp;
pp_show_color (&pp) = pp_show_color (global_dc->printer);
- pp.buffer->stream = stderr;
+ pp.set_output_stream (stderr);
print (&pp, format (true));
pp_flush (&pp);
}
{
const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (succ);
- /* Reject abnormal edges; we special-case setjmp/longjmp. */
if (cfg_sedge->get_flags () & EDGE_ABNORMAL)
- return false;
+ {
+ const supernode *src_snode = cfg_sedge->m_src;
+ if (gimple *last_stmt = src_snode->get_last_stmt ())
+ if (last_stmt->code == GIMPLE_GOTO)
+ {
+ /* For the program_point aspect here, consider all
+ out-edges from goto stmts to be valid; we'll
+ consider state separately. */
+ return true;
+ }
+
+ /* Reject other kinds of abnormal edges;
+ we special-case setjmp/longjmp. */
+ return false;
+ }
}
break;
program_point
program_point::from_function_entry (const region_model_manager &mgr,
const supergraph &sg,
- function *fun)
+ const function &fun)
{
return program_point (function_point::from_function_entry (sg, fun),
mgr.get_empty_call_string ());
}
}
+/* Return true iff POINT_A and POINT_B share the same function and
+ call_string, both directly, and when attempting to undo inlining
+ information. */
+
+bool
+program_point::effectively_intraprocedural_p (const program_point &point_a,
+ const program_point &point_b)
+{
+ /* First, compare without considering inlining info. */
+ if (point_a.get_function ()
+ != point_b.get_function ())
+ return false;
+ if (&point_a.get_call_string ()
+ != &point_b.get_call_string ())
+ return false;
+
+ /* Consider inlining info; they must have originally come from
+ the same function and have been inlined in the same way. */
+ location_t loc_a = point_a.get_location ();
+ location_t loc_b = point_b.get_location ();
+ inlining_iterator iter_a (loc_a);
+ inlining_iterator iter_b (loc_b);
+ while (!(iter_a.done_p () || iter_b.done_p ()))
+ {
+ if (iter_a.done_p () || iter_b.done_p ())
+ return false;
+
+ if (iter_a.get_fndecl () != iter_b.get_fndecl ())
+ return false;
+ if (iter_a.get_callsite () != iter_b.get_callsite ())
+ return false;
+ if (iter_a.get_block () != iter_b.get_block ())
+ return false;
+
+ iter_a.next ();
+ iter_b.next ();
+ }
+
+ return true;
+}
+
#if CHECKING_P
namespace selftest {