arm: fix typo in dg-require-effective-target [PR118089]
[official-gcc.git] / gcc / analyzer / known-function-manager.cc
blobdb670b8ae6cd76fbc2dfee0d591916bf963c00ec
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>.
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_VECTOR
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "analyzer/analyzer.h"
27 #include "diagnostic-core.h"
28 #include "analyzer/analyzer-logging.h"
29 #include "stringpool.h"
30 #include "basic-block.h"
31 #include "gimple.h"
32 #include "analyzer/known-function-manager.h"
33 #include "analyzer/region-model.h"
34 #include "analyzer/call-details.h"
36 #if ENABLE_ANALYZER
38 namespace ana {
40 /* class known_function_manager : public log_user. */
42 known_function_manager::known_function_manager (logger *logger)
43 : log_user (logger)
45 memset (m_combined_fns_arr, 0, sizeof (m_combined_fns_arr));
48 known_function_manager::~known_function_manager ()
50 /* Delete all owned kfs. */
51 for (auto iter : m_map_id_to_kf)
52 delete iter.second;
53 for (auto iter : m_std_ns_map_id_to_kf)
54 delete iter.second;
55 for (auto iter : m_combined_fns_arr)
56 delete iter;
59 void
60 known_function_manager::add (const char *name,
61 std::unique_ptr<known_function> kf)
63 LOG_FUNC_1 (get_logger (), "registering %s", name);
64 tree id = get_identifier (name);
65 m_map_id_to_kf.put (id, kf.release ());
68 void
69 known_function_manager::add_std_ns (const char *name,
70 std::unique_ptr<known_function> kf)
72 LOG_FUNC_1 (get_logger (), "registering std::%s", name);
73 tree id = get_identifier (name);
74 m_std_ns_map_id_to_kf.put (id, kf.release ());
77 void
78 known_function_manager::add (enum built_in_function name,
79 std::unique_ptr<known_function> kf)
81 gcc_assert (name < END_BUILTINS);
82 delete m_combined_fns_arr[name];
83 m_combined_fns_arr[name] = kf.release ();
86 void
87 known_function_manager::add (enum internal_fn ifn,
88 std::unique_ptr<known_function> kf)
90 gcc_assert (ifn < IFN_LAST);
91 delete m_combined_fns_arr[ifn + END_BUILTINS];
92 m_combined_fns_arr[ifn + END_BUILTINS] = kf.release ();
95 /* Get any known_function for FNDECL for call CD.
97 The call must match all assumptions made by the known_function (such as
98 e.g. "argument 1's type must be a pointer type").
100 Return NULL if no known_function is found, or it does not match the
101 assumption(s). */
103 const known_function *
104 known_function_manager::get_match (tree fndecl, const call_details &cd) const
106 /* Look for a matching built-in. */
107 if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
109 if (const known_function *candidate
110 = get_normal_builtin (DECL_FUNCTION_CODE (fndecl)))
111 if (gimple_builtin_call_types_compatible_p (cd.get_call_stmt (),
112 fndecl))
113 return candidate;
116 /* Look for a match by name. */
118 if (is_std_function_p (fndecl))
120 if (tree identifier = DECL_NAME (fndecl))
121 if (const known_function *candidate
122 = get_by_identifier_in_std_ns (identifier))
123 if (candidate->matches_call_types_p (cd))
124 return candidate;
125 return nullptr;
128 if (DECL_CONTEXT (fndecl)
129 && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
130 return NULL;
131 if (tree identifier = DECL_NAME (fndecl))
132 if (const known_function *candidate = get_by_identifier (identifier))
133 if (candidate->matches_call_types_p (cd))
134 return candidate;
136 return NULL;
139 /* Get any known_function for IFN, or NULL. */
141 const known_function *
142 known_function_manager::get_internal_fn (enum internal_fn ifn) const
144 gcc_assert (ifn < IFN_LAST);
145 return m_combined_fns_arr[ifn + END_BUILTINS];
148 /* Get any known_function for NAME, without type-checking.
149 Return NULL if there isn't one. */
151 const known_function *
152 known_function_manager::get_normal_builtin (enum built_in_function name) const
154 /* The numbers for built-in functions in enum combined_fn are the same as
155 for the built_in_function enum. */
156 gcc_assert (name < END_BUILTINS);
157 return m_combined_fns_arr[name];
160 const known_function *
161 known_function_manager::
162 get_normal_builtin (const builtin_known_function *builtin_kf) const
164 return get_normal_builtin (builtin_kf->builtin_code ());
167 /* Get any known_function matching IDENTIFIER, without type-checking.
168 Return NULL if there isn't one. */
170 const known_function *
171 known_function_manager::get_by_identifier (tree identifier) const
173 known_function_manager *mut_this = const_cast<known_function_manager *>(this);
174 known_function **slot = mut_this->m_map_id_to_kf.get (identifier);
175 if (slot)
176 return *slot;
177 else
178 return NULL;
181 /* Get any known_function in C++ std:: namespace matching IDENTIFIER, without
182 type-checking.
183 Return nullptr if there isn't one. */
185 const known_function *
186 known_function_manager::get_by_identifier_in_std_ns (tree identifier) const
188 known_function_manager *mut_this = const_cast<known_function_manager *>(this);
189 known_function **slot = mut_this->m_std_ns_map_id_to_kf.get (identifier);
190 if (slot)
191 return *slot;
192 else
193 return nullptr;
197 } // namespace ana
199 #endif /* #if ENABLE_ANALYZER */