On Thu, 2015-06-11 at 00:18 +0200, Jakub Jelinek wrote:
> On Wed, Jun 10, 2015 at 01:16:20PM -0400, David Malcolm wrote:
> > On Wed, 2015-06-10 at 17:34 +0200, Jakub Jelinek wrote:
> > > On Wed, Jun 10, 2015 at 11:24:41AM -0400, David Malcolm wrote:
> > > > I picked the Google Test framework:
> > > >   http://code.google.com/p/googletest/
> > > 
> > > I must say I'm not very excited about using this, it won't integrate
> > > very well with dejagnu
> > 
> > Why is that a goal?  I've been using DejaGnu's unittesting API for
> > testing the jit, and it is... suboptimal, to put it mildly.
> 
> Primarily consistency, people want consistent output of the testresults from
> the compiler, not to have to pass one set of magic options to dejagnu to do
> something and then mirror them to something completely different to make
> gtest happy.  Similarly, there are all kinds of scripts that analyze gcc
> testresults, having to parse a completely different format because a tiny
> percentage of tests runs something different isn't a very good idea.
> Plus, by using googletest, you add another build requirement, we already
> have quite a lot of them.

Thanks.

I've rewritten the patches so that instead of building a "frontend", it
instead builds a plugin: unittests_plugin.so, which runs the testsuite
within a PLUGIN_FINISH callback.  Doing so required a fair amount of
time in gdb dealing with state issues.

The plugin is referenced from a new testcase:
  c-c++-common/torture/run-unittests-plugin.c
which is simply:
 /* { dg-options "-fplugin=../../unittests_plugin.so" } */

leading to a unittest suite that's run repeatedly for both cc1 and
cc1plus, for all of the various torturing options.  

Presumably something similar could be added for the other frontends (I
tried for gfortran, but couldn't seem to get it to add the option to the
torture test, so the plugin didn't run).

> > > whether talking about results (will it provide
> > > some *.log/*.sum file with FAIL/XFAIL/PASS/XPASS etc. lines?),
> > 
> > It doesn't have an output formatter for the DejaGnu format, but I guess
> > I could write one.  The gtest standard output format is IMHO superior to
> > DejaGnu's since it tells you start-of-test/end-of-test on separate
> > lines, so you can see which test killed things in the event of total
> 
> I find the dejagnu log files quite readable, unlike the gtest stuff, so
> supposedly this is quite subjective.

I wrote a custom formatter for the output (class deja_gnu_printer within
unittests-plugin.c) which generates lines like this on stderr:

PASS: ggc_test.tree_marking
PASS: ggc_test.custom_struct
PASS: ggc_test.finalization
PASS: ggc_test.inheritance
PASS: ggc_test.chain_next

These get detected on stderr by some new logic inside
testsuite/lib/prune.exp, which prefixes them with
[testname-for-summary], and emitting them at the Tcl level, so they end
up in the .log and .sum files as lines like this:

PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   ggc_test.tree_marking
PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   ggc_test.custom_struct
PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   ggc_test.finalization
PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   ggc_test.inheritance
PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   ggc_test.chain_next

(if doing it for all testcase output is an issue, perhaps this prune.exp
logic could be made conditional, so that we only do it for testcases
using the plugin, or that contain a dg command)

> > > etc.
> > > E.g. for asan.exp testing, I just wrote a gtest emulation using
> > > dejagnu, see testsuite/g++.dg/asan/dejagnu-gtest.h and
> > > testsuite/lib/asan-dg.exp
> > 
> > ...which doesn't have things like EXPECT_STREQ, or custom comparators,
> > doesn't appear to support fixtures, type-parameterized tests,
> > value-parameterized tests, etc, my point being that a unit-testing
> > framework is a non-trivial amount of code that could do useful things
> > for us.
> 
> The question is why you really need it, or if it is more than a few lines of
> macros.

I'm not sure.

gtest is available in collapsed form as a pair of .cc and .h files; in
my latest version, as an experiment, I embedded a copy of gtest-1.7 in
the source tree, as:
  gcc/unittests/gtest-all.c
  gcc/unittests/gtest/gtest.h
and they're built as part of the plugin.

This works, and means there's no extra external dependency, and I was
able to bootstrap with this.  I ran into an issue with "make check": the
plugin is linked against the previous stage's libstdc++, but "make
check" doesn't seem to set up LD_LIBRARY_PATH to point at a fresh
libstdc++ and uses the system copy, leading to
cc1: error: cannot load plugin ../../unittests_plugin.so
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required
by ../../unittests_plugin.so)

on this Fedora 20 box.  Manually setting LD_LIBRARY_PATH to point at the
built libstdc++ fixes it.

My higher-level goals here are:
  * to get test coverage of things like gengtype/ggc, our data
structures, etc.
  * to have an easy place for people to add unit-test coverage, without
needing to write a new plugin each time

It's clearly possible to write a family of macros that emulate the gtest
API.  However, if we also want e.g. fixture classes, I wonder at what
point it would be simpler to use gtest itself, rather than a
reimplementation of it (or some other framework).

Perhaps it would be simplest to have a minimal reimplementation of gtest
that mimics the API (although perhaps without the use of CamelCase?).

FWIW, I attempted to use the "Catch" unittest header
(https://github.com/philsquared/Catch) but it relies on exceptions, so
presumably that's a no-no.

> > > but that was mainly meant for cases where
> > > many routines are expected to crash the process.
> > 
> > FWIW, if I'm reading testsuite/g++.dg/asan/dejagnu-gtest.h and
> > testsuite/lib/asan-dg.exp correctly, it looks like you're spawning the
> > tool once per EXPECT_DEATH instance in the testsuite.  That seems
> > suboptimal, gtest uses fork without exec
> > to do it all directly at the point of the test without lots of extra
> > work, where the parent verifies the death of the child.
> 
> That was a design choice, makes it much easier to debug the individual
> tests, especially for asan where for gtest there are just way too many forks
> and way too many (expected) crashes.
> For the unittests, I see no problem running numerous tests from within one
> process, it can emit multiple PASS/FAIL/XFAIL etc.

(nods).

I'm attaching a patch; this is relative to the previous patch kit (since
this is more for discussion, as this clearly isn't ready yet), and omits
the embedded copies of gtest.

Thoughts?

Dave
commit f843bf0ed5764a36b0c0188c6d367b3164dfd34c
Author: David Malcolm <dmalc...@redhat.com>
Date:   Wed Jun 17 15:27:53 2015 -0400

    Rewrite unittests to be a plugin

diff --git a/gcc/testsuite/c-c++-common/torture/run-unittests-plugin.c b/gcc/testsuite/c-c++-common/torture/run-unittests-plugin.c
new file mode 100644
index 0000000..297d78b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/run-unittests-plugin.c
@@ -0,0 +1,2 @@
+/* This source file leads to the unittests_plugin being loaded and run.
+   { dg-options "-fplugin=../../unittests_plugin.so" } */
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 8e4c203..c5d24be 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -68,6 +68,48 @@ proc prune_gcc_output { text } {
     # Ignore harmless warnings from Xcode 4.0.
     regsub -all "(^|\n)\[^\n\]*ld: warning: could not create compact unwind for\[^\n\]*" $text "" text
 
+    # Process any DejaGnu output from the test, and convert into results at
+    # this level, prefixing with the testcase.
+    # For example, given the line
+    #   PASS: vec_test.quick_push
+    # from the test, we want to call "pass", giving a line like this in
+    # our .log/.sum, depending on [testname-for-summary]:
+    #   PASS: c-c++-common/torture/run-unittests-plugin.c   -O0   vec_test.quick_push
+    verbose "Would handle: $text\n"
+    # TODO: generalize for other kinds of test result:
+    foreach status_pair { {"PASS" pass} {"FAIL" fail} } {
+	set kind [lindex $status_pair 0]
+	set handler [lindex $status_pair 1]
+	#verbose "kind: $kind   handler: $handler"
+	set pattern "^$kind: (.*?)$"
+	#verbose "pattern: $pattern"
+	set matches [regexp -all -inline -lineanchor $pattern $text]
+	#verbose "matches: $matches"
+	foreach {matched_line detail} $matches {
+	    #verbose "matched_line: $matched_line"
+	    #verbose "detail: $detail"
+	    set testname [testname-for-summary]
+
+	    # Call the handler ("pass"/"fail" etc) to convert to a message
+	    # at this level, prefixed with [testname-for-summary]:
+	    $handler "$testname $detail"
+
+	    # Prune $matched_line from $text (or, at least, the first
+	    # instance of it).
+	    # Is there a less clunky way to do this?  (regsub would require
+	    # escaping any regex special characters within $matched_line).
+	    # Locate first instance of matched_line:
+	    set idx [string first $matched_line $text]
+	    # Get length, adding one for the trailing newline char:
+	    set linelen [expr [string length $matched_line] + 1]
+	    # Cut it out from the middle of $text:
+	    set textlen [string length $text]
+	    set before [string range $text 0 [expr $idx - 1] ]
+	    set after_ [string range $text [expr $idx + $linelen] $textlen]
+	    set text $before$after_
+	}
+    }
+
     #send_user "After:$text\n"
 
     return $text
diff --git a/gcc/unittests/Make-lang.in b/gcc/unittests/Make-lang.in
index 50d6e4f..26a0cb9 100644
--- a/gcc/unittests/Make-lang.in
+++ b/gcc/unittests/Make-lang.in
@@ -40,43 +40,33 @@
 # into the unittests rule, but that needs a little bit of work
 # to do the right thing within all.cross.
 
-LIBGCCUNITTESTS_LINKER_NAME = libgccunittests.so
-LIBGCCUNITTESTS_VERSION_NUM = 0
-LIBGCCUNITTESTS_MINOR_NUM = 0
-LIBGCCUNITTESTS_RELEASE_NUM = 1
-LIBGCCUNITTESTS_SONAME = $(LIBGCCUNITTESTS_LINKER_NAME).$(LIBGCCUNITTESTS_VERSION_NUM)
-LIBGCCUNITTESTS_FILENAME = \
-  $(LIBGCCUNITTESTS_SONAME).$(LIBGCCUNITTESTS_MINOR_NUM).$(LIBGCCUNITTESTS_RELEASE_NUM)
+UNITTESTS_PLUGIN_SO = unittests_plugin.so
 
-LIBGCCUNITTESTS_LINKER_NAME_SYMLINK = $(LIBGCCUNITTESTS_LINKER_NAME)
-LIBGCCUNITTESTS_SONAME_SYMLINK = $(LIBGCCUNITTESTS_SONAME)
-
-TESTPROGRAMS = unittests.exe
-
-RUN_TESTPROGRAMS = run-unittests.exe
-
-unittests: $(LIBGCCUNITTESTS_FILENAME) \
-	$(LIBGCCUNITTESTS_SYMLINK) \
-	$(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK) \
+unittests: \
 	$(FULL_DRIVER_NAME) \
-	$(TESTPROGRAMS) \
-	$(RUN_TESTPROGRAMS)
+	$(UNITTESTS_PLUGIN_SO)
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: unittests $(RUN_TESTPROGRAMS)
+.PHONY: unittests
 
-# "Frontend" objects, which go into libgccunittests.so
-unittests_OBJS = attribs.o \
-	unittests/unittests-frontend.o
+# gengtype integration
+gt-unittests-test-ggc.h: ./gengtype $(srcdir)/unittests/test-ggc.c
+	./gengtype \
+	  --plugin $@ \
+	  --read-state gtype.state \
+	  $(srcdir)/unittests/test-ggc.c
 
 # Build various files against gtest
 
 # Files that are linked into unittests.exe
-UNITTESTS_EXE_OBJS = \
+
+UNITTESTS_PLUGIN_SO_OBJS = \
+	gtest-all.o \
 	test-bitmap.o \
 	test-cfg.o \
 	test-folding.o \
 	test-functions.o \
+	test-ggc.o \
 	test-gimple.o \
 	test-hash-map.o \
 	test-hash-set.o \
@@ -85,11 +75,11 @@ UNITTESTS_EXE_OBJS = \
 	test-tree.o \
 	test-vec.o \
 	test-wide-int.o \
-	unittests-main.o
+	unittests-plugin.o
 
 # Files to be built against gtest
-# test-ggc.o has to be linked in to libgccunittests.so
-OBJS_BUILT_AGAINST_GTEST = $(UNITTESTS_EXE_OBJS) test-ggc.o
+# FIXME: do we still need this?
+OBJS_BUILT_AGAINST_GTEST = $(UNITTESTS_PLUGIN_SO_OBJS)
 
 # All objects (for the main Makefile.in's dependency tracking)
 #extra_OBJS += $(OBJS_BUILT_AGAINST_GTEST)
@@ -97,23 +87,6 @@ OBJS_BUILT_AGAINST_GTEST = $(UNITTESTS_EXE_OBJS) test-ggc.o
 # Use strict warnings for this front end.
 unittests-warn = $(STRICT_WARN)
 
-# We avoid using $(BACKEND) from Makefile.in in order to avoid pulling
-# in main.o
-$(LIBGCCUNITTESTS_FILENAME): $(unittests_OBJS) \
-	libbackend.a libcommon-target.a libcommon.a \
-	$(CPPLIB) $(LIBDECNUMBER) \
-	$(LIBDEPS) test-ggc.o
-	+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ -shared \
-	     $(unittests_OBJS) libbackend.a libcommon-target.a libcommon.a \
-	     $(CPPLIB) $(LIBDECNUMBER) $(LIBS) $(BACKENDLIBS) test-ggc.o \
-	     -Wl,-soname,$(LIBGCCUNITTESTS_SONAME)
-
-$(LIBGCCUNITTESTS_SONAME_SYMLINK): $(LIBGCCUNITTESTS_FILENAME)
-	ln -sf $(LIBGCCUNITTESTS_FILENAME) $(LIBGCCUNITTESTS_SONAME_SYMLINK)
-
-$(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK): $(LIBGCCUNITTESTS_SONAME_SYMLINK)
-	ln -sf $(LIBGCCUNITTESTS_SONAME_SYMLINK) $(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK)
-
 #
 # Build hooks:
 
@@ -121,24 +94,31 @@ unittests.all.cross:
 unittests.start.encap:
 unittests.rest.encap:
 
-$(OBJS_BUILT_AGAINST_GTEST): %.o: $(srcdir)/unittests/%.c
+# Needed by gtest-all.c:
+#   -Wno-missing-field-initializers
+#   -Wno-conversion-null
+#   -Wno-suggest-attribute=format
+# Needed by various test-*.c:
+#   -Wno-sign-compare
+
+$(OBJS_BUILT_AGAINST_GTEST): %.o: $(srcdir)/unittests/%.c \
+	  gt-unittests-test-ggc.h
 	$(COMPILER) \
-	  $(shell gtest-config --cppflags --cxxflags) \
 	  $(INCLUDES) \
 	  $(ALL_COMPILERFLAGS) \
-	  -c -o $@ $<
-
-unittests.exe: $(UNITTESTS_EXE_OBJS) $(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK)
+	  -c -o $@ $< \
+	-fPIC \
+	-Wno-missing-field-initializers \
+	-Wno-conversion-null \
+	-Wno-suggest-attribute=format \
+	-Wno-sign-compare
+
+$(UNITTESTS_PLUGIN_SO): $(UNITTESTS_PLUGIN_SO_OBJS)
 	$(LINKER) \
-	  $(shell gtest-config --ldflags --libs) \
-	  $(ALL_LINKERFLAGS) \
-	  -L. -lgccunittests \
 	  -o $@ \
-	  $(UNITTESTS_EXE_OBJS) \
-	  $(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK)
-
-run-unittests.exe: unittests.exe
-	LD_LIBRARY_PATH=. ./unittests.exe
+	  -shared \
+	  $(UNITTESTS_PLUGIN_SO_OBJS) \
+	-lpthread
 
 # Documentation build hooks.
 unittests.info:
@@ -149,19 +129,7 @@ lang_checks += check-unittests
 
 #
 # Install hooks:
-unittests.install-common: installdirs
-	$(INSTALL_PROGRAM) $(LIBGCCUNITTESTS_FILENAME) \
-	  $(DESTDIR)/$(libdir)/$(LIBGCCUNITTESTS_FILENAME)
-	ln -sf \
-	  $(LIBGCCUNITTESTS_FILENAME) \
-	  $(DESTDIR)/$(libdir)/$(LIBGCCUNITTESTS_SONAME_SYMLINK)
-	ln -sf \
-	  $(LIBGCCUNITTESTS_SONAME_SYMLINK)\
-	  $(DESTDIR)/$(libdir)/$(LIBGCCUNITTESTS_LINKER_NAME_SYMLINK)
-	$(INSTALL_PROGRAM) $(srcdir)/unittests/libgccunittests.h \
-	  $(DESTDIR)/$(includedir)/libgccunittests.h
-	$(INSTALL_PROGRAM) $(srcdir)/unittests/libgccunittests++.h \
-	  $(DESTDIR)/$(includedir)/libgccunittests++.h
+unittests.install-common:
 
 unittests.install-man:
 
diff --git a/gcc/unittests/config-lang.in b/gcc/unittests/config-lang.in
index 1e0bfd7..0d24609 100644
--- a/gcc/unittests/config-lang.in
+++ b/gcc/unittests/config-lang.in
@@ -29,6 +29,6 @@ compilers="unittest-suite"
 
 target_libs=""
 
-gtfiles="\$(srcdir)/unittests/unittests-frontend.c \$(srcdir)/unittests/test-ggc.c"
+gtfiles=""
 
 build_by_default="no"
diff --git a/gcc/unittests/test-ggc.c b/gcc/unittests/test-ggc.c
index 197b4b5..4418a21 100644
--- a/gcc/unittests/test-ggc.c
+++ b/gcc/unittests/test-ggc.c
@@ -125,6 +125,12 @@ TEST_F (ggc_test, finalization)
 
 static GTY((deletable)) test_struct *test_of_deletable;
 
+/* FIXME: we can't do this test via a plugin as it stands.
+   The list of deletable roots is fixed by the main gengtype
+   run; there isn't yet a way to add extra
+   deletable roots (PLUGIN_REGISTER_GGC_ROOTS is for regular
+   roots).  */
+#if 0
 TEST_F (ggc_test, deletable_global)
 {
   test_of_deletable = ggc_cleared_alloc <test_struct> ();
@@ -134,6 +140,7 @@ TEST_F (ggc_test, deletable_global)
 
   EXPECT_EQ (NULL, test_of_deletable);
 }
+#endif
 
 /* Verify that gengtype etc can cope with inheritance.  */
 
diff --git a/gcc/unittests/unittests-plugin.c b/gcc/unittests/unittests-plugin.c
new file mode 100644
index 0000000..83dc4f3
--- /dev/null
+++ b/gcc/unittests/unittests-plugin.c
@@ -0,0 +1,182 @@
+/* Plugin that process internal tests for sreal.  */
+#include "config.h"
+#include "gtest/gtest.h"
+#include "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "toplev.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "context.h"
+#include "diagnostic.h"
+#include "bitmap.h"
+
+int plugin_is_GPL_compatible;
+
+/* Print test output in DejaGnu form.  */
+class deja_gnu_printer : public ::testing::EmptyTestEventListener
+{
+ public:
+  deja_gnu_printer (FILE *outfile, int verbose)
+    : m_outfile (outfile),
+      m_verbose (verbose)
+  {}
+
+ private:
+  virtual void
+  OnTestCaseStart(const ::testing::TestCase& test_case)
+  {
+    if (m_verbose)
+      fprintf (m_outfile, "NOTE: %s: case starting\n",
+	       test_case.name ());
+  }
+
+  /* Vfunc called before a test starts.  */
+  virtual void
+  OnTestStart (const ::testing::TestInfo& test_info)
+  {
+    if (m_verbose)
+      fprintf (m_outfile,
+	       "NOTE: %s.%s: test starting\n",
+	       test_info.test_case_name (), test_info.name ());
+    m_per_test_fails = 0;
+  }
+
+  /* Vfunc called after a failed assertion or a SUCCEED() invocation.  */
+  virtual void
+  OnTestPartResult (const ::testing::TestPartResult& test_part_result)
+  {
+    fprintf (m_outfile,
+	     "%s: %s:%d: %s\n",
+	     test_part_result.failed () ? "FAIL" : "PASS",
+	     test_part_result.file_name (),
+	     test_part_result.line_number (),
+	     test_part_result.summary ());
+    if (test_part_result.failed ())
+      m_per_test_fails++;
+  }
+
+  /* Vfunc called after a test ends.  */
+  virtual void
+  OnTestEnd (const ::testing::TestInfo& test_info)
+  {
+    if (m_verbose)
+      fprintf (m_outfile,
+	       "NOTE: %s.%s: test ending: %i failure(s)\n",
+	       test_info.test_case_name (), test_info.name (),
+	       m_per_test_fails);
+    fprintf (m_outfile,
+	     "%s: %s.%s\n",
+	     m_per_test_fails > 0 ? "FAIL" : "PASS",
+	     test_info.test_case_name (), test_info.name ());
+  }
+
+  virtual void
+  OnTestCaseEnd (const ::testing::TestCase& test_case)
+  {
+    if (m_verbose)
+      fprintf (m_outfile, "NOTE: %s: case ending\n",
+	       test_case.name ());
+  }
+
+ private:
+    FILE *m_outfile;
+    int m_verbose;
+    int m_per_test_fails;
+};
+
+/* Get rid of the default gtest result printer, and instead use LISTENER,
+   taking ownership of the ptr.  */
+
+static void
+replace_default_gtest_result_printer (::testing::TestEventListener *listener)
+{
+  ::testing::TestEventListeners& listeners =
+    ::testing::UnitTest::GetInstance()->listeners();
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(listener);
+}
+
+/* Callback handler for the PLUGIN_FINISH event.
+   At this point, all GCC subsystems should be initialized and
+   "warmed up"; this is where we run our unit tests.  */
+
+static void
+on_finish (void */*gcc_data*/, void */*user_data*/)
+{
+  /* FIXME: get these from the passed-in args to the plugin?
+     would we need to store them?  */
+  int argc = 0;
+  char **argv = NULL;
+  ::testing::InitGoogleTest (&argc, argv);
+
+  /* Use our custom result-printer.  */
+  replace_default_gtest_result_printer (new deja_gnu_printer (stderr, 0));
+
+  /* Reset some state.  */
+  input_location = UNKNOWN_LOCATION;
+  bitmap_obstack_initialize (NULL);
+
+  /* Run the tests.  */
+  int result = RUN_ALL_TESTS();
+
+  /* Ensure that a test failure leads to the process exiting with
+     a non-zero exit code.  */
+  if (result)
+    error ("at least one test failure occurred");
+
+  /* Cleanup.  */
+  bitmap_obstack_release (NULL);
+}
+
+/* Declared in "gt-unittests-test-ggc.h". */
+extern const struct ggc_root_tab gt_ggc_r_gt_unittests_test_ggc_h[];
+#if 0
+extern const struct ggc_root_tab gt_ggc_rd_gt_unittests_test_ggc_h[];
+#endif
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+	     struct plugin_gcc_version */*version*/)
+{
+  if (0)
+    fprintf (stderr, "got here\n");
+
+  register_callback (plugin_info->base_name,
+		     PLUGIN_REGISTER_GGC_ROOTS,
+		     NULL,
+		     const_cast <ggc_root_tab *> (
+		       gt_ggc_r_gt_unittests_test_ggc_h));
+  /* FIXME: we'd use this for test-ggc.c's test_of_deletable.
+     However we'd need to register it as a different kind of roottab;
+     doing it with PLUGIN_REGISTER_GGC_ROOTS leads to a segfault on
+     collection due to the NULL cb.
+     It looks like we need another hook; gt_ggc_deletable_rtab is
+     currently not expandable.  */
+#if 0
+  register_callback (plugin_info->base_name,
+		     PLUGIN_REGISTER_GGC_ROOTS,
+		     NULL,
+		     const_cast <ggc_root_tab *> (
+		       gt_ggc_rd_gt_unittests_test_ggc_h));
+#endif
+  register_callback (plugin_info->base_name,
+		     PLUGIN_FINISH,
+		     on_finish,
+		     NULL); /* void *user_data */
+
+  return 0;
+}

Reply via email to