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)
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/>. */
22 #define INCLUDE_MEMORY
24 #include "coretypes.h"
27 #include "basic-block.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"
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. */
70 call_details::get_logger () const
73 return m_ctxt
->get_logger ();
78 /* Get any uncertainty_t associated with the region_model_context. */
81 call_details::get_uncertainty () const
84 return m_ctxt
->get_uncertainty ();
89 /* If the callsite has a left-hand-side region, set it to RESULT
91 Otherwise do nothing and return false. */
94 call_details::maybe_set_lhs (const svalue
*result
) const
99 m_model
->set_value (m_lhs_region
, result
, m_ctxt
);
106 /* Return the number of arguments used by the call statement. */
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). */
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. */
125 call_details::get_location () const
127 return m_call
->location
;
130 /* Get argument IDX at the callsite as a 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. */
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. */
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
157 For use when implementing "__analyzer_*" functions that take
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
);
173 /* Attempt to get the fndecl used at this call, if known, or NULL_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. */
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 */);
190 pp_string (pp
, "return region: ");
192 m_lhs_region
->dump_to_pp (pp
, simple
);
194 pp_string (pp
, "NULL");
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
);
205 /* Dump a multiline representation of this call to stderr. */
208 call_details::dump (bool simple
) const
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
);
218 /* Get a conjured_svalue for this call for REG,
219 and purge any state already relating to that conjured_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
));
231 #endif /* #if ENABLE_ANALYZER */