1 | /* Subclasses of custom_edge_info for describing outcomes of function calls. |
2 | Copyright (C) 2021-2024 Free Software Foundation, Inc. |
3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3, or (at your option) |
10 | any later version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include "config.h" |
22 | #define INCLUDE_MEMORY |
23 | #include "system.h" |
24 | #include "coretypes.h" |
25 | #include "tree.h" |
26 | #include "function.h" |
27 | #include "basic-block.h" |
28 | #include "gimple.h" |
29 | #include "gimple-iterator.h" |
30 | #include "diagnostic-core.h" |
31 | #include "options.h" |
32 | #include "cgraph.h" |
33 | #include "tree-pretty-print.h" |
34 | #include "bitmap.h" |
35 | #include "analyzer/analyzer.h" |
36 | #include "analyzer/analyzer-logging.h" |
37 | #include "ordered-hash-map.h" |
38 | #include "cfg.h" |
39 | #include "digraph.h" |
40 | #include "analyzer/supergraph.h" |
41 | #include "sbitmap.h" |
42 | #include "analyzer/call-string.h" |
43 | #include "analyzer/program-point.h" |
44 | #include "analyzer/store.h" |
45 | #include "analyzer/region-model.h" |
46 | #include "analyzer/constraint-manager.h" |
47 | #include "diagnostic-event-id.h" |
48 | #include "analyzer/sm.h" |
49 | #include "analyzer/pending-diagnostic.h" |
50 | #include "analyzer/region-model-reachability.h" |
51 | #include "analyzer/analyzer-selftests.h" |
52 | #include "analyzer/program-state.h" |
53 | #include "diagnostic-path.h" |
54 | #include "analyzer/checker-path.h" |
55 | #include "analyzer/diagnostic-manager.h" |
56 | #include "analyzer/exploded-graph.h" |
57 | #include "analyzer/call-details.h" |
58 | #include "analyzer/call-info.h" |
59 | #include "make-unique.h" |
60 | |
61 | #if ENABLE_ANALYZER |
62 | |
63 | namespace ana { |
64 | |
65 | /* class custom_edge_info. */ |
66 | |
67 | bool |
68 | custom_edge_info::update_state (program_state *state, |
69 | const exploded_edge *eedge, |
70 | region_model_context *ctxt) const |
71 | { |
72 | return update_model (model: state->m_region_model, eedge, ctxt); |
73 | } |
74 | |
75 | /* class call_info : public custom_edge_info. */ |
76 | |
77 | /* Implementation of custom_edge_info::print vfunc for call_info: |
78 | use get_desc to get a label_text, and print it to PP. */ |
79 | |
80 | void |
81 | call_info::print (pretty_printer *pp) const |
82 | { |
83 | label_text desc (get_desc (pp_show_color (pp))); |
84 | pp_string (pp, desc.get ()); |
85 | } |
86 | |
87 | /* Implementation of custom_edge_info::add_events_to_path vfunc for |
88 | call_info: add a custom_event using call_info::get_desc as its |
89 | description. */ |
90 | |
91 | void |
92 | call_info::add_events_to_path (checker_path *emission_path, |
93 | const exploded_edge &eedge) const |
94 | { |
95 | class call_event : public custom_event |
96 | { |
97 | public: |
98 | call_event (const event_loc_info &loc_info, |
99 | const call_info *call_info) |
100 | : custom_event (loc_info), |
101 | m_call_info (call_info) |
102 | {} |
103 | |
104 | label_text get_desc (bool can_colorize) const final override |
105 | { |
106 | return m_call_info->get_desc (can_colorize); |
107 | } |
108 | |
109 | private: |
110 | const call_info *m_call_info; |
111 | }; |
112 | |
113 | const exploded_node *src_node = eedge.m_src; |
114 | const program_point &src_point = src_node->get_point (); |
115 | tree caller_fndecl = src_point.get_fndecl (); |
116 | const int stack_depth = src_point.get_stack_depth (); |
117 | |
118 | emission_path->add_event |
119 | (event: make_unique<call_event> (args: event_loc_info (get_call_stmt ()->location, |
120 | caller_fndecl, |
121 | stack_depth), |
122 | args: this)); |
123 | } |
124 | |
125 | /* Recreate a call_details instance from this call_info. */ |
126 | |
127 | call_details |
128 | call_info::get_call_details (region_model *model, |
129 | region_model_context *ctxt) const |
130 | { |
131 | return call_details (m_call_stmt, model, ctxt); |
132 | } |
133 | |
134 | /* call_info's ctor. |
135 | |
136 | The call_info instance will outlive the call_details instance; |
137 | call_details instances are typically created on the stack. */ |
138 | |
139 | call_info::call_info (const call_details &cd) |
140 | : m_call_stmt (cd.get_call_stmt ()), |
141 | m_fndecl (cd.get_fndecl_for_call ()) |
142 | { |
143 | gcc_assert (m_fndecl); |
144 | } |
145 | |
146 | call_info::call_info (const call_details &cd, |
147 | const function &called_fn) |
148 | : m_call_stmt (cd.get_call_stmt ()), |
149 | m_fndecl (called_fn.decl) |
150 | { |
151 | gcc_assert (m_fndecl); |
152 | } |
153 | |
154 | /* class succeed_or_fail_call_info : public call_info. */ |
155 | |
156 | label_text |
157 | succeed_or_fail_call_info::get_desc (bool can_colorize) const |
158 | { |
159 | if (m_success) |
160 | return make_label_text (can_colorize, fmt: "when %qE succeeds" , get_fndecl ()); |
161 | else |
162 | return make_label_text (can_colorize, fmt: "when %qE fails" , get_fndecl ()); |
163 | } |
164 | |
165 | } // namespace ana |
166 | |
167 | #endif /* #if ENABLE_ANALYZER */ |
168 | |