]> TLD Linux GIT Repositories - packages/gcc.git/blob - gcc-plugin-decl-hook.patch
9865f65e888c6d115dfcb4abc8e73d1974440022
[packages/gcc.git] / gcc-plugin-decl-hook.patch
1 Date: Tue, 22 Dec 2009 10:00:29 -0800
2 Subject: plugin event for C/C++ declarations
3 From: Brian Hackett <bhackett1024 at gmail dot com>
4 To: gcc-patches at gcc dot gnu dot org
5
6 Hi, this patch adds a new plugin event FINISH_DECL, which is invoked
7 at every finish_decl in the C and C++ frontends.  Previously there did
8 not seem to be a way for a plugin to see the definition for a global
9 that is never used in the input file, or the initializer for a global
10 which is declared before a function but defined after.  This event
11 isn't restricted to just globals though, but also locals, fields, and
12 parameters (C frontend only).
13
14 Index: gcc/doc/plugins.texi
15 ===================================================================
16 --- gcc/doc/plugins.texi        (revision 155401)
17 +++ gcc/doc/plugins.texi        (working copy)
18 @@ -146,6 +146,7 @@ enum plugin_event
19    PLUGIN_FINISH_TYPE,           /* After finishing parsing a type.  */
20    PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
21    PLUGIN_PRE_GENERICIZE,        /* Allows to see low level AST in C and C++ frontends.  */
22 +  PLUGIN_FINISH_DECL,           /* Allows to see all declarations in C and C++ frontends. */
23    PLUGIN_FINISH,                /* Called before GCC exits.  */
24    PLUGIN_INFO,                  /* Information about the plugin. */
25    PLUGIN_GGC_START,            /* Called at start of GCC Garbage Collection. */
26 Index: gcc/plugin.def
27 ===================================================================
28 --- gcc/plugin.def      (revision 155386)
29 +++ gcc/plugin.def      (working copy)
30 @@ -30,6 +30,9 @@ DEFEVENT (PLUGIN_FINISH_UNIT)
31  /* Allows to see low level AST in C and C++ frontends. */
32  DEFEVENT (PLUGIN_PRE_GENERICIZE)
33
34 +/* Allows to see all declarations in C and C++ frontends. */
35 +DEFEVENT (PLUGIN_FINISH_DECL)
36 +
37  /* Called before GCC exits.  */
38  DEFEVENT (PLUGIN_FINISH)
39
40 Index: gcc/testsuite/g++.dg/plugin/plugin.exp
41 ===================================================================
42 --- gcc/testsuite/g++.dg/plugin/plugin.exp      (revision 155401)
43 +++ gcc/testsuite/g++.dg/plugin/plugin.exp      (working copy)
44 @@ -51,7 +51,8 @@ set plugin_test_list [list \
45      { pragma_plugin.c pragma_plugin-test-1.C } \
46      { selfassign.c self-assign-test-1.C self-assign-test-2.C self-assign-test-3.C } \
47      { dumb_plugin.c dumb-plugin-test-1.C } \
48 -    { header_plugin.c header-plugin-test.C } ]
49 +    { header_plugin.c header-plugin-test.C } \
50 +    { decl_plugin.c decl-plugin-test.C } ]
51
52  foreach plugin_test $plugin_test_list {
53      # Replace each source file with its full-path name
54 Index: gcc/testsuite/g++.dg/plugin/decl-plugin-test.C
55 ===================================================================
56 --- gcc/testsuite/g++.dg/plugin/decl-plugin-test.C      (revision 0)
57 +++ gcc/testsuite/g++.dg/plugin/decl-plugin-test.C      (revision 0)
58 @@ -0,0 +1,32 @@
59 +
60 +
61 +extern int global; // { dg-warning "Decl Global global" }
62 +int global_array[] = { 1, 2, 3 }; // { dg-warning "Decl Global global_array" }
63 +
64 +int takes_args(int arg1, int arg2)
65 +{
66 +  int local = arg1 + arg2 + global; // { dg-warning "Decl Local local" }
67 +  return local + 1;
68 +}
69 +
70 +int global = 12; // { dg-warning "Decl Global global" }
71 +
72 +struct test_str {
73 +  int field; // { dg-warning "Decl Field field" }
74 +};
75 +
76 +class test_class {
77 +  int class_field1; // { dg-warning "Decl Field class_field1" }
78 +  int class_field2; // { dg-warning "Decl Field class_field2" }
79 +
80 +  test_class() // { dg-warning "Decl Function test_class" }
81 +    : class_field1(0), class_field2(0)
82 +  {}
83 +
84 +  void swap_fields(int bias) // { dg-warning "Decl Function swap_fields" }
85 +  {
86 +    int temp = class_field1 + bias; // { dg-warning "Decl Local temp" }
87 +    class_field1 = class_field2 - bias;
88 +    class_field2 = temp;
89 +  }
90 +};
91 Index: gcc/testsuite/g++.dg/plugin/decl_plugin.c
92 ===================================================================
93 --- gcc/testsuite/g++.dg/plugin/decl_plugin.c   (revision 0)
94 +++ gcc/testsuite/g++.dg/plugin/decl_plugin.c   (revision 0)
95 @@ -0,0 +1,51 @@
96 +/* A plugin example that shows which declarations are caught by FINISH_DECL */
97 +
98 +#include "gcc-plugin.h"
99 +#include <stdlib.h>
100 +#include "config.h"
101 +#include "system.h"
102 +#include "coretypes.h"
103 +#include "tree.h"
104 +#include "tree-pass.h"
105 +#include "intl.h"
106 +
107 +int plugin_is_GPL_compatible;
108 +
109 +/* Callback function to invoke after GCC finishes a declaration. */
110 +
111 +void plugin_finish_decl (void *event_data, void *data)
112 +{
113 +  tree decl = (tree) event_data;
114 +
115 +  const char *kind = NULL;
116 +  switch (TREE_CODE(decl)) {
117 +  case FUNCTION_DECL:
118 +    kind = "Function"; break;
119 +  case PARM_DECL:
120 +    kind = "Parameter"; break;
121 +  case VAR_DECL:
122 +    if (DECL_CONTEXT(decl) != NULL)
123 +      kind = "Local";
124 +    else
125 +      kind = "Global";
126 +    break;
127 +  case FIELD_DECL:
128 +    kind = "Field"; break;
129 +  default:
130 +    kind = "Unknown";
131 +  }
132 +
133 +  warning (0, G_("Decl %s %s"),
134 +           kind, IDENTIFIER_POINTER (DECL_NAME (decl)));
135 +}
136 +
137 +int
138 +plugin_init (struct plugin_name_args *plugin_info,
139 +             struct plugin_gcc_version *version)
140 +{
141 +  const char *plugin_name = plugin_info->base_name;
142 +
143 +  register_callback (plugin_name, PLUGIN_FINISH_DECL,
144 +                     plugin_finish_decl, NULL);
145 +  return 0;
146 +}
147 Index: gcc/cp/decl.c
148 ===================================================================
149 --- gcc/cp/decl.c       (revision 155386)
150 +++ gcc/cp/decl.c       (working copy)
151 @@ -5949,6 +5949,8 @@ cp_finish_decl (tree decl, tree init, bo
152    /* If this was marked 'used', be sure it will be output.  */
153    if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
154      mark_decl_referenced (decl);
155 +
156 +  invoke_plugin_callbacks(PLUGIN_FINISH_DECL, decl);
157  }
158
159  /* Returns a declaration for a VAR_DECL as if:
160 Index: gcc/c-decl.c
161 ===================================================================
162 --- gcc/c-decl.c        (revision 155386)
163 +++ gcc/c-decl.c        (working copy)
164 @@ -4389,6 +4389,8 @@ finish_decl (tree decl, location_t init_
165        && DECL_INITIAL (decl) == NULL_TREE)
166      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
167                 "uninitialized const %qD is invalid in C++", decl);
168 +
169 +  invoke_plugin_callbacks(PLUGIN_FINISH_DECL, decl);
170  }
171
172  /* Given a parsed parameter declaration, decode it into a PARM_DECL.  */
173 Index: gcc/plugin.c
174 ===================================================================
175 --- gcc/plugin.c        (revision 155386)
176 +++ gcc/plugin.c        (working copy)
177 @@ -403,6 +403,7 @@ register_callback (const char *plugin_na
178        case PLUGIN_START_UNIT:
179        case PLUGIN_FINISH_UNIT:
180        case PLUGIN_PRE_GENERICIZE:
181 +      case PLUGIN_FINISH_DECL:
182        case PLUGIN_GGC_START:
183        case PLUGIN_GGC_MARKING:
184        case PLUGIN_GGC_END:
185 @@ -484,6 +485,7 @@ invoke_plugin_callbacks (int event, void
186        case PLUGIN_START_UNIT:
187        case PLUGIN_FINISH_UNIT:
188        case PLUGIN_PRE_GENERICIZE:
189 +      case PLUGIN_FINISH_DECL:
190        case PLUGIN_ATTRIBUTES:
191        case PLUGIN_PRAGMAS:
192        case PLUGIN_FINISH: