1 /* Utility functions for the analyzer.
2 Copyright (C) 2019-2020 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/>. */
23 #include "coretypes.h"
26 #include "basic-block.h"
28 #include "diagnostic.h"
31 #include "analyzer/analyzer.h"
37 /* Workaround for missing location information for some stmts,
38 which ultimately should be solved by fixing the frontends
39 to provide the locations (TODO). */
42 get_stmt_location (const gimple
*stmt
, function
*fun
)
44 if (get_pure_location (stmt
->location
) == UNKNOWN_LOCATION
)
46 /* Workaround for missing location information for clobber
47 stmts, which seem to lack location information in the C frontend
48 at least. Created by gimplify_bind_expr, which uses the
49 BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr))
50 but this is never set up when the block is created in
51 c_end_compound_stmt's pop_scope.
52 TODO: fix this missing location information.
54 For now, as a hackish workaround, use the location of the end of
56 if (gimple_clobber_p (stmt
) && fun
)
57 return fun
->function_end_locus
;
60 return stmt
->location
;
65 /* Helper function for checkers. Is the CALL to the given function name,
66 and with the given number of arguments?
68 This doesn't resolve function pointers via the region model;
69 is_named_call_p should be used instead, using a fndecl from
70 get_fndecl_for_call; this function should only be used for special cases
71 where it's not practical to get at the region model, or for special
72 analyzer functions such as __analyzer_dump. */
75 is_special_named_call_p (const gcall
*call
, const char *funcname
,
76 unsigned int num_args
)
78 gcc_assert (funcname
);
80 tree fndecl
= gimple_call_fndecl (call
);
84 return is_named_call_p (fndecl
, funcname
, call
, num_args
);
87 /* Helper function for checkers. Is FNDECL an extern fndecl at file scope
88 that has the given FUNCNAME?
90 Compare with special_function_p in calls.c. */
93 is_named_call_p (tree fndecl
, const char *funcname
)
96 gcc_assert (funcname
);
98 if (!maybe_special_function_p (fndecl
))
101 tree identifier
= DECL_NAME (fndecl
);
102 const char *name
= IDENTIFIER_POINTER (identifier
);
103 const char *tname
= name
;
105 /* Potentially disregard prefix _ or __ in FNDECL's name, but not if
106 FUNCNAME itself has leading underscores (e.g. when looking for
107 "__analyzer_eval"). */
108 if (funcname
[0] != '_' && name
[0] == '_')
116 return 0 == strcmp (tname
, funcname
);
119 /* Return true if FNDECL is within the namespace "std".
120 Compare with cp/typeck.c: decl_in_std_namespace_p, but this doesn't
121 rely on being the C++ FE (or handle inline namespaces inside of std). */
124 is_std_function_p (const_tree fndecl
)
126 tree name_decl
= DECL_NAME (fndecl
);
129 if (!DECL_CONTEXT (fndecl
))
131 if (TREE_CODE (DECL_CONTEXT (fndecl
)) != NAMESPACE_DECL
)
133 tree ns
= DECL_CONTEXT (fndecl
);
134 if (!(DECL_CONTEXT (ns
) == NULL_TREE
135 || TREE_CODE (DECL_CONTEXT (ns
)) == TRANSLATION_UNIT_DECL
))
139 return id_equal ("std", DECL_NAME (ns
));
142 /* Like is_named_call_p, but look for std::FUNCNAME. */
145 is_std_named_call_p (tree fndecl
, const char *funcname
)
148 gcc_assert (funcname
);
150 if (!is_std_function_p (fndecl
))
153 tree identifier
= DECL_NAME (fndecl
);
154 const char *name
= IDENTIFIER_POINTER (identifier
);
155 const char *tname
= name
;
157 /* Don't disregard prefix _ or __ in FNDECL's name. */
159 return 0 == strcmp (tname
, funcname
);
162 /* Helper function for checkers. Is FNDECL an extern fndecl at file scope
163 that has the given FUNCNAME, and does CALL have the given number of
167 is_named_call_p (tree fndecl
, const char *funcname
,
168 const gcall
*call
, unsigned int num_args
)
171 gcc_assert (funcname
);
173 if (!is_named_call_p (fndecl
, funcname
))
176 if (gimple_call_num_args (call
) != num_args
)
182 /* Like is_named_call_p, but check for std::FUNCNAME. */
185 is_std_named_call_p (tree fndecl
, const char *funcname
,
186 const gcall
*call
, unsigned int num_args
)
189 gcc_assert (funcname
);
191 if (!is_std_named_call_p (fndecl
, funcname
))
194 if (gimple_call_num_args (call
) != num_args
)
200 /* Return true if stmt is a setjmp or sigsetjmp call. */
203 is_setjmp_call_p (const gcall
*call
)
205 if (is_special_named_call_p (call
, "setjmp", 1)
206 || is_special_named_call_p (call
, "sigsetjmp", 2))
207 /* region_model::on_setjmp requires a pointer. */
208 if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
214 /* Return true if stmt is a longjmp or siglongjmp call. */
217 is_longjmp_call_p (const gcall
*call
)
219 if (is_special_named_call_p (call
, "longjmp", 2)
220 || is_special_named_call_p (call
, "siglongjmp", 2))
221 /* exploded_node::on_longjmp requires a pointer for the initial
223 if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
229 /* For a CALL that matched is_special_named_call_p or is_named_call_p for
230 some name, return a name for the called function suitable for use in
231 diagnostics (stripping the leading underscores). */
234 get_user_facing_name (const gcall
*call
)
236 tree fndecl
= gimple_call_fndecl (call
);
239 tree identifier
= DECL_NAME (fndecl
);
240 gcc_assert (identifier
);
242 const char *name
= IDENTIFIER_POINTER (identifier
);
244 /* Strip prefix _ or __ in FNDECL's name. */
256 /* Generate a label_text instance by formatting FMT, using a
257 temporary clone of the global_dc's printer (thus using its
258 formatting callbacks).
260 Colorize if the global_dc supports colorization and CAN_COLORIZE is
264 make_label_text (bool can_colorize
, const char *fmt
, ...)
266 pretty_printer
*pp
= global_dc
->printer
->clone ();
267 pp_clear_output_area (pp
);
270 pp_show_color (pp
) = false;
273 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
279 ti
.format_spec
= _(fmt
);
283 ti
.m_richloc
= &rich_loc
;
286 pp_output_formatted_text (pp
);
290 label_text result
= label_text::take (xstrdup (pp_formatted_text (pp
)));
295 #endif /* #if ENABLE_ANALYZER */