From 93608de9f055e4229551dfcf7647b2e1d883b542 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 25 May 2017 10:41:13 -0400
Subject: [PATCH 04/38] FIXME: move to checkers.c and cleanup

---
 gcc/Makefile.in     |   2 +-
 gcc/checkers.c      | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/run-analyzers.c | 252 ---------------------------------------------------
 3 files changed, 257 insertions(+), 253 deletions(-)
 create mode 100644 gcc/checkers.c
 delete mode 100644 gcc/run-analyzers.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index c0408a4..b64c3e8 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1232,6 +1232,7 @@ OBJS = \
 	cfgloopanal.o \
 	cfgloopmanip.o \
 	cfgrtl.o \
+	checkers.o \
 	symtab.o \
 	cgraph.o \
 	cgraphbuild.o \
@@ -1441,7 +1442,6 @@ OBJS = \
 	rtlhash.o \
 	rtlanal.o \
 	rtlhooks.o \
-	run-analyzers.o \
 	run-rtl-passes.o \
 	sbitmap.o \
 	sched-deps.o \
diff --git a/gcc/checkers.c b/gcc/checkers.c
new file mode 100644
index 0000000..201628b
--- /dev/null
+++ b/gcc/checkers.c
@@ -0,0 +1,256 @@
+/* Running 3rd-party code analysis tools.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+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 "options.h"
+#include "diagnostic.h"
+#include "selftest.h" // FIXME
+#include "firehose.h"
+#include "json.h"
+
+/* FIXME.  */
+
+static void
+print_any_trace (const firehose::issue &issue)
+{
+  if (!issue.m_trace)
+    return;
+  if (0)
+    inform (UNKNOWN_LOCATION, "got trace");
+  int i;
+  firehose::state *s;
+  int num_states = issue.m_trace->m_states.length ();
+  FOR_EACH_VEC_ELT (issue.m_trace->m_states, i, s)
+    {
+      if (s->m_notes)
+	inform (s->m_location, "state %i of %i: %s", i + 1, num_states,
+		s->m_notes);
+      else
+	inform (s->m_location, "state %i of %i", i + 1, num_states);
+    }
+}
+
+bool
+diagnostic_at_rich_loc_va (rich_location *richloc,
+			   diagnostic_info *diagnostic,
+			   const char *gmsgid,
+			   va_list *ap)
+{
+  gcc_assert (richloc);
+  gcc_assert (diagnostic);
+  gcc_assert (gmsgid);
+  gcc_assert (ap);
+
+  diagnostic_t kind = diagnostic->kind;
+#if 0
+  if (kind == DK_PERMERROR)
+    {
+      diagnostic_set_info (diagnostic, gmsgid, ap, richloc,
+			   permissive_error_kind (global_dc));
+      diagnostic.option_index = permissive_error_option (global_dc);
+    }
+  else
+#endif
+    {
+      diagnostic_set_info (diagnostic, gmsgid, ap, richloc, kind);
+#if 0
+      if (kind == DK_WARNING || kind == DK_PEDWARN)
+	diagnostic.option_index = opt;
+#endif
+    }
+  return diagnostic_report_diagnostic (global_dc, diagnostic);
+}
+
+/* FIXME.  */
+
+void
+diagnostic_at (location_t loc, diagnostic_info *diagnostic,
+	       const char *gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, loc);
+  diagnostic_at_rich_loc_va (&richloc, diagnostic, gmsgid, &ap);
+  va_end (ap);
+}
+
+/* FIXME.  */
+
+static void
+handle_issue (const firehose::analysis &analysis,
+	      const firehose::issue &issue)
+{
+  // FIXME: generate "In function", perhaps based on blt_node ?
+  // FIXME:  ^^^ better to get it from the JSON
+  diagnostic_info diagnostic;
+  diagnostic.kind = DK_ERROR;
+  diagnostic.external_tool = analysis.m_metadata.m_generator.m_name;
+  diagnostic.external_test_id = issue.m_testid;
+  diagnostic_at (issue.m_location, &diagnostic, "%s",
+		 issue.m_message);
+  print_any_trace (issue);
+  // FIXME: identify metadata (which analyzer?)
+}
+
+/* Given UTF8_BUFFER, a non-NULL UTF-8-encoded buffer of JSON output
+   from a tool, in Firehose JSON format, emit the results through GCC's
+   diagnostic subsystem.  */
+
+static void
+handle_json (const char *utf8_buffer)
+{
+  /* Attempt to parse the buffer as UTF-8-encoded JSON.  */
+  char *err = NULL;
+  json::value *jv = json::parse_utf8_string (utf8_buffer, &err);
+  if (!jv)
+    {
+      gcc_assert (err);
+      error_at (UNKNOWN_LOCATION,
+		"unable to parse tool output as UTF-8 JSON: %s", err);
+      free (err);
+      return;
+    }
+
+  gcc_assert (err == NULL);
+
+  if (0)
+    {
+      jv->dump(stderr);
+      fprintf (stderr, "\n");
+    }
+
+  /* Attempt to parse the JSON values into Firehose objects.  */
+  firehose::analysis analysis;
+  analysis.from_json (jv, err);
+  if (err)
+    {
+      error_at (UNKNOWN_LOCATION, "error parsing JSON output: %qs", err);
+      free (err);
+      delete jv;
+      return;
+    }
+
+  gcc_assert (err == NULL);
+
+  /* Emit the results as GCC diagnostics.  */
+  int i;
+  firehose::result *result;
+  FOR_EACH_VEC_ELT (analysis.m_results, i, result)
+    {
+      switch (result->get_kind ())
+	{
+	case firehose::result::FIREHOSE_ISSUE:
+	  handle_issue (analysis, *static_cast <firehose::issue *> (result));
+	  break;
+
+	  // FIXME
+	default:
+	  gcc_unreachable ();
+	}
+    }
+
+  delete jv;
+}
+
+/* FIXME: taken from jit-playback.c.  */
+
+/* A subclass of auto_vec <char *> that frees all of its elements on
+   deletion.  */
+
+class auto_argvec : public auto_vec <char *>
+{
+ public:
+  ~auto_argvec ();
+};
+
+/* auto_argvec's dtor, freeing all contained strings, automatically
+   chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
+
+auto_argvec::~auto_argvec ()
+{
+  int i;
+  char *str;
+  FOR_EACH_VEC_ELT (*this, i, str)
+    free (str);
+}
+
+/* FIXME.  */
+
+static void
+run_one_analyzer (const char *wrapper_path)
+{
+  auto_argvec argvec;
+#define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
+
+  ADD_ARG (wrapper_path);
+  ADD_ARG ("-B."); // FIXME
+  ADD_ARG ("-c");
+  ADD_ARG (main_input_filename);
+
+  /* pex argv arrays are NULL-terminated.  */
+  argvec.safe_push (NULL);
+
+  const char *errmsg;
+  int exit_status = 0;
+  int err = 0;
+  /* FIXME: avoid using known filename; read direct from stdout.  */
+  errmsg = pex_one (PEX_SEARCH | PEX_LAST, /* int flags, */
+		    wrapper_path,
+		    const_cast <char *const *> (argvec.address ()),
+		    "FIXME:ctxt_progname", /* const char *pname */
+		    "temp.json", /* const char *outname */
+		    NULL, /* const char *errname */
+		    &exit_status, /* int *status */
+		    &err); /* int *err*/
+  if (errmsg)
+    {
+      error_at (UNKNOWN_LOCATION, "error invoking tool: %s", errmsg);
+      return;
+    }
+  if (exit_status || err)
+    {
+      error_at (UNKNOWN_LOCATION,
+		"error invoking tool: exit_status: %i err: %i",
+		exit_status, err);
+      return;
+    }
+
+  // FIXME: use something other than a selftest for this!
+  char *utf8_buffer = selftest::read_file (SELFTEST_LOCATION,
+				      "temp.json"); // FIXME: filename
+  // FIXME: error-checking
+  handle_json (utf8_buffer);
+  free (utf8_buffer);
+
+  // FIXME: capture clang version in metadata
+}
+
+/* FIXME.  */
+
+void
+run_analyzers (const char *path)
+{
+  if (0)
+    inform (UNKNOWN_LOCATION, "run_analyzers (%qs)", path);
+
+  run_one_analyzer ("../../src/fakegcc_clang_analyzer.py");
+  run_one_analyzer ("../../src/fakegcc_cppcheck.py");
+}
diff --git a/gcc/run-analyzers.c b/gcc/run-analyzers.c
deleted file mode 100644
index 04a4955..0000000
--- a/gcc/run-analyzers.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* Running 3rd-party code analysis tools.
-   Copyright (C) 2017 Free Software Foundation, Inc.
-
-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 "options.h"
-#include "diagnostic.h"
-#include "selftest.h" // FIXME
-#include "firehose.h"
-#include "json.h"
-
-/* FIXME.  */
-
-static void
-print_any_trace (const firehose::issue *issue)
-{
-  if (!issue->m_trace)
-    return;
-  if (0)
-    inform (UNKNOWN_LOCATION, "got trace");
-  int i;
-  firehose::state *s;
-  int num_states = issue->m_trace->m_states.length ();
-  FOR_EACH_VEC_ELT (issue->m_trace->m_states, i, s)
-    {
-      if (s->m_notes)
-	inform (s->m_location, "state %i of %i: %s", i + 1, num_states,
-		s->m_notes);
-      else
-	inform (s->m_location, "state %i of %i", i + 1, num_states);
-    }
-}
-
-bool
-diagnostic_at_rich_loc_va (rich_location *richloc,
-			   diagnostic_info *diagnostic,
-			   const char *gmsgid,
-			   va_list *ap)
-{
-  gcc_assert (richloc);
-  gcc_assert (diagnostic);
-  gcc_assert (gmsgid);
-  gcc_assert (ap);
-
-  diagnostic_t kind = diagnostic->kind;
-#if 0
-  if (kind == DK_PERMERROR)
-    {
-      diagnostic_set_info (diagnostic, gmsgid, ap, richloc,
-			   permissive_error_kind (global_dc));
-      diagnostic.option_index = permissive_error_option (global_dc);
-    }
-  else
-#endif
-    {
-      diagnostic_set_info (diagnostic, gmsgid, ap, richloc, kind);
-#if 0
-      if (kind == DK_WARNING || kind == DK_PEDWARN)
-	diagnostic.option_index = opt;
-#endif
-    }
-  return diagnostic_report_diagnostic (global_dc, diagnostic);
-}
-
-/* FIXME.  */
-
-void
-diagnostic_at (location_t loc, diagnostic_info *diagnostic,
-	       const char *gmsgid, ...)
-{
-  va_list ap;
-  va_start (ap, gmsgid);
-  rich_location richloc (line_table, loc);
-  diagnostic_at_rich_loc_va (&richloc, diagnostic, gmsgid, &ap);
-  va_end (ap);
-}
-
-
-/* Given UTF8_BUFFER, a non-NULL UTF-8-encoded buffer of JSON output
-   from a tool, in Firehose JSON format, emit the results through GCC's
-   diagnostic subsystem.  */
-
-static void
-handle_json (const char *utf8_buffer)
-{
-  /* Attempt to parse the buffer as UTF-8-encoded JSON.  */
-  char *err = NULL;
-  json::value *jv = json::parse_utf8_string (utf8_buffer, &err);
-  if (!jv)
-    {
-      gcc_assert (err);
-      error_at (UNKNOWN_LOCATION,
-		"unable to parse tool output as UTF-8 JSON: %s", err);
-      free (err);
-      return;
-    }
-
-  gcc_assert (err == NULL);
-
-  if (0)
-    {
-      jv->dump(stderr);
-      fprintf (stderr, "\n");
-    }
-
-  /* Attempt to parse the JSON values into Firehose objects.  */
-  firehose::analysis analysis;
-  analysis.from_json (jv, err);
-  if (err)
-    {
-      error_at (UNKNOWN_LOCATION, "error parsing JSON output: %qs", err);
-      free (err);
-      delete jv;
-      return;
-    }
-
-  gcc_assert (err == NULL);
-
-  /* Emit the results as GCC diagnostics.  */
-  int i;
-  firehose::result *result;
-  FOR_EACH_VEC_ELT (analysis.m_results, i, result)
-    {
-      switch (result->get_kind ())
-	{
-	case firehose::result::FIREHOSE_ISSUE:
-	  {
-	    firehose::issue *issue
-	      = static_cast <firehose::issue *> (result);
-	    // FIXME: generate "In function", perhaps based on blt_node ?
-	    // FIXME:  ^^^ better to get it from the JSON
-	    diagnostic_info diagnostic;
-	    diagnostic.kind = DK_ERROR;
-	    diagnostic.external_tool = analysis.m_metadata.m_generator.m_name;
-	    diagnostic.external_test_id = issue->m_testid;
-	    diagnostic_at (issue->m_location, &diagnostic, "%s",
-			   issue->m_message);
-	    print_any_trace (issue);
-	    // FIXME: identify metadata (which analyzer?)
-	  }
-	  break;
-
-	  // FIXME
-	default:
-	  gcc_unreachable ();
-	}
-    }
-
-  delete jv;
-}
-
-/* FIXME: taken from jit-playback.c.  */
-
-/* A subclass of auto_vec <char *> that frees all of its elements on
-   deletion.  */
-
-class auto_argvec : public auto_vec <char *>
-{
- public:
-  ~auto_argvec ();
-};
-
-/* auto_argvec's dtor, freeing all contained strings, automatically
-   chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
-
-auto_argvec::~auto_argvec ()
-{
-  int i;
-  char *str;
-  FOR_EACH_VEC_ELT (*this, i, str)
-    free (str);
-}
-
-/* FIXME.  */
-
-static void
-run_one_analyzer (const char *wrapper_path)
-{
-  auto_argvec argvec;
-#define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
-
-  ADD_ARG (wrapper_path);
-  ADD_ARG ("-B."); // FIXME
-  ADD_ARG ("-c");
-  ADD_ARG (main_input_filename);
-
-  /* pex argv arrays are NULL-terminated.  */
-  argvec.safe_push (NULL);
-
-  const char *errmsg;
-  int exit_status = 0;
-  int err = 0;
-  /* FIXME: avoid using known filename; read direct from stdout.  */
-  errmsg = pex_one (PEX_SEARCH | PEX_LAST, /* int flags, */
-		    wrapper_path,
-		    const_cast <char *const *> (argvec.address ()),
-		    "FIXME:ctxt_progname", /* const char *pname */
-		    "temp.json", /* const char *outname */
-		    NULL, /* const char *errname */
-		    &exit_status, /* int *status */
-		    &err); /* int *err*/
-  if (errmsg)
-    {
-      error_at (UNKNOWN_LOCATION, "error invoking tool: %s", errmsg);
-      return;
-    }
-  if (exit_status || err)
-    {
-      error_at (UNKNOWN_LOCATION,
-		"error invoking tool: exit_status: %i err: %i",
-		exit_status, err);
-      return;
-    }
-
-  // FIXME: use something other than a selftest for this!
-  char *utf8_buffer = selftest::read_file (SELFTEST_LOCATION,
-				      "temp.json"); // FIXME: filename
-  // FIXME: error-checking
-  handle_json (utf8_buffer);
-  free (utf8_buffer);
-
-  // FIXME: capture clang version in metadata
-}
-
-/* FIXME.  */
-
-void
-run_analyzers (const char *path)
-{
-  if (0)
-    inform (UNKNOWN_LOCATION, "run_analyzers (%qs)", path);
-
-  run_one_analyzer ("../../src/fakegcc_clang_analyzer.py");
-  run_one_analyzer ("../../src/fakegcc_cppcheck.py");
-}
-- 
1.8.5.3

