Hi,

This patch solves some lacks with the PLUGIN_FINISH_TYPE event
triggering. For now, both C and C++ parser won't trigger it for enums or
for typedef. In C++, when a struct, class or union declaration is parsed
(without definition), the given event data is an error mark instead of
the parsed type node.

Bootstrapped and tested on x86_64.

Romain Geissler

gcc/
2011-09-12  Romain Geissler  <romain.geiss...@gmail.com>

        * c-decl.c (grokdeclarator): Trigger PLUGIN_FINISH_TYPE for typedefs.
        * c-parser.c (cp_parser_type_specifier: Trigger PLUGIN_FINISH_TYPE for
        enums.


gcc/cp/
2011-09-12  Romain Geissler  <romain.geiss...@gmail.com>

        * decl.c (grokdeclarator): Trigger PLUGIN_FINISH_TYPE for typedefs.
        * parser.c (cp_parser_type_specifier: Trigger PLUGIN_FINISH_TYPE for
        enums.
        Correctly trigger PLUGIN_FINISH_TYPE for unions, structs or classes.


gcc/testsuite/
2011-09-12  Romain Geissler  <romain.geiss...@gmail.com>

        * gcc.dg/plugin/dumb-plugin-test-1.c: New File.
        * gcc.dg/plugin/dumb_plugin.c: Likewise.
        * gcc.dg/plugin/plugin.exp: Add above testcase.
        * g++.dg/plugin/dumb-plugin-test-1.C: New tests.
        * g++.dg/plugin/dumb_plugin.c (handle_type): Renamed from handle_struct.
        Add warnings for all kind of types.
Index: gcc/testsuite/gcc.dg/plugin/dumb-plugin-test-1.c
===================================================================
--- gcc/testsuite/gcc.dg/plugin/dumb-plugin-test-1.c    (revision 0)
+++ gcc/testsuite/gcc.dg/plugin/dumb-plugin-test-1.c    (revision 0)
@@ -0,0 +1,56 @@
+// Test case for the dumb plugin.
+// { dg-do compile }
+// { dg-options "-O -fplugin-arg-dumb_plugin-ref-pass-name=ccp 
-fplugin-arg-dumb_plugin-ref-pass-instance-num=1" }
+
+struct my_struct {
+  int a_;
+  char b_;
+}; // { dg-warning "Process struct my_struct" }
+
+struct Bar; // { dg-warning "Process struct Bar" }
+struct Bar; // { dg-warning "Process struct Bar" }
+struct Bar {
+  int c_;
+  int d_;
+  struct my_struct e_; // { dg-warning "Process struct my_struct" }
+}; // { dg-warning "Process struct Bar" }
+
+union my_union; // { dg-warning "Process union my_union" }
+union my_union; // { dg-warning "Process union my_union" }
+union my_union {
+  int g_;
+  char h_;
+}; // { dg-warning "Process union my_union" }
+
+enum my_enum; // { dg-warning "Process enum my_enum" }
+enum my_enum; // { dg-warning "Process enum my_enum" }
+enum my_enum {
+  i_,
+  j_
+}; // { dg-warning "Process enum my_enum" }
+
+typedef int* my_typedef; // { dg-warning "Process typedef my_typedef" }
+
+int g = 2;
+
+int func()
+{
+  struct Bar *bar1, bar2; // { dg-warning "Process struct Bar" }
+  int x = x;
+  static int y = 6;
+  float *f;
+  struct Bar bar_array[5];  // { dg-warning "Process struct Bar" }
+  char n;
+  int overflow;
+
+  *f = *f;
+  bar1->c_ = bar1->c_;
+  bar2.d_ = bar2.d_;
+  bar_array[3].e_ = bar_array[3].e_;
+  bar_array[x+g].d_ = bar_array[x+g].d_;
+  y = x;
+  x = y;
+} // { dg-warning "Before genericizing function" }
+
+// { dg-warning "Analyze function" "" { target *-*-* } 53 }
+// {  dg-warning "End of compilation unit" "" { target *-*-* } 53 }
Index: gcc/testsuite/gcc.dg/plugin/dumb_plugin.c
===================================================================
--- gcc/testsuite/gcc.dg/plugin/dumb_plugin.c   (revision 0)
+++ gcc/testsuite/gcc.dg/plugin/dumb_plugin.c   (revision 0)
@@ -0,0 +1,160 @@
+/* A trivial (dumb) plugin example that shows how to use the GCC plugin
+   mechanism.  */
+
+#include "gcc-plugin.h"
+#include <stdlib.h>
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "toplev.h"
+#include "diagnostic.h"
+
+int plugin_is_GPL_compatible;
+
+/* Callback function to invoke after GCC finishes parsing a type.  */
+
+void
+handle_type (void *event_data, void *data)
+{
+  tree type = (tree) event_data;
+
+  switch (TREE_CODE (type)) {
+    case RECORD_TYPE:
+      warning (0, G_("Process struct %s"),
+             IDENTIFIER_POINTER (TYPE_NAME (type)));
+      break;
+    case UNION_TYPE:
+      warning (0, G_("Process union %s"),
+             IDENTIFIER_POINTER (TYPE_NAME (type)));
+      break;
+    case ENUMERAL_TYPE:
+      warning (0, G_("Process enum %s"),
+             IDENTIFIER_POINTER (TYPE_NAME (type)));
+      break;
+    case TYPE_DECL:
+      warning (0, G_("Process typedef %s"),
+             IDENTIFIER_POINTER (DECL_NAME (type)));
+      break;
+    default:
+      error (G_("Unexpected tree node in PLUGIN_FINISH_TYPE %s\n"), 
tree_code_name [TREE_CODE (type)]);
+  }
+}
+
+/* Callback function to invoke before the function body is genericized.  */ 
+
+void
+handle_pre_generic (void *event_data, void *data)
+{
+  tree fndecl = (tree) event_data;
+  warning (0, G_("Before genericizing function %s"),
+           IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+}
+
+/* Callback function to invoke after GCC finishes the compilation unit.  */
+
+void
+handle_end_of_compilation_unit (void *event_data, void *data)
+{
+  warning (0, G_("End of compilation unit"));
+}
+
+
+static unsigned int
+execute_dumb_plugin_example (void)
+{
+  warning (0, G_("Analyze function %s"),
+           IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+  return 0;
+}
+
+static bool
+gate_dumb_plugin_example (void)
+{
+  return true;
+}
+
+static struct gimple_opt_pass pass_dumb_plugin_example =
+{
+  {
+    GIMPLE_PASS,
+    "dumb_plugin_example",                /* name */
+    gate_dumb_plugin_example,             /* gate */
+    execute_dumb_plugin_example,          /* execute */
+    NULL,                                 /* sub */
+    NULL,                                 /* next */
+    0,                                    /* static_pass_number */
+    TV_NONE,                              /* tv_id */
+    PROP_cfg,                             /* properties_required */
+    0,                                    /* properties_provided */
+    0,                                    /* properties_destroyed */
+    0,                                    /* todo_flags_start */
+    TODO_dump_func                        /* todo_flags_finish */
+  }
+};
+
+/* Initialization function that GCC calls. This plugin takes an argument
+   that specifies the name of the reference pass and an instance number,
+   both of which determine where the plugin pass should be inserted.  */
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+             struct plugin_gcc_version *version)
+{
+  struct register_pass_info pass_info;
+  const char *plugin_name = plugin_info->base_name;
+  int argc = plugin_info->argc;
+  struct plugin_argument *argv = plugin_info->argv;
+  char *ref_pass_name = NULL;
+  int ref_instance_number = 0;
+  int i;
+
+  /* Process the plugin arguments. This plugin takes the following arguments:
+     ref-pass-name=<PASS_NAME> and ref-pass-instance-num=<NUM>.  */
+  for (i = 0; i < argc; ++i)
+    {
+      if (!strcmp (argv[i].key, "ref-pass-name"))
+        {
+          if (argv[i].value)
+            ref_pass_name = argv[i].value;
+          else
+            warning (0, G_("option '-fplugin-arg-%s-ref-pass-name'"
+                           " requires a pass name"), plugin_name);
+        }
+      else if (!strcmp (argv[i].key, "ref-pass-instance-num"))
+        {
+          if (argv[i].value)
+            ref_instance_number = strtol (argv[i].value, NULL, 0);
+          else
+            warning (0, G_("option '-fplugin-arg-%s-ref-pass-instance-num'"
+                           " requires an integer value"), plugin_name);
+        }
+      else
+        warning (0, G_("plugin %qs: unrecognized argument %qs ignored"),
+                 plugin_name, argv[i].key);
+    }
+
+  if (!ref_pass_name)
+    {
+      error (G_("plugin %qs requires a reference pass name"), plugin_name);
+      return 1;
+    }
+
+  pass_info.pass = &pass_dumb_plugin_example.pass;
+  pass_info.reference_pass_name = ref_pass_name;
+  pass_info.ref_pass_instance_number = ref_instance_number;
+  pass_info.pos_op = PASS_POS_INSERT_AFTER;
+
+  register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
+
+  register_callback (plugin_name, PLUGIN_FINISH_TYPE, handle_type, NULL);
+
+  register_callback (plugin_name, PLUGIN_PRE_GENERICIZE,
+                     handle_pre_generic, NULL);
+
+  register_callback (plugin_name, PLUGIN_FINISH_UNIT,
+                     handle_end_of_compilation_unit, NULL);
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/plugin/plugin.exp
===================================================================
--- gcc/testsuite/gcc.dg/plugin/plugin.exp      (revision 178252)
+++ gcc/testsuite/gcc.dg/plugin/plugin.exp      (working copy)
@@ -52,6 +52,7 @@ set plugin_test_list [list \
     { one_time_plugin.c one_time-test-1.c } \
     { start_unit_plugin.c start_unit-test-1.c } \
     { finish_unit_plugin.c finish_unit-test-1.c } \
+       { dumb_plugin.c dumb-plugin-test-1.c } \
 ]
 
 foreach plugin_test $plugin_test_list {
Index: gcc/testsuite/g++.dg/plugin/dumb-plugin-test-1.C
===================================================================
--- gcc/testsuite/g++.dg/plugin/dumb-plugin-test-1.C    (revision 178252)
+++ gcc/testsuite/g++.dg/plugin/dumb-plugin-test-1.C    (working copy)
@@ -2,6 +2,8 @@
 // { dg-do compile }
 // { dg-options "-O -fplugin-arg-dumb_plugin-ref-pass-name=ccp 
-fplugin-arg-dumb_plugin-ref-pass-instance-num=1" }
 
+class Foo; // { dg-warning "Process struct Foo" }
+class Foo; // { dg-warning "Process struct Foo" }
 class Foo {
  private:
   int a_;
@@ -18,11 +20,32 @@ class Foo {
   } // { dg-warning "Before genericizing function" }
 }; // { dg-warning "Process struct Foo" }
 
+struct Bar; // { dg-warning "Process struct Bar" }
+struct Bar; // { dg-warning "Process struct Bar" }
 struct Bar {
   int b_;
   int c_;
 }; // { dg-warning "Process struct Bar" }
 
+struct my_struct {
+  int d_;
+  struct Bar e_; // { dg-warning "Process struct Bar" }
+}; // { dg-warning "Process struct my_struct" }
+
+union my_union; // { dg-warning "Process union my_union" }
+union my_union; // { dg-warning "Process union my_union" }
+union my_union {
+  int f_;
+  char g_;
+}; // { dg-warning "Process union my_union" }
+
+enum my_enum {
+  h_,
+  i_
+}; // { dg-warning "Process enum my_enum" }
+
+typedef int* my_typedef; // { dg-warning "Process typedef my_typedef" }
+
 int g = g;
 Foo foo = foo;
 
@@ -33,7 +56,7 @@ int func()
   int x = x;
   static int y = y;
   float *f;
-  Bar bar_array[5];
+  class Bar bar_array[5]; // { dg-warning "Process struct Bar" }
   char n;
   int overflow;
 
@@ -49,5 +72,5 @@ int func()
   x = y;
 } // { dg-warning "Before genericizing function" }
 
-// { dg-warning "Analyze function" "" { target *-*-* } 50 }
-// { dg-warning "End of compilation unit" "" { target *-*-* } 50 }
+// { dg-warning "Analyze function" "" { target *-*-* } 73 }
+// {  dg-warning "End of compilation unit" "" { target *-*-* } 73 }
Index: gcc/testsuite/g++.dg/plugin/dumb_plugin.c
===================================================================
--- gcc/testsuite/g++.dg/plugin/dumb_plugin.c   (revision 178252)
+++ gcc/testsuite/g++.dg/plugin/dumb_plugin.c   (working copy)
@@ -14,14 +14,33 @@
 
 int plugin_is_GPL_compatible;
 
-/* Callback function to invoke after GCC finishes parsing a struct.  */
+/* Callback function to invoke after GCC finishes parsing a type.  */
 
 void
-handle_struct (void *event_data, void *data)
+handle_type (void *event_data, void *data)
 {
   tree type = (tree) event_data;
-  warning (0, G_("Process struct %s"),
-           IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+
+  switch (TREE_CODE (type)) {
+    case RECORD_TYPE:
+      warning (0, G_("Process struct %s"),
+             IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+      break;
+    case UNION_TYPE:
+      warning (0, G_("Process union %s"),
+             IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+      break;
+    case ENUMERAL_TYPE:
+      warning (0, G_("Process enum %s"),
+             IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+      break;
+    case TYPE_DECL:
+      warning (0, G_("Process typedef %s"),
+             IDENTIFIER_POINTER (DECL_NAME (type)));
+      break;
+    default:
+      error (G_("Unexpected tree node in PLUGIN_FINISH_TYPE %s\n"), 
tree_code_name [TREE_CODE (type)]);
+  }
 }
 
 /* Callback function to invoke before the function body is genericized.  */ 
@@ -130,7 +149,7 @@ plugin_init (struct plugin_name_args *pl
 
   register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
 
-  register_callback (plugin_name, PLUGIN_FINISH_TYPE, handle_struct, NULL);
+  register_callback (plugin_name, PLUGIN_FINISH_TYPE, handle_type, NULL);
 
   register_callback (plugin_name, PLUGIN_PRE_GENERICIZE,
                      handle_pre_generic, NULL);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c       (revision 178252)
+++ gcc/cp/decl.c       (working copy)
@@ -9682,6 +9682,9 @@ grokdeclarator (const cp_declarator *dec
                      memfn_quals != TYPE_UNQUALIFIED,
                      inlinep, friendp, raises != NULL_TREE);
 
+      if (TREE_TYPE (decl) != error_mark_node && !DECL_ARTIFICIAL (decl))
+        invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, decl);
+
       return decl;
     }
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 178252)
+++ gcc/cp/parser.c     (working copy)
@@ -12578,7 +12578,9 @@ cp_parser_type_specifier (cp_parser* par
                                          type_spec,
                                          token->location,
                                          /*user_defined_p=*/true);
-         return type_spec;
+
+       invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
+       return type_spec;
        }
       else
        goto elaborated_type_specifier;
@@ -12596,7 +12598,7 @@ cp_parser_type_specifier (cp_parser* par
       cp_parser_parse_tentatively (parser);
       /* Look for the class-specifier.  */
       type_spec = cp_parser_class_specifier (parser);
-      invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
+
       /* If that worked, we're done.  */
       if (cp_parser_parse_definitely (parser))
        {
@@ -12607,7 +12609,9 @@ cp_parser_type_specifier (cp_parser* par
                                          type_spec,
                                          token->location,
                                          /*user_defined_p=*/true);
-         return type_spec;
+
+      invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
+      return type_spec;
        }
 
       /* Fall through.  */
@@ -12629,6 +12633,10 @@ cp_parser_type_specifier (cp_parser* par
                                      type_spec,
                                      token->location,
                                      /*user_defined_p=*/true);
+
+      if (declares_class_or_enum && *declares_class_or_enum)
+        invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
+
       return type_spec;
 
     case RID_CONST:
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c        (revision 178252)
+++ gcc/c-decl.c        (working copy)
@@ -5763,6 +5763,9 @@ grokdeclarator (const struct c_declarato
            }
        }
 
+      if (!DECL_ARTIFICIAL (decl))
+        invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, decl);
+
       return decl;
     }
 
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c      (revision 178252)
+++ gcc/c-parser.c      (working copy)
@@ -2133,6 +2133,7 @@ c_parser_declspecs (c_parser *parser, st
          attrs_ok = true;
          seen_type = true;
          t = c_parser_enum_specifier (parser);
+         invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
          declspecs_add_type (loc, specs, t);
          break;
        case RID_STRUCT:
@@ -2142,7 +2143,7 @@ c_parser_declspecs (c_parser *parser, st
          attrs_ok = true;
          seen_type = true;
          t = c_parser_struct_or_union_specifier (parser);
-          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+         invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
          declspecs_add_type (loc, specs, t);
          break;
        case RID_TYPEOF:

Reply via email to