Date: Tue, 22 Dec 2009 10:00:29 -0800 Subject: plugin event for C/C++ declarations From: Brian Hackett To: gcc-patches at gcc dot gnu dot org Hi, this patch adds a new plugin event FINISH_DECL, which is invoked at every finish_decl in the C and C++ frontends. Previously there did not seem to be a way for a plugin to see the definition for a global that is never used in the input file, or the initializer for a global which is declared before a function but defined after. This event isn't restricted to just globals though, but also locals, fields, and parameters (C frontend only). Index: gcc/doc/plugins.texi =================================================================== --- gcc/doc/plugins.texi (revision 155401) +++ gcc/doc/plugins.texi (working copy) @@ -146,6 +146,7 @@ enum plugin_event PLUGIN_FINISH_TYPE, /* After finishing parsing a type. */ PLUGIN_FINISH_UNIT, /* Useful for summary processing. */ PLUGIN_PRE_GENERICIZE, /* Allows to see low level AST in C and C++ frontends. */ + PLUGIN_FINISH_DECL, /* Allows to see all declarations in C and C++ frontends. */ PLUGIN_FINISH, /* Called before GCC exits. */ PLUGIN_INFO, /* Information about the plugin. */ PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */ Index: gcc/plugin.def =================================================================== --- gcc/plugin.def (revision 155386) +++ gcc/plugin.def (working copy) @@ -30,6 +30,9 @@ DEFEVENT (PLUGIN_FINISH_UNIT) /* Allows to see low level AST in C and C++ frontends. */ DEFEVENT (PLUGIN_PRE_GENERICIZE) +/* Allows to see all declarations in C and C++ frontends. */ +DEFEVENT (PLUGIN_FINISH_DECL) + /* Called before GCC exits. */ DEFEVENT (PLUGIN_FINISH) Index: gcc/testsuite/g++.dg/plugin/plugin.exp =================================================================== --- gcc/testsuite/g++.dg/plugin/plugin.exp (revision 155401) +++ gcc/testsuite/g++.dg/plugin/plugin.exp (working copy) @@ -51,7 +51,8 @@ set plugin_test_list [list \ { pragma_plugin.c pragma_plugin-test-1.C } \ { selfassign.c self-assign-test-1.C self-assign-test-2.C self-assign-test-3.C } \ { dumb_plugin.c dumb-plugin-test-1.C } \ - { header_plugin.c header-plugin-test.C } ] + { header_plugin.c header-plugin-test.C } \ + { decl_plugin.c decl-plugin-test.C } ] foreach plugin_test $plugin_test_list { # Replace each source file with its full-path name Index: gcc/testsuite/g++.dg/plugin/decl-plugin-test.C =================================================================== --- gcc/testsuite/g++.dg/plugin/decl-plugin-test.C (revision 0) +++ gcc/testsuite/g++.dg/plugin/decl-plugin-test.C (revision 0) @@ -0,0 +1,32 @@ + + +extern int global; // { dg-warning "Decl Global global" } +int global_array[] = { 1, 2, 3 }; // { dg-warning "Decl Global global_array" } + +int takes_args(int arg1, int arg2) +{ + int local = arg1 + arg2 + global; // { dg-warning "Decl Local local" } + return local + 1; +} + +int global = 12; // { dg-warning "Decl Global global" } + +struct test_str { + int field; // { dg-warning "Decl Field field" } +}; + +class test_class { + int class_field1; // { dg-warning "Decl Field class_field1" } + int class_field2; // { dg-warning "Decl Field class_field2" } + + test_class() // { dg-warning "Decl Function test_class" } + : class_field1(0), class_field2(0) + {} + + void swap_fields(int bias) // { dg-warning "Decl Function swap_fields" } + { + int temp = class_field1 + bias; // { dg-warning "Decl Local temp" } + class_field1 = class_field2 - bias; + class_field2 = temp; + } +}; Index: gcc/testsuite/g++.dg/plugin/decl_plugin.c =================================================================== --- gcc/testsuite/g++.dg/plugin/decl_plugin.c (revision 0) +++ gcc/testsuite/g++.dg/plugin/decl_plugin.c (revision 0) @@ -0,0 +1,51 @@ +/* A plugin example that shows which declarations are caught by FINISH_DECL */ + +#include "gcc-plugin.h" +#include +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-pass.h" +#include "intl.h" + +int plugin_is_GPL_compatible; + +/* Callback function to invoke after GCC finishes a declaration. */ + +void plugin_finish_decl (void *event_data, void *data) +{ + tree decl = (tree) event_data; + + const char *kind = NULL; + switch (TREE_CODE(decl)) { + case FUNCTION_DECL: + kind = "Function"; break; + case PARM_DECL: + kind = "Parameter"; break; + case VAR_DECL: + if (DECL_CONTEXT(decl) != NULL) + kind = "Local"; + else + kind = "Global"; + break; + case FIELD_DECL: + kind = "Field"; break; + default: + kind = "Unknown"; + } + + warning (0, G_("Decl %s %s"), + kind, IDENTIFIER_POINTER (DECL_NAME (decl))); +} + +int +plugin_init (struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + const char *plugin_name = plugin_info->base_name; + + register_callback (plugin_name, PLUGIN_FINISH_DECL, + plugin_finish_decl, NULL); + return 0; +} Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 155386) +++ gcc/cp/decl.c (working copy) @@ -5949,6 +5949,8 @@ cp_finish_decl (tree decl, tree init, bo /* If this was marked 'used', be sure it will be output. */ if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) mark_decl_referenced (decl); + + invoke_plugin_callbacks(PLUGIN_FINISH_DECL, decl); } /* Returns a declaration for a VAR_DECL as if: Index: gcc/c-decl.c =================================================================== --- gcc/c-decl.c (revision 155386) +++ gcc/c-decl.c (working copy) @@ -4389,6 +4389,8 @@ finish_decl (tree decl, location_t init_ && DECL_INITIAL (decl) == NULL_TREE) warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat, "uninitialized const %qD is invalid in C++", decl); + + invoke_plugin_callbacks(PLUGIN_FINISH_DECL, decl); } /* Given a parsed parameter declaration, decode it into a PARM_DECL. */ Index: gcc/plugin.c =================================================================== --- gcc/plugin.c (revision 155386) +++ gcc/plugin.c (working copy) @@ -403,6 +403,7 @@ register_callback (const char *plugin_na case PLUGIN_START_UNIT: case PLUGIN_FINISH_UNIT: case PLUGIN_PRE_GENERICIZE: + case PLUGIN_FINISH_DECL: case PLUGIN_GGC_START: case PLUGIN_GGC_MARKING: case PLUGIN_GGC_END: @@ -484,6 +485,7 @@ invoke_plugin_callbacks (int event, void case PLUGIN_START_UNIT: case PLUGIN_FINISH_UNIT: case PLUGIN_PRE_GENERICIZE: + case PLUGIN_FINISH_DECL: case PLUGIN_ATTRIBUTES: case PLUGIN_PRAGMAS: case PLUGIN_FINISH: