Branch data Line data Source code
1 : : /* Support for plugin-supplied behaviors of known functions.
2 : : Copyright (C) 2022-2025 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 "analyzer/common.h"
22 : :
23 : : #include "diagnostic-core.h"
24 : : #include "stringpool.h"
25 : :
26 : : #include "analyzer/analyzer-logging.h"
27 : : #include "analyzer/known-function-manager.h"
28 : : #include "analyzer/region-model.h"
29 : : #include "analyzer/call-details.h"
30 : :
31 : : #if ENABLE_ANALYZER
32 : :
33 : : namespace ana {
34 : :
35 : : /* class known_function_manager : public log_user. */
36 : :
37 : 3880 : known_function_manager::known_function_manager (logger *logger)
38 : 3880 : : log_user (logger)
39 : : {
40 : 3880 : memset (m_combined_fns_arr, 0, sizeof (m_combined_fns_arr));
41 : 3880 : }
42 : :
43 : 3880 : known_function_manager::~known_function_manager ()
44 : : {
45 : : /* Delete all owned kfs. */
46 : 599534 : for (auto iter : m_map_id_to_kf)
47 : 297827 : delete iter.second;
48 : 116352 : for (auto iter : m_std_ns_map_id_to_kf)
49 : 56236 : delete iter.second;
50 : 8900720 : for (auto iter : m_combined_fns_arr)
51 : 8896840 : delete iter;
52 : 3880 : }
53 : :
54 : : void
55 : 297827 : known_function_manager::add (const char *name,
56 : : std::unique_ptr<known_function> kf)
57 : : {
58 : 297827 : LOG_FUNC_1 (get_logger (), "registering %s", name);
59 : 297827 : tree id = get_identifier (name);
60 : 297827 : m_map_id_to_kf.put (id, kf.release ());
61 : 297827 : }
62 : :
63 : : void
64 : 56236 : known_function_manager::add_std_ns (const char *name,
65 : : std::unique_ptr<known_function> kf)
66 : : {
67 : 56236 : LOG_FUNC_1 (get_logger (), "registering std::%s", name);
68 : 56236 : tree id = get_identifier (name);
69 : 56236 : m_std_ns_map_id_to_kf.put (id, kf.release ());
70 : 56236 : }
71 : :
72 : : void
73 : 572284 : known_function_manager::add (enum built_in_function name,
74 : : std::unique_ptr<known_function> kf)
75 : : {
76 : 572284 : gcc_assert (name < END_BUILTINS);
77 : 572284 : delete m_combined_fns_arr[name];
78 : 572284 : m_combined_fns_arr[name] = kf.release ();
79 : 572284 : }
80 : :
81 : : void
82 : 19848 : known_function_manager::add (enum internal_fn ifn,
83 : : std::unique_ptr<known_function> kf)
84 : : {
85 : 19848 : gcc_assert (ifn < IFN_LAST);
86 : 19848 : delete m_combined_fns_arr[ifn + END_BUILTINS];
87 : 19848 : m_combined_fns_arr[ifn + END_BUILTINS] = kf.release ();
88 : 19848 : }
89 : :
90 : : /* Get any known_function for FNDECL for call CD.
91 : :
92 : : The call must match all assumptions made by the known_function (such as
93 : : e.g. "argument 1's type must be a pointer type").
94 : :
95 : : Return nullptr if no known_function is found, or it does not match the
96 : : assumption(s). */
97 : :
98 : : const known_function *
99 : 367413 : known_function_manager::get_match (tree fndecl, const call_details &cd) const
100 : : {
101 : : /* Look for a matching built-in. */
102 : 367413 : if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
103 : : {
104 : 295098 : if (const known_function *candidate
105 : 147549 : = get_normal_builtin (DECL_FUNCTION_CODE (fndecl)))
106 : 19961 : if (gimple_builtin_call_types_compatible_p (&cd.get_call_stmt (),
107 : : fndecl))
108 : : return candidate;
109 : : }
110 : :
111 : : /* Look for a match by name. */
112 : :
113 : 347452 : if (is_std_function_p (fndecl))
114 : : {
115 : 1404 : if (tree identifier = DECL_NAME (fndecl))
116 : 2808 : if (const known_function *candidate
117 : 1404 : = get_by_identifier_in_std_ns (identifier))
118 : 90 : if (candidate->matches_call_types_p (cd))
119 : : return candidate;
120 : 1314 : return nullptr;
121 : : }
122 : :
123 : 346048 : if (DECL_CONTEXT (fndecl)
124 : 346048 : && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
125 : : return nullptr;
126 : 335158 : if (tree identifier = DECL_NAME (fndecl))
127 : 335158 : if (const known_function *candidate = get_by_identifier (identifier))
128 : 197306 : if (candidate->matches_call_types_p (cd))
129 : : return candidate;
130 : :
131 : : return nullptr;
132 : : }
133 : :
134 : : /* Get any known_function for IFN, or nullptr. */
135 : :
136 : : const known_function *
137 : 1336 : known_function_manager::get_internal_fn (enum internal_fn ifn) const
138 : : {
139 : 1336 : gcc_assert (ifn < IFN_LAST);
140 : 1336 : return m_combined_fns_arr[ifn + END_BUILTINS];
141 : : }
142 : :
143 : : /* Get any known_function for NAME, without type-checking.
144 : : Return nullptr if there isn't one. */
145 : :
146 : : const known_function *
147 : 147549 : known_function_manager::get_normal_builtin (enum built_in_function name) const
148 : : {
149 : : /* The numbers for built-in functions in enum combined_fn are the same as
150 : : for the built_in_function enum. */
151 : 147549 : gcc_assert (name < END_BUILTINS);
152 : 147549 : return m_combined_fns_arr[name];
153 : : }
154 : :
155 : : const known_function *
156 : 0 : known_function_manager::
157 : : get_normal_builtin (const builtin_known_function *builtin_kf) const
158 : : {
159 : 0 : return get_normal_builtin (builtin_kf->builtin_code ());
160 : : }
161 : :
162 : : /* Get any known_function matching IDENTIFIER, without type-checking.
163 : : Return nullptr if there isn't one. */
164 : :
165 : : const known_function *
166 : 335158 : known_function_manager::get_by_identifier (tree identifier) const
167 : : {
168 : 335158 : known_function_manager *mut_this = const_cast<known_function_manager *>(this);
169 : 335158 : known_function **slot = mut_this->m_map_id_to_kf.get (identifier);
170 : 335158 : if (slot)
171 : 197306 : return *slot;
172 : : else
173 : : return nullptr;
174 : : }
175 : :
176 : : /* Get any known_function in C++ std:: namespace matching IDENTIFIER, without
177 : : type-checking.
178 : : Return nullptr if there isn't one. */
179 : :
180 : : const known_function *
181 : 1404 : known_function_manager::get_by_identifier_in_std_ns (tree identifier) const
182 : : {
183 : 1404 : known_function_manager *mut_this = const_cast<known_function_manager *>(this);
184 : 1404 : known_function **slot = mut_this->m_std_ns_map_id_to_kf.get (identifier);
185 : 1404 : if (slot)
186 : 90 : return *slot;
187 : : else
188 : : return nullptr;
189 : : }
190 : :
191 : :
192 : : } // namespace ana
193 : :
194 : : #endif /* #if ENABLE_ANALYZER */
|