1/* Iterator for walking a chain of inlining locations.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#ifndef GCC_ANALYZER_INLINING_ITERATOR_H
22#define GCC_ANALYZER_INLINING_ITERATOR_H
23
24/* Iterator for walking a chain of inlining locations.
25
26 The fndecls and locations will be traversed from innermost to outermost.
27 For example, given:
28
29 inline void inner (void)
30 {
31 ...LOCATION HERE...
32 }
33 void outer (void)
34 {
35 inner (); <-- CALLSITE
36 }
37
38 then the fndecl will be "inner" on the initial iteration, and "outer" on
39 the second (final) iteration.
40
41 Compare with lhd_print_error_function, cp_print_error_function,
42 and optrecord_json_writer::inlining_chain_to_json. */
43
44class inlining_iterator
45{
46public:
47 inlining_iterator (location_t loc)
48 : m_abstract_origin (LOCATION_BLOCK (loc)),
49 m_callsite (UNKNOWN_LOCATION), m_fndecl (NULL),
50 m_next_abstract_origin (NULL)
51 {
52 prepare_iteration ();
53 }
54
55 bool done_p () const { return m_abstract_origin == NULL; }
56
57 void next ()
58 {
59 m_abstract_origin = m_next_abstract_origin;
60 prepare_iteration ();
61 }
62
63 tree get_fndecl () const { return m_fndecl; }
64 location_t get_callsite () const { return m_callsite; }
65 tree get_block () const { return m_abstract_origin; }
66
67private:
68 void prepare_iteration ()
69 {
70 if (done_p ())
71 return;
72 tree block = m_abstract_origin;
73 m_callsite = BLOCK_SOURCE_LOCATION (block);
74 m_fndecl = NULL;
75 block = BLOCK_SUPERCONTEXT (block);
76 while (block && TREE_CODE (block) == BLOCK
77 && BLOCK_ABSTRACT_ORIGIN (block))
78 {
79 tree ao = BLOCK_ABSTRACT_ORIGIN (block);
80 if (TREE_CODE (ao) == FUNCTION_DECL)
81 {
82 m_fndecl = ao;
83 break;
84 }
85 else if (TREE_CODE (ao) != BLOCK)
86 break;
87
88 block = BLOCK_SUPERCONTEXT (block);
89 }
90 if (m_fndecl)
91 m_next_abstract_origin = block;
92 else
93 {
94 while (block && TREE_CODE (block) == BLOCK)
95 block = BLOCK_SUPERCONTEXT (block);
96
97 if (block && TREE_CODE (block) == FUNCTION_DECL)
98 m_fndecl = block;
99 m_next_abstract_origin = NULL;
100 }
101 }
102
103 tree m_abstract_origin;
104 location_t m_callsite;
105 tree m_fndecl;
106 tree m_next_abstract_origin;
107};
108
109/* A class for fixing up fndecls and stack depths in checker_event, based
110 on inlining records.
111
112 The early inliner runs before the analyzer, which can lead to confusing
113 output.
114
115 Tne base fndecl and depth within a checker_event are from call strings
116 in program_points, which reflect the call strings after inlining.
117 This class lets us offset the depth and fix up the reported fndecl and
118 stack depth to better reflect the user's original code. */
119
120class inlining_info
121{
122public:
123 inlining_info (location_t loc)
124 {
125 inlining_iterator iter (loc);
126 m_inner_fndecl = iter.get_fndecl ();
127 int num_frames = 0;
128 while (!iter.done_p ())
129 {
130 m_outer_fndecl = iter.get_fndecl ();
131 num_frames++;
132 iter.next ();
133 }
134 if (num_frames > 1)
135 m_extra_frames = num_frames - 1;
136 else
137 m_extra_frames = 0;
138 }
139
140 tree get_inner_fndecl () const { return m_inner_fndecl; }
141 int get_extra_frames () const { return m_extra_frames; }
142
143private:
144 tree m_outer_fndecl;
145 tree m_inner_fndecl;
146 int m_extra_frames;
147};
148
149#endif /* GCC_ANALYZER_INLINING_ITERATOR_H */
150

source code of gcc/analyzer/inlining-iterator.h