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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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: