From dcc1b625c66619771a8d72cae64d7a58a141c4ca Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 28 Feb 2019 14:07:05 -0500
Subject: [PATCH 24/60] Add in-tree plugin: "analyzer"

This patch supplies the {Make|config}-plugin.in files for the analyzer,
along with the entrypoint to the plugin, and the driver logic for
converting "--analyzer" into the option to inject the plugin.

gcc/ChangeLog:
	* analyzer/Make-plugin.in: New file.
	* analyzer/analyzer-plugin.cc: New file.
	* analyzer/config-plugin.in: New file.
	* gcc.c (driver_handle_option): Handle "--analyzer" by injecting
	the plugin, if available.
---
 gcc/analyzer/Make-plugin.in     | 166 ++++++++++++++++++++++++++++++++++++++++
 gcc/analyzer/analyzer-plugin.cc |  63 +++++++++++++++
 gcc/analyzer/config-plugin.in   |  34 ++++++++
 gcc/gcc.c                       |  13 ++++
 4 files changed, 276 insertions(+)
 create mode 100644 gcc/analyzer/Make-plugin.in
 create mode 100644 gcc/analyzer/analyzer-plugin.cc
 create mode 100644 gcc/analyzer/config-plugin.in

diff --git a/gcc/analyzer/Make-plugin.in b/gcc/analyzer/Make-plugin.in
new file mode 100644
index 0000000..7ee6ac0
--- /dev/null
+++ b/gcc/analyzer/Make-plugin.in
@@ -0,0 +1,166 @@
+# Top level -*- makefile -*- fragment for analyzer
+#   Copyright (C) 2013-2019 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/>.
+
+# This file provides the plugin dependent support in the main Makefile.
+# Each plugin makefile fragment must provide the following targets:
+#
+# foo.all.cross, foo.start.encap, foo.rest.encap,
+# foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.mostlyclean, foo.clean, foo.distclean,
+# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
+#
+# where `foo' is the name of the plugin.
+#
+# It should also provide rules for:
+#
+# - making any compiler driver (eg: g++)
+# - the plugin proper (eg: analyzer_plugin.so)
+# - define the names for selecting the plugin in PLUGINS.
+
+#
+# Define the names for selecting analyzer in PLUGINS.
+# Note that it would be nice to move the dependency on g++
+# into the analyzer rule, but that needs a little bit of work
+# to do the right thing within all.cross.
+
+plugin_builddir = plugin
+
+ANALYZER_PLUGIN_SO = $(plugin_builddir)/analyzer_plugin.so
+
+analyzer: \
+	$(FULL_DRIVER_NAME) \
+	$(ANALYZER_PLUGIN_SO)
+
+# Tell GNU make to ignore these if they exist.
+.PHONY: analyzer
+
+# Files that are linked into analyzer plugin
+
+analyzer_OBJS = \
+	analyzer/analyzer.o \
+	analyzer/analyzer-logging.o \
+	analyzer/analyzer-pass.o \
+	analyzer/analyzer-plugin.o \
+	analyzer/analyzer-selftests.o \
+	analyzer/constraint-manager.o \
+	analyzer/digraph.o \
+	analyzer/graphviz.o \
+	analyzer/engine.o \
+	analyzer/pending-diagnostic.o \
+	analyzer/region-model.o \
+	analyzer/sm.o \
+	analyzer/sm-file.o \
+	analyzer/sm-malloc.o \
+	analyzer/sm-pattern-test.o \
+	analyzer/sm-sensitive.o \
+	analyzer/sm-taint.o \
+	analyzer/supergraph.o \
+	analyzer/tristate.o \
+
+# Use strict warnings for this plugin.
+analyzer-warn = $(STRICT_WARN)
+
+#
+# Build hooks:
+
+analyzer.all.cross:
+analyzer.start.encap:
+analyzer.rest.encap:
+
+$(plugin_builddir):
+	mkdir $@
+
+$(ANALYZER_PLUGIN_SO): $(analyzer_OBJS) $(plugin_builddir)
+	$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) \
+	  -o $@ \
+	  -shared \
+	  $(analyzer_OBJS) \
+	-lpthread
+
+# If the analyzer is enabled, require the selftests to be run for it
+# at each stage of the build:
+selftest-analyzer: s-selftest-analyzer
+
+ANALYZER_SELFTEST_FLAGS = -xc $(SELFTEST_FLAGS) --analyzer
+ANALYZER_SELFTEST_DEPS = cc1$(exeext) $(SELFTEST_DEPS) $(ANALYZER_PLUGIN_SO)
+
+# Run the analyzer selftests:
+s-selftest-analyzer: $(ANALYZER_SELFTEST_DEPS)
+	$(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS)
+	$(STAMP) $@
+
+# Convenience methods for running analyzer selftests under gdb:
+.PHONY: selftest-analyzer-gdb
+selftest-analyzer-gdb: $(ANALYZER_SELFTEST_DEPS)
+	$(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS) \
+	  -wrapper gdb,--args
+
+# Convenience methods for running analyzer selftests under valgrind:
+.PHONY: selftest-analyzer-valgrind
+selftest-analyzer-valgrind: $(ANALYZER_SELFTEST_DEPS)
+	$(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS) \
+	  -wrapper valgrind,--leak-check=full
+
+# Documentation build hooks.
+analyzer.info:
+analyzer.man:
+
+# Testing hooks:
+lang_checks += check-analyzer
+
+#
+# Install hooks:
+analyzer.install-common:
+
+analyzer.install-man:
+
+analyzer.install-plugin:
+
+analyzer.uninstall:
+
+#
+# Clean hooks:
+# A lot of the ancillary files are deleted by the main makefile.
+# We just have to delete files specific to us.
+
+analyzer.mostlyclean:
+
+analyzer.clean:
+
+analyzer.distclean:
+
+analyzer.maintainer-clean:
+
+#
+# Stage hooks:
+# The main makefile has already created stage?/analyzer.
+
+analyzer.stage1: stage1-start
+	-mv analyzer/*$(objext) stage1/analyzer
+analyzer.stage2: stage2-start
+	-mv analyzer/*$(objext) stage2/analyzer
+analyzer.stage3: stage3-start
+	-mv analyzer/*$(objext) stage3/analyzer
+analyzer.stage4: stage4-start
+	-mv analyzer/*$(objext) stage4/analyzer
+analyzer.stageprofile: stageprofile-start
+	-mv analyzer/*$(objext) stageprofile/analyzer
+analyzer.stagefeedback: stagefeedback-start
+	-mv analyzer/*$(objext) stagefeedback/analyzer
diff --git a/gcc/analyzer/analyzer-plugin.cc b/gcc/analyzer/analyzer-plugin.cc
new file mode 100644
index 0000000..1e7c56e
--- /dev/null
+++ b/gcc/analyzer/analyzer-plugin.cc
@@ -0,0 +1,63 @@
+/* Top-level interface to the analyzer, as a GCC plugin.
+   Copyright (C) 2019 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 "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analyzer-selftests.h"
+
+int plugin_is_GPL_compatible;
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Callback for running the analyzer's selftests.  */
+
+static void
+analyzer_selftests_cb (void */*gcc_data*/, void */*user_data*/)
+{
+  run_analyzer_selftests ();
+}
+
+} /* end of namespace selftest.  */
+
+#endif /* #if CHECKING_P */
+
+/* Entrypoint to the pass.  */
+
+int
+plugin_init (struct plugin_name_args *plugin_info ATTRIBUTE_UNUSED,
+	     struct plugin_gcc_version */*version*/)
+{
+  /* Register our selftests.  */
+#if CHECKING_P
+  register_callback (plugin_info->base_name,
+		     PLUGIN_RUN_SELFTESTS,
+		     selftest::analyzer_selftests_cb, NULL);
+#endif /* #if CHECKING_P */
+
+  /* Register our pass.  */
+  register_analyzer_pass ();
+
+  return 0;
+}
diff --git a/gcc/analyzer/config-plugin.in b/gcc/analyzer/config-plugin.in
new file mode 100644
index 0000000..283e8e9
--- /dev/null
+++ b/gcc/analyzer/config-plugin.in
@@ -0,0 +1,34 @@
+# Top level configure fragment for static analyzer
+#   Copyright (C) 2013-2015 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/>.
+
+# Configure looks for the existence of this file to auto-config each plugin.
+# We define several parameters used by configure:
+#
+# plugin	- name of plugin as it would appear in $(PLUGINS)
+# compilers	- value to add to $(COMPILERS)
+
+plugin="analyzer"
+
+compilers=""
+
+target_libs=""
+
+gtfiles=""
+
+build_by_default="no"
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c45a1df..733f080 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4290,6 +4290,19 @@ driver_handle_option (struct gcc_options *opts,
       handle_foffload_option (arg);
       break;
 
+    case OPT__analyzer:
+      {
+	validated = true;
+#ifdef ENABLE_ANALYZER
+	save_switch ("-fplugin=analyzer_plugin", 0, NULL, validated, true);
+#else
+	sorry ("%qs was not enabled in this build of GCC"
+	       " (missing configure-time option %qs)",
+	       "--analyzer", "--enable-plugins=analyzer");
+#endif
+      }
+      break;
+
     default:
       /* Various driver options need no special processing at this
 	 point, having been handled in a prescan above or being
-- 
1.8.5.3

