1*4c3eb207Smrg /* Utility functions for the analyzer.
2*4c3eb207Smrg Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*4c3eb207Smrg Contributed by David Malcolm <dmalcolm@redhat.com>.
4*4c3eb207Smrg
5*4c3eb207Smrg This file is part of GCC.
6*4c3eb207Smrg
7*4c3eb207Smrg GCC is free software; you can redistribute it and/or modify it
8*4c3eb207Smrg under the terms of the GNU General Public License as published by
9*4c3eb207Smrg the Free Software Foundation; either version 3, or (at your option)
10*4c3eb207Smrg any later version.
11*4c3eb207Smrg
12*4c3eb207Smrg GCC is distributed in the hope that it will be useful, but
13*4c3eb207Smrg WITHOUT ANY WARRANTY; without even the implied warranty of
14*4c3eb207Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15*4c3eb207Smrg General Public License for more details.
16*4c3eb207Smrg
17*4c3eb207Smrg You should have received a copy of the GNU General Public License
18*4c3eb207Smrg along with GCC; see the file COPYING3. If not see
19*4c3eb207Smrg <http://www.gnu.org/licenses/>. */
20*4c3eb207Smrg
21*4c3eb207Smrg #include "config.h"
22*4c3eb207Smrg #include "system.h"
23*4c3eb207Smrg #include "coretypes.h"
24*4c3eb207Smrg #include "tree.h"
25*4c3eb207Smrg #include "function.h"
26*4c3eb207Smrg #include "basic-block.h"
27*4c3eb207Smrg #include "gimple.h"
28*4c3eb207Smrg #include "diagnostic.h"
29*4c3eb207Smrg #include "intl.h"
30*4c3eb207Smrg #include "function.h"
31*4c3eb207Smrg #include "analyzer/analyzer.h"
32*4c3eb207Smrg
33*4c3eb207Smrg #if ENABLE_ANALYZER
34*4c3eb207Smrg
35*4c3eb207Smrg /* Helper function for checkers. Is the CALL to the given function name,
36*4c3eb207Smrg and with the given number of arguments?
37*4c3eb207Smrg
38*4c3eb207Smrg This doesn't resolve function pointers via the region model;
39*4c3eb207Smrg is_named_call_p should be used instead, using a fndecl from
40*4c3eb207Smrg get_fndecl_for_call; this function should only be used for special cases
41*4c3eb207Smrg where it's not practical to get at the region model, or for special
42*4c3eb207Smrg analyzer functions such as __analyzer_dump. */
43*4c3eb207Smrg
44*4c3eb207Smrg bool
is_special_named_call_p(const gcall * call,const char * funcname,unsigned int num_args)45*4c3eb207Smrg is_special_named_call_p (const gcall *call, const char *funcname,
46*4c3eb207Smrg unsigned int num_args)
47*4c3eb207Smrg {
48*4c3eb207Smrg gcc_assert (funcname);
49*4c3eb207Smrg
50*4c3eb207Smrg tree fndecl = gimple_call_fndecl (call);
51*4c3eb207Smrg if (!fndecl)
52*4c3eb207Smrg return false;
53*4c3eb207Smrg
54*4c3eb207Smrg return is_named_call_p (fndecl, funcname, call, num_args);
55*4c3eb207Smrg }
56*4c3eb207Smrg
57*4c3eb207Smrg /* Helper function for checkers. Is FNDECL an extern fndecl at file scope
58*4c3eb207Smrg that has the given FUNCNAME?
59*4c3eb207Smrg
60*4c3eb207Smrg Compare with special_function_p in calls.c. */
61*4c3eb207Smrg
62*4c3eb207Smrg bool
is_named_call_p(tree fndecl,const char * funcname)63*4c3eb207Smrg is_named_call_p (tree fndecl, const char *funcname)
64*4c3eb207Smrg {
65*4c3eb207Smrg gcc_assert (fndecl);
66*4c3eb207Smrg gcc_assert (funcname);
67*4c3eb207Smrg
68*4c3eb207Smrg if (!maybe_special_function_p (fndecl))
69*4c3eb207Smrg return false;
70*4c3eb207Smrg
71*4c3eb207Smrg tree identifier = DECL_NAME (fndecl);
72*4c3eb207Smrg const char *name = IDENTIFIER_POINTER (identifier);
73*4c3eb207Smrg const char *tname = name;
74*4c3eb207Smrg
75*4c3eb207Smrg /* Potentially disregard prefix _ or __ in FNDECL's name, but not if
76*4c3eb207Smrg FUNCNAME itself has leading underscores (e.g. when looking for
77*4c3eb207Smrg "__analyzer_eval"). */
78*4c3eb207Smrg if (funcname[0] != '_' && name[0] == '_')
79*4c3eb207Smrg {
80*4c3eb207Smrg if (name[1] == '_')
81*4c3eb207Smrg tname += 2;
82*4c3eb207Smrg else
83*4c3eb207Smrg tname += 1;
84*4c3eb207Smrg }
85*4c3eb207Smrg
86*4c3eb207Smrg return 0 == strcmp (tname, funcname);
87*4c3eb207Smrg }
88*4c3eb207Smrg
89*4c3eb207Smrg /* Return true if FNDECL is within the namespace "std".
90*4c3eb207Smrg Compare with cp/typeck.c: decl_in_std_namespace_p, but this doesn't
91*4c3eb207Smrg rely on being the C++ FE (or handle inline namespaces inside of std). */
92*4c3eb207Smrg
93*4c3eb207Smrg static inline bool
is_std_function_p(const_tree fndecl)94*4c3eb207Smrg is_std_function_p (const_tree fndecl)
95*4c3eb207Smrg {
96*4c3eb207Smrg tree name_decl = DECL_NAME (fndecl);
97*4c3eb207Smrg if (!name_decl)
98*4c3eb207Smrg return false;
99*4c3eb207Smrg if (!DECL_CONTEXT (fndecl))
100*4c3eb207Smrg return false;
101*4c3eb207Smrg if (TREE_CODE (DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
102*4c3eb207Smrg return false;
103*4c3eb207Smrg tree ns = DECL_CONTEXT (fndecl);
104*4c3eb207Smrg if (!(DECL_CONTEXT (ns) == NULL_TREE
105*4c3eb207Smrg || TREE_CODE (DECL_CONTEXT (ns)) == TRANSLATION_UNIT_DECL))
106*4c3eb207Smrg return false;
107*4c3eb207Smrg if (!DECL_NAME (ns))
108*4c3eb207Smrg return false;
109*4c3eb207Smrg return id_equal ("std", DECL_NAME (ns));
110*4c3eb207Smrg }
111*4c3eb207Smrg
112*4c3eb207Smrg /* Like is_named_call_p, but look for std::FUNCNAME. */
113*4c3eb207Smrg
114*4c3eb207Smrg bool
is_std_named_call_p(tree fndecl,const char * funcname)115*4c3eb207Smrg is_std_named_call_p (tree fndecl, const char *funcname)
116*4c3eb207Smrg {
117*4c3eb207Smrg gcc_assert (fndecl);
118*4c3eb207Smrg gcc_assert (funcname);
119*4c3eb207Smrg
120*4c3eb207Smrg if (!is_std_function_p (fndecl))
121*4c3eb207Smrg return false;
122*4c3eb207Smrg
123*4c3eb207Smrg tree identifier = DECL_NAME (fndecl);
124*4c3eb207Smrg const char *name = IDENTIFIER_POINTER (identifier);
125*4c3eb207Smrg const char *tname = name;
126*4c3eb207Smrg
127*4c3eb207Smrg /* Don't disregard prefix _ or __ in FNDECL's name. */
128*4c3eb207Smrg
129*4c3eb207Smrg return 0 == strcmp (tname, funcname);
130*4c3eb207Smrg }
131*4c3eb207Smrg
132*4c3eb207Smrg /* Helper function for checkers. Is FNDECL an extern fndecl at file scope
133*4c3eb207Smrg that has the given FUNCNAME, and does CALL have the given number of
134*4c3eb207Smrg arguments? */
135*4c3eb207Smrg
136*4c3eb207Smrg bool
is_named_call_p(tree fndecl,const char * funcname,const gcall * call,unsigned int num_args)137*4c3eb207Smrg is_named_call_p (tree fndecl, const char *funcname,
138*4c3eb207Smrg const gcall *call, unsigned int num_args)
139*4c3eb207Smrg {
140*4c3eb207Smrg gcc_assert (fndecl);
141*4c3eb207Smrg gcc_assert (funcname);
142*4c3eb207Smrg
143*4c3eb207Smrg if (!is_named_call_p (fndecl, funcname))
144*4c3eb207Smrg return false;
145*4c3eb207Smrg
146*4c3eb207Smrg if (gimple_call_num_args (call) != num_args)
147*4c3eb207Smrg return false;
148*4c3eb207Smrg
149*4c3eb207Smrg return true;
150*4c3eb207Smrg }
151*4c3eb207Smrg
152*4c3eb207Smrg /* Like is_named_call_p, but check for std::FUNCNAME. */
153*4c3eb207Smrg
154*4c3eb207Smrg bool
is_std_named_call_p(tree fndecl,const char * funcname,const gcall * call,unsigned int num_args)155*4c3eb207Smrg is_std_named_call_p (tree fndecl, const char *funcname,
156*4c3eb207Smrg const gcall *call, unsigned int num_args)
157*4c3eb207Smrg {
158*4c3eb207Smrg gcc_assert (fndecl);
159*4c3eb207Smrg gcc_assert (funcname);
160*4c3eb207Smrg
161*4c3eb207Smrg if (!is_std_named_call_p (fndecl, funcname))
162*4c3eb207Smrg return false;
163*4c3eb207Smrg
164*4c3eb207Smrg if (gimple_call_num_args (call) != num_args)
165*4c3eb207Smrg return false;
166*4c3eb207Smrg
167*4c3eb207Smrg return true;
168*4c3eb207Smrg }
169*4c3eb207Smrg
170*4c3eb207Smrg /* Return true if stmt is a setjmp or sigsetjmp call. */
171*4c3eb207Smrg
172*4c3eb207Smrg bool
is_setjmp_call_p(const gcall * call)173*4c3eb207Smrg is_setjmp_call_p (const gcall *call)
174*4c3eb207Smrg {
175*4c3eb207Smrg if (is_special_named_call_p (call, "setjmp", 1)
176*4c3eb207Smrg || is_special_named_call_p (call, "sigsetjmp", 2))
177*4c3eb207Smrg return true;
178*4c3eb207Smrg
179*4c3eb207Smrg return false;
180*4c3eb207Smrg }
181*4c3eb207Smrg
182*4c3eb207Smrg /* Return true if stmt is a longjmp or siglongjmp call. */
183*4c3eb207Smrg
184*4c3eb207Smrg bool
is_longjmp_call_p(const gcall * call)185*4c3eb207Smrg is_longjmp_call_p (const gcall *call)
186*4c3eb207Smrg {
187*4c3eb207Smrg if (is_special_named_call_p (call, "longjmp", 2)
188*4c3eb207Smrg || is_special_named_call_p (call, "siglongjmp", 2))
189*4c3eb207Smrg return true;
190*4c3eb207Smrg
191*4c3eb207Smrg return false;
192*4c3eb207Smrg }
193*4c3eb207Smrg
194*4c3eb207Smrg /* For a CALL that matched is_special_named_call_p or is_named_call_p for
195*4c3eb207Smrg some name, return a name for the called function suitable for use in
196*4c3eb207Smrg diagnostics (stripping the leading underscores). */
197*4c3eb207Smrg
198*4c3eb207Smrg const char *
get_user_facing_name(const gcall * call)199*4c3eb207Smrg get_user_facing_name (const gcall *call)
200*4c3eb207Smrg {
201*4c3eb207Smrg tree fndecl = gimple_call_fndecl (call);
202*4c3eb207Smrg gcc_assert (fndecl);
203*4c3eb207Smrg
204*4c3eb207Smrg tree identifier = DECL_NAME (fndecl);
205*4c3eb207Smrg gcc_assert (identifier);
206*4c3eb207Smrg
207*4c3eb207Smrg const char *name = IDENTIFIER_POINTER (identifier);
208*4c3eb207Smrg
209*4c3eb207Smrg /* Strip prefix _ or __ in FNDECL's name. */
210*4c3eb207Smrg if (name[0] == '_')
211*4c3eb207Smrg {
212*4c3eb207Smrg if (name[1] == '_')
213*4c3eb207Smrg return name + 2;
214*4c3eb207Smrg else
215*4c3eb207Smrg return name + 1;
216*4c3eb207Smrg }
217*4c3eb207Smrg
218*4c3eb207Smrg return name;
219*4c3eb207Smrg }
220*4c3eb207Smrg
221*4c3eb207Smrg /* Generate a label_text instance by formatting FMT, using a
222*4c3eb207Smrg temporary clone of the global_dc's printer (thus using its
223*4c3eb207Smrg formatting callbacks).
224*4c3eb207Smrg
225*4c3eb207Smrg Colorize if the global_dc supports colorization and CAN_COLORIZE is
226*4c3eb207Smrg true. */
227*4c3eb207Smrg
228*4c3eb207Smrg label_text
make_label_text(bool can_colorize,const char * fmt,...)229*4c3eb207Smrg make_label_text (bool can_colorize, const char *fmt, ...)
230*4c3eb207Smrg {
231*4c3eb207Smrg pretty_printer *pp = global_dc->printer->clone ();
232*4c3eb207Smrg pp_clear_output_area (pp);
233*4c3eb207Smrg
234*4c3eb207Smrg if (!can_colorize)
235*4c3eb207Smrg pp_show_color (pp) = false;
236*4c3eb207Smrg
237*4c3eb207Smrg text_info ti;
238*4c3eb207Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
239*4c3eb207Smrg
240*4c3eb207Smrg va_list ap;
241*4c3eb207Smrg
242*4c3eb207Smrg va_start (ap, fmt);
243*4c3eb207Smrg
244*4c3eb207Smrg ti.format_spec = _(fmt);
245*4c3eb207Smrg ti.args_ptr = ≈
246*4c3eb207Smrg ti.err_no = 0;
247*4c3eb207Smrg ti.x_data = NULL;
248*4c3eb207Smrg ti.m_richloc = &rich_loc;
249*4c3eb207Smrg
250*4c3eb207Smrg pp_format (pp, &ti);
251*4c3eb207Smrg pp_output_formatted_text (pp);
252*4c3eb207Smrg
253*4c3eb207Smrg va_end (ap);
254*4c3eb207Smrg
255*4c3eb207Smrg label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
256*4c3eb207Smrg delete pp;
257*4c3eb207Smrg return result;
258*4c3eb207Smrg }
259*4c3eb207Smrg
260*4c3eb207Smrg #endif /* #if ENABLE_ANALYZER */
261