d: Add test for PR d/108167 to the testsuite [PR108167]
[official-gcc.git] / gcc / analyzer / call-details.cc
blob17edaf26276fed755ecfe62fe12ef8006011193a
1 /* Helper class for handling a call with specific arguments.
2 Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
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 "diagnostic-core.h"
30 #include "analyzer/analyzer.h"
31 #include "analyzer/analyzer-logging.h"
32 #include "diagnostic.h"
33 #include "tree-diagnostic.h" /* for default_tree_printer. */
34 #include "gimple-pretty-print.h"
35 #include "analyzer/region-model.h"
36 #include "analyzer/call-details.h"
38 #if ENABLE_ANALYZER
40 namespace ana {
42 /* class call_details. */
44 /* call_details's ctor. */
46 call_details::call_details (const gcall *call, region_model *model,
47 region_model_context *ctxt)
48 : m_call (call), m_model (model), m_ctxt (ctxt),
49 m_lhs_type (NULL_TREE), m_lhs_region (NULL)
51 m_lhs_type = NULL_TREE;
52 if (tree lhs = gimple_call_lhs (call))
54 m_lhs_region = model->get_lvalue (lhs, ctxt);
55 m_lhs_type = TREE_TYPE (lhs);
59 /* Get the manager from m_model. */
61 region_model_manager *
62 call_details::get_manager () const
64 return m_model->get_manager ();
67 /* Get any logger associated with this object. */
69 logger *
70 call_details::get_logger () const
72 if (m_ctxt)
73 return m_ctxt->get_logger ();
74 else
75 return NULL;
78 /* Get any uncertainty_t associated with the region_model_context. */
80 uncertainty_t *
81 call_details::get_uncertainty () const
83 if (m_ctxt)
84 return m_ctxt->get_uncertainty ();
85 else
86 return NULL;
89 /* If the callsite has a left-hand-side region, set it to RESULT
90 and return true.
91 Otherwise do nothing and return false. */
93 bool
94 call_details::maybe_set_lhs (const svalue *result) const
96 gcc_assert (result);
97 if (m_lhs_region)
99 m_model->set_value (m_lhs_region, result, m_ctxt);
100 return true;
102 else
103 return false;
106 /* Return the number of arguments used by the call statement. */
108 unsigned
109 call_details::num_args () const
111 return gimple_call_num_args (m_call);
114 /* Return true if argument IDX is a size_t (or compatible with it). */
116 bool
117 call_details::arg_is_size_p (unsigned idx) const
119 return types_compatible_p (get_arg_type (idx), size_type_node);
122 /* Get the location of the call statement. */
124 location_t
125 call_details::get_location () const
127 return m_call->location;
130 /* Get argument IDX at the callsite as a tree. */
132 tree
133 call_details::get_arg_tree (unsigned idx) const
135 return gimple_call_arg (m_call, idx);
138 /* Get the type of argument IDX. */
140 tree
141 call_details::get_arg_type (unsigned idx) const
143 return TREE_TYPE (gimple_call_arg (m_call, idx));
146 /* Get argument IDX at the callsite as an svalue. */
148 const svalue *
149 call_details::get_arg_svalue (unsigned idx) const
151 tree arg = get_arg_tree (idx);
152 return m_model->get_rvalue (arg, m_ctxt);
155 /* Attempt to get the string literal for argument IDX, or return NULL
156 otherwise.
157 For use when implementing "__analyzer_*" functions that take
158 string literals. */
160 const char *
161 call_details::get_arg_string_literal (unsigned idx) const
163 const svalue *str_arg = get_arg_svalue (idx);
164 if (const region *pointee = str_arg->maybe_get_region ())
165 if (const string_region *string_reg = pointee->dyn_cast_string_region ())
167 tree string_cst = string_reg->get_string_cst ();
168 return TREE_STRING_POINTER (string_cst);
170 return NULL;
173 /* Attempt to get the fndecl used at this call, if known, or NULL_TREE
174 otherwise. */
176 tree
177 call_details::get_fndecl_for_call () const
179 return m_model->get_fndecl_for_call (m_call, m_ctxt);
182 /* Dump a multiline representation of this call to PP. */
184 void
185 call_details::dump_to_pp (pretty_printer *pp, bool simple) const
187 pp_string (pp, "gcall: ");
188 pp_gimple_stmt_1 (pp, m_call, 0 /* spc */, TDF_NONE /* flags */);
189 pp_newline (pp);
190 pp_string (pp, "return region: ");
191 if (m_lhs_region)
192 m_lhs_region->dump_to_pp (pp, simple);
193 else
194 pp_string (pp, "NULL");
195 pp_newline (pp);
196 for (unsigned i = 0; i < gimple_call_num_args (m_call); i++)
198 const svalue *arg_sval = get_arg_svalue (i);
199 pp_printf (pp, "arg %i: ", i);
200 arg_sval->dump_to_pp (pp, simple);
201 pp_newline (pp);
205 /* Dump a multiline representation of this call to stderr. */
207 DEBUG_FUNCTION void
208 call_details::dump (bool simple) const
210 pretty_printer pp;
211 pp_format_decoder (&pp) = default_tree_printer;
212 pp_show_color (&pp) = pp_show_color (global_dc->printer);
213 pp.buffer->stream = stderr;
214 dump_to_pp (&pp, simple);
215 pp_flush (&pp);
218 /* Get a conjured_svalue for this call for REG,
219 and purge any state already relating to that conjured_svalue. */
221 const svalue *
222 call_details::get_or_create_conjured_svalue (const region *reg) const
224 region_model_manager *mgr = m_model->get_manager ();
225 return mgr->get_or_create_conjured_svalue (reg->get_type (), m_call, reg,
226 conjured_purge (m_model, m_ctxt));
229 } // namespace ana
231 #endif /* #if ENABLE_ANALYZER */