1 /* Support for plugin-supplied behaviors of known functions.
2 Copyright (C) 2022-2024 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
23 #define INCLUDE_VECTOR
25 #include "coretypes.h"
27 #include "analyzer/analyzer.h"
28 #include "diagnostic-core.h"
29 #include "analyzer/analyzer-logging.h"
30 #include "stringpool.h"
31 #include "basic-block.h"
33 #include "analyzer/known-function-manager.h"
34 #include "analyzer/region-model.h"
35 #include "analyzer/call-details.h"
41 /* class known_function_manager : public log_user. */
43 known_function_manager::known_function_manager (logger
*logger
)
46 memset (m_combined_fns_arr
, 0, sizeof (m_combined_fns_arr
));
49 known_function_manager::~known_function_manager ()
51 /* Delete all owned kfs. */
52 for (auto iter
: m_map_id_to_kf
)
54 for (auto iter
: m_std_ns_map_id_to_kf
)
56 for (auto iter
: m_combined_fns_arr
)
61 known_function_manager::add (const char *name
,
62 std::unique_ptr
<known_function
> kf
)
64 LOG_FUNC_1 (get_logger (), "registering %s", name
);
65 tree id
= get_identifier (name
);
66 m_map_id_to_kf
.put (id
, kf
.release ());
70 known_function_manager::add_std_ns (const char *name
,
71 std::unique_ptr
<known_function
> kf
)
73 LOG_FUNC_1 (get_logger (), "registering std::%s", name
);
74 tree id
= get_identifier (name
);
75 m_std_ns_map_id_to_kf
.put (id
, kf
.release ());
79 known_function_manager::add (enum built_in_function name
,
80 std::unique_ptr
<known_function
> kf
)
82 gcc_assert (name
< END_BUILTINS
);
83 delete m_combined_fns_arr
[name
];
84 m_combined_fns_arr
[name
] = kf
.release ();
88 known_function_manager::add (enum internal_fn ifn
,
89 std::unique_ptr
<known_function
> kf
)
91 gcc_assert (ifn
< IFN_LAST
);
92 delete m_combined_fns_arr
[ifn
+ END_BUILTINS
];
93 m_combined_fns_arr
[ifn
+ END_BUILTINS
] = kf
.release ();
96 /* Get any known_function for FNDECL for call CD.
98 The call must match all assumptions made by the known_function (such as
99 e.g. "argument 1's type must be a pointer type").
101 Return NULL if no known_function is found, or it does not match the
104 const known_function
*
105 known_function_manager::get_match (tree fndecl
, const call_details
&cd
) const
107 /* Look for a matching built-in. */
108 if (fndecl_built_in_p (fndecl
, BUILT_IN_NORMAL
))
110 if (const known_function
*candidate
111 = get_normal_builtin (DECL_FUNCTION_CODE (fndecl
)))
112 if (gimple_builtin_call_types_compatible_p (cd
.get_call_stmt (),
117 /* Look for a match by name. */
119 if (is_std_function_p (fndecl
))
121 if (tree identifier
= DECL_NAME (fndecl
))
122 if (const known_function
*candidate
123 = get_by_identifier_in_std_ns (identifier
))
124 if (candidate
->matches_call_types_p (cd
))
129 if (DECL_CONTEXT (fndecl
)
130 && TREE_CODE (DECL_CONTEXT (fndecl
)) != TRANSLATION_UNIT_DECL
)
132 if (tree identifier
= DECL_NAME (fndecl
))
133 if (const known_function
*candidate
= get_by_identifier (identifier
))
134 if (candidate
->matches_call_types_p (cd
))
140 /* Get any known_function for IFN, or NULL. */
142 const known_function
*
143 known_function_manager::get_internal_fn (enum internal_fn ifn
) const
145 gcc_assert (ifn
< IFN_LAST
);
146 return m_combined_fns_arr
[ifn
+ END_BUILTINS
];
149 /* Get any known_function for NAME, without type-checking.
150 Return NULL if there isn't one. */
152 const known_function
*
153 known_function_manager::get_normal_builtin (enum built_in_function name
) const
155 /* The numbers for built-in functions in enum combined_fn are the same as
156 for the built_in_function enum. */
157 gcc_assert (name
< END_BUILTINS
);
158 return m_combined_fns_arr
[name
];
161 const known_function
*
162 known_function_manager::
163 get_normal_builtin (const builtin_known_function
*builtin_kf
) const
165 return get_normal_builtin (builtin_kf
->builtin_code ());
168 /* Get any known_function matching IDENTIFIER, without type-checking.
169 Return NULL if there isn't one. */
171 const known_function
*
172 known_function_manager::get_by_identifier (tree identifier
) const
174 known_function_manager
*mut_this
= const_cast<known_function_manager
*>(this);
175 known_function
**slot
= mut_this
->m_map_id_to_kf
.get (identifier
);
182 /* Get any known_function in C++ std:: namespace matching IDENTIFIER, without
184 Return nullptr if there isn't one. */
186 const known_function
*
187 known_function_manager::get_by_identifier_in_std_ns (tree identifier
) const
189 known_function_manager
*mut_this
= const_cast<known_function_manager
*>(this);
190 known_function
**slot
= mut_this
->m_std_ns_map_id_to_kf
.get (identifier
);
200 #endif /* #if ENABLE_ANALYZER */