aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/analyzer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/analyzer.cc')
-rw-r--r--gcc/analyzer/analyzer.cc151
1 files changed, 151 insertions, 0 deletions
diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
new file mode 100644
index 0000000..2a3ffae
--- /dev/null
+++ b/gcc/analyzer/analyzer.cc
@@ -0,0 +1,151 @@
+/* Utility functions for the analyzer.
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "diagnostic.h"
+#include "intl.h"
+#include "function.h"
+#include "analyzer/analyzer.h"
+
+#if ENABLE_ANALYZER
+
+/* Helper function for checkers. Is the CALL to the given function name,
+ and with the given number of arguments?
+
+ This doesn't resolve function pointers via the region model;
+ is_named_call_p should be used instead, using a fndecl from
+ get_fndecl_for_call; this function should only be used for special cases
+ where it's not practical to get at the region model, or for special
+ analyzer functions such as __analyzer_dump. */
+
+bool
+is_special_named_call_p (const gcall *call, const char *funcname,
+ unsigned int num_args)
+{
+ gcc_assert (funcname);
+
+ tree fndecl = gimple_call_fndecl (call);
+ if (!fndecl)
+ return false;
+
+ return is_named_call_p (fndecl, funcname, call, num_args);
+}
+
+/* Helper function for checkers. Does FNDECL have the given FUNCNAME? */
+
+bool
+is_named_call_p (tree fndecl, const char *funcname)
+{
+ gcc_assert (fndecl);
+ gcc_assert (funcname);
+
+ return 0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname);
+}
+
+/* Helper function for checkers. Does FNDECL have the given FUNCNAME, and
+ does CALL have the given number of arguments? */
+
+bool
+is_named_call_p (tree fndecl, const char *funcname,
+ const gcall *call, unsigned int num_args)
+{
+ gcc_assert (fndecl);
+ gcc_assert (funcname);
+
+ if (!is_named_call_p (fndecl, funcname))
+ return false;
+
+ if (gimple_call_num_args (call) != num_args)
+ return false;
+
+ return true;
+}
+
+/* Return true if stmt is a setjmp call. */
+
+bool
+is_setjmp_call_p (const gimple *stmt)
+{
+ /* TODO: is there a less hacky way to check for "setjmp"? */
+ if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ if (is_special_named_call_p (call, "_setjmp", 1))
+ return true;
+
+ return false;
+}
+
+/* Return true if stmt is a longjmp call. */
+
+bool
+is_longjmp_call_p (const gcall *call)
+{
+ /* TODO: is there a less hacky way to check for "longjmp"? */
+ if (is_special_named_call_p (call, "longjmp", 2))
+ return true;
+
+ return false;
+}
+
+/* Generate a label_text instance by formatting FMT, using a
+ temporary clone of the global_dc's printer (thus using its
+ formatting callbacks).
+
+ Colorize if the global_dc supports colorization and CAN_COLORIZE is
+ true. */
+
+label_text
+make_label_text (bool can_colorize, const char *fmt, ...)
+{
+ pretty_printer *pp = global_dc->printer->clone ();
+ pp_clear_output_area (pp);
+
+ if (!can_colorize)
+ pp_show_color (pp) = false;
+
+ text_info ti;
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+ va_list ap;
+
+ va_start (ap, fmt);
+
+ ti.format_spec = _(fmt);
+ ti.args_ptr = &ap;
+ ti.err_no = 0;
+ ti.x_data = NULL;
+ ti.m_richloc = &rich_loc;
+
+ pp_format (pp, &ti);
+ pp_output_formatted_text (pp);
+
+ va_end (ap);
+
+ label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
+ delete pp;
+ return result;
+}
+
+#endif /* #if ENABLE_ANALYZER */