On 11/15/19 6:23 PM, David Malcolm wrote:
gcc/ChangeLog: * analyzer/analyzer.cc: New file. * analyzer/analyzer.h: New file.
Here are a few more comments/suggestions as I'm slowly making my way through the patch, partly for my own benefit. Hopefully they're at least moderately useful.
--- gcc/analyzer/analyzer.cc | 125 ++++++++++++++++++++++++++++++++++++++++++++++ gcc/analyzer/analyzer.h | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 gcc/analyzer/analyzer.cc create mode 100644 gcc/analyzer/analyzer.h diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc new file mode 100644 index 0000000..399925c --- /dev/null +++ b/gcc/analyzer/analyzer.cc @@ -0,0 +1,125 @@ +/* Utility functions for the analyzer. + Copyright (C) 2019 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalc...@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 "gcc-plugin.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "gimple.h" +#include "diagnostic.h" +#include "intl.h" +#include "analyzer/analyzer.h" + +/* Helper function for checkers. Is the CALL to the given function name? */ + +bool +is_named_call_p (const gcall *call, const char *funcname) +{ + gcc_assert (funcname); + + tree fndecl = gimple_call_fndecl (call); + if (!fndecl) + return false; + + return 0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname); +} + +/* Helper function for checkers. Is the CALL to the given function name, + and with the given number of arguments? */ + +bool +is_named_call_p (const gcall *call, const char *funcname, + unsigned int num_args) +{ + gcc_assert (funcname); + + if (!is_named_call_p (call, 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_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_named_call_p (call, "longjmp", 2)) + return true; + + return false; +}
I haven't actually needed these helper functions myself but they seem quite generic and might make good additions to gimple.h.
+ +/* 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 = ≈ + 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; +} diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h new file mode 100644 index 0000000..ace8924 --- /dev/null +++ b/gcc/analyzer/analyzer.h @@ -0,0 +1,126 @@ +/* Utility functions for the analyzer. + Copyright (C) 2019 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalc...@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/>. */ + +#ifndef GCC_ANALYZER_ANALYZER_H +#define GCC_ANALYZER_ANALYZER_H + +/* Forward decls of common types, with indentation to show inheritance. */ + +class graphviz_out; +class supergraph; +class supernode; +class superedge; + class cfg_superedge; + class switch_cfg_superedge; + class callgraph_superedge; + class call_superedge; + class return_superedge; +class svalue; + class region_svalue; + class constant_svalue; + class poisoned_svalue; + class unknown_svalue; + class setjmp_svalue; +class region; + class map_region; + class symbolic_region; +class region_model; +class region_model_context; + class impl_region_model_context; +class constraint_manager; +class equiv_class; +struct model_merger; +struct svalue_id_merger_mapping; +struct canonicalization; +class pending_diagnostic; +class checker_path; +class extrinsic_state; +class sm_state_map; +class stmt_finder; +class program_point; +class program_state; +class exploded_graph; +class exploded_node; +class exploded_edge; +class exploded_cluster; +class exploded_path; +class analysis_plan; +class state_purge_map; +class state_purge_per_ssa_name; +class state_change; + +//////////////////////////////////////////////////////////////////////////// + +extern bool is_named_call_p (const gcall *call, const char *funcname); +extern bool is_named_call_p (const gcall *call, const char *funcname, + unsigned int num_args); +extern bool is_setjmp_call_p (const gimple *stmt); +extern bool is_longjmp_call_p (const gcall *call);
There are functions in GCC that match either is_xxx() and xxx_p() but by in my experience (and now also by my count) the latter is far more prevalent: 538 vs 3,172. I count just 28 functions that combine the two into is_xxx_p(). I think it would make sense to choose either of the two dominant forms over the is_xxx_p() combination here. (Ideally, there'd be just one style to make it easy to remember.)
+ +extern void register_analyzer_pass (); + +extern label_text make_label_text (bool can_colorize, const char *fmt, ...); + +//////////////////////////////////////////////////////////////////////////// + +/* An RAII-style class for pushing/popping cfun within a scope. + Doing so ensures we get "In function " announcements + from the diagnostics subsystem. */ + +class auto_cfun +{ +public: + auto_cfun (function *fun) { push_cfun (fun); } + ~auto_cfun () { pop_cfun (); } +};
This also seems like a nice general-purpose utility that might be worth adding someplace more central. I thought I'd seen code like this in the compiler already but all I can find now is a plenty of calls to push_cfun and but just one to pop.
+ +//////////////////////////////////////////////////////////////////////////// + +/* Begin suppressing -Wformat and -Wformat-extra-args. */ + +#define PUSH_IGNORE_WFORMAT \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wformat\"") \ + _Pragma("GCC diagnostic ignored \"-Wformat-extra-args\"") + +/* Finish suppressing -Wformat and -Wformat-extra-args. */ + +#define POP_IGNORE_WFORMAT \ + _Pragma("GCC diagnostic pop") + +//////////////////////////////////////////////////////////////////////////// + +/* A template for creating hash traits for a POD type. */ + +template <typename Type> +struct pod_hash_traits : typed_noop_remove<Type>
Would it make sense to add this to hash-traits.h? Martin
+{ + typedef Type value_type; + typedef Type compare_type; + static inline hashval_t hash (value_type); + static inline bool equal (const value_type &existing, + const value_type &candidate); + static inline void mark_deleted (Type &); + static inline void mark_empty (Type &); + static inline bool is_deleted (Type); + static inline bool is_empty (Type); +}; + +#endif /* GCC_ANALYZER_ANALYZER_H */