analyzer: only use CWE-690 for unchecked return value [PR97893]
[gcc.git] / gcc / analyzer / supergraph.cc
index 7c6fed3a060da85e211bc1eeb6a3a56bf5a7046a..37f143c6fca007aa4ba604837531f55619a908ec 100644 (file)
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-dfa.h"
 #include "cfganal.h"
 #include "function.h"
+#include "json.h"
 #include "analyzer/analyzer.h"
 #include "ordered-hash-map.h"
 #include "options.h"
@@ -89,7 +90,8 @@ supergraph_call_edge (function *fun, gimple *stmt)
 /* supergraph's ctor.  Walk the callgraph, building supernodes for each
    CFG basic block, splitting the basic blocks at callsites.  Join
    together the supernodes with interprocedural and intraprocedural
-   superedges as appropriate.  */
+   superedges as appropriate.
+   Assign UIDs to the gimple stmts.  */
 
 supergraph::supergraph (logger *logger)
 {
@@ -97,8 +99,10 @@ supergraph::supergraph (logger *logger)
 
   LOG_FUNC (logger);
 
-  /* First pass: make supernodes.  */
+  /* First pass: make supernodes (and assign UIDs to the gimple stmts).  */
   {
+    unsigned next_uid = 0;
+
     /* Sort the cgraph_nodes?  */
     cgraph_node *node;
     FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
@@ -123,6 +127,7 @@ supergraph::supergraph (logger *logger)
            {
              gimple *stmt = gsi_stmt (gpi);
              m_stmt_to_node_t.put (stmt, node_for_stmts);
+             stmt->uid = next_uid++;
            }
 
          /* Append statements from BB to the current supernode, splitting
@@ -134,6 +139,7 @@ supergraph::supergraph (logger *logger)
              gimple *stmt = gsi_stmt (gsi);
              node_for_stmts->m_stmts.safe_push (stmt);
              m_stmt_to_node_t.put (stmt, node_for_stmts);
+             stmt->uid = next_uid++;
              if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
                {
                  m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
@@ -374,6 +380,38 @@ supergraph::dump_dot (const char *path, const dump_args_t &dump_args) const
   fclose (fp);
 }
 
+/* Return a new json::object of the form
+   {"nodes" : [objs for snodes],
+    "edges" : [objs for sedges]}.  */
+
+json::object *
+supergraph::to_json () const
+{
+  json::object *sgraph_obj = new json::object ();
+
+  /* Nodes.  */
+  {
+    json::array *nodes_arr = new json::array ();
+    unsigned i;
+    supernode *n;
+    FOR_EACH_VEC_ELT (m_nodes, i, n)
+      nodes_arr->append (n->to_json ());
+    sgraph_obj->set ("nodes", nodes_arr);
+  }
+
+  /* Edges.  */
+  {
+    json::array *edges_arr = new json::array ();
+    unsigned i;
+    superedge *n;
+    FOR_EACH_VEC_ELT (m_edges, i, n)
+      edges_arr->append (n->to_json ());
+    sgraph_obj->set ("edges", edges_arr);
+  }
+
+  return sgraph_obj;
+}
+
 /* Create a supernode for BB within FUN and add it to this supergraph.
 
    If RETURNING_CALL is non-NULL, the supernode represents the resumption
@@ -594,6 +632,63 @@ supernode::dump_dot_id (pretty_printer *pp) const
   pp_printf (pp, "node_%i", m_index);
 }
 
+/* Return a new json::object of the form
+   {"idx": int,
+    "bb_idx": int,
+    "m_returning_call": optional str,
+    "phis": [str],
+    "stmts" : [str]}.  */
+
+json::object *
+supernode::to_json () const
+{
+  json::object *snode_obj = new json::object ();
+
+  snode_obj->set ("idx", new json::integer_number (m_index));
+  snode_obj->set ("bb_idx", new json::integer_number (m_bb->index));
+
+  if (m_returning_call)
+    {
+      pretty_printer pp;
+      pp_format_decoder (&pp) = default_tree_printer;
+      pp_gimple_stmt_1 (&pp, m_returning_call, 0, (dump_flags_t)0);
+      snode_obj->set ("returning_call",
+                     new json::string (pp_formatted_text (&pp)));
+    }
+
+  /* Phi nodes.  */
+  {
+    json::array *phi_arr = new json::array ();
+    for (gphi_iterator gpi = const_cast<supernode *> (this)->start_phis ();
+        !gsi_end_p (gpi); gsi_next (&gpi))
+      {
+       const gimple *stmt = gsi_stmt (gpi);
+       pretty_printer pp;
+       pp_format_decoder (&pp) = default_tree_printer;
+       pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
+       phi_arr->append (new json::string (pp_formatted_text (&pp)));
+      }
+    snode_obj->set ("phis", phi_arr);
+  }
+
+  /* Statements.  */
+  {
+    json::array *stmt_arr = new json::array ();
+    int i;
+    gimple *stmt;
+    FOR_EACH_VEC_ELT (m_stmts, i, stmt)
+      {
+       pretty_printer pp;
+       pp_format_decoder (&pp) = default_tree_printer;
+       pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
+       stmt_arr->append (new json::string (pp_formatted_text (&pp)));
+      }
+    snode_obj->set ("stmts", stmt_arr);
+  }
+
+  return snode_obj;
+}
+
 /* Get a location_t for the start of this supernode.  */
 
 location_t
@@ -759,6 +854,28 @@ superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const
   pp_printf (pp, "\"];\n");
 }
 
+/* Return a new json::object of the form
+   {"src_idx": int, the index of the source supernode,
+    "dst_idx": int, the index of the destination supernode,
+    "desc"   : str.  */
+
+json::object *
+superedge::to_json () const
+{
+  json::object *sedge_obj = new json::object ();
+  sedge_obj->set ("src_idx", new json::integer_number (m_src->m_index));
+  sedge_obj->set ("dst_idx", new json::integer_number (m_dest->m_index));
+
+  {
+    pretty_printer pp;
+    pp_format_decoder (&pp) = default_tree_printer;
+    dump_label_to_pp (&pp, false);
+    sedge_obj->set ("desc", new json::string (pp_formatted_text (&pp)));
+  }
+
+  return sedge_obj;
+}
+
 /* If this is an intraprocedural superedge, return the associated
    CFG edge.  Otherwise, return NULL.  */