This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [plugins] Add user attribute(try #2)
- From: Taras Glek <tglek at mozilla dot com>
- To: Diego Novillo <dnovillo at google dot com>
- Cc: Le-Chun Wu <lcwu at google dot com>, "Joseph S. Myers" <joseph at codesourcery dot com>, Richard Guenther <richard dot guenther at gmail dot com>, gcc-patches at gcc dot gnu dot org
- Date: Tue, 12 May 2009 17:38:53 -0700
- Subject: Re: [plugins] Add user attribute(try #2)
- References: <49D25E40.6080507@mozilla.com> <84fc9c000904010146j53e49ed9i6c271751d41dfd42@mail.gmail.com> <Pine.LNX.4.64.0904011257550.14922@digraph.polyomino.org.uk> <49D398C9.1010809@mozilla.com> <82091ad70904021448y71547117q9fbd21cb8bd5b94d@mail.gmail.com> <49EFA543.8030602@mozilla.com> <b798aad50905120523g5bd39e0clac07d2019dff7778@mail.gmail.com>
Diego Novillo wrote:
On Wed, Apr 22, 2009 at 19:16, Taras Glek <tglek@mozilla.com> wrote:
+void
+register_attribute (const struct attribute_spec *attr)
+{
Needs comment.
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -29,6 +29,7 @@ enum plugin_event
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
PLUGIN_INFO, /* Information about the plugin */
+ PLUGIN_ATTRIBUTES, /* Called during attribute registration */
Needs to be added to plugins.texi.
Also, could you add a testcase and documentation on how plugins
should use this mechanism?
Finally, the patch needs a ChangeLog entry.
Docs + testcase made for a big changelog.
2009-05-12 Taras Glek <tglek@mozilla.com>
gcc/ChangeLog
* attribs.c moved out attribute registration into register_attribute
* doc/plugins.texi Documented register_attribute and
PLUGIN_ATTRIBUTES
* gcc-plugin.h Added forward decl for register_attribute
* plugin.c Added PLUGIN_ATTRIBUTES boilerplate
* plugin.h Added PLUGIN_ATTRIBUTES
gcc/testsuite/ChangeLog
* g++.dg/plugin/attribute_plugin-test-1.C Testcase input for
custom attributes and decl smashing
* g++.dg/plugin/attribute_plugin.c Testcase plugin to test user
attributes
* g++.dg/plugin/dumb_plugin.c Fixed typo
* g++.dg/plugin/plugin.exp Added attribute_plugin test
The testcase has 2 XFails which will turn to PASSes once decl smashing
fix lands (http://gcc.gnu.org/ml/gcc-patches/2009-05/msg00657.html)
Hope this is it,
Taras
diff --git a/gcc/attribs.c b/gcc/attribs.c
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.
#include "target.h"
#include "langhooks.h"
#include "hashtab.h"
+#include "plugin.h"
static void init_attributes (void);
@@ -182,18 +183,27 @@ init_attributes (void)
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
for (k = 0; attribute_tables[i][k].name != NULL; k++)
{
+ register_attribute (&attribute_tables[i][k]);
+ }
+ invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
+ attributes_initialized = true;
+}
+
+/* Insert a single attribute into the attribute table */
+
+void
+register_attribute (const struct attribute_spec *attr)
+{
struct substring str;
const void **slot;
- str.str = attribute_tables[i][k].name;
- str.length = strlen (attribute_tables[i][k].name);
+ str.str = attr->name;
+ str.length = strlen (str.str);
slot = (const void **)htab_find_slot_with_hash (attribute_hash, &str,
substring_hash (str.str, str.length),
INSERT);
gcc_assert (!*slot);
- *slot = &attribute_tables[i][k];
- }
- attributes_initialized = true;
+ *slot = attr;
}
/* Return the spec for the attribute named NAME. */
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -71,6 +71,7 @@ enum plugin_event
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
+ PLUGIN_ATTRIBUTES, /* Called during attribute registration */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
array. */
@};
@@ -135,3 +136,35 @@ plugin_init (const char *plugin_name, in
...
@}
@end smallexample
+@section Registering custom attributes
+
+For analysis purposes it is useful to be able to add custom attributes.
+
+The @code{PLUGIN_ATTRIBUTES} callback is called during attribute
+registration. Use the @code{register_attribute} function to register
+custom attributes.
+
+@smallexample
+/* Attribute handler callback */
+static tree
+handle_user_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+@{
+ return NULL_TREE;
+@}
+
+/* Attribute definition */
+static struct attribute_spec user_attr =
+ @{ "user", 1, 1, false, false, false, handle_user_attribute @};
+
+/* Plugin callback called during attribute registration.
+Registered with register_callback (plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL)
+*/
+static void
+register_attributes (void *event_data, void *data)
+@{
+ warning (0, G_("Callback to register attributes"));
+ register_attribute (&user_attr);
+@}
+
+@end smallexample
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -29,6 +29,7 @@ enum plugin_event
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
PLUGIN_INFO, /* Information about the plugin */
+ PLUGIN_ATTRIBUTES, /* Called during attribute registration */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
array. */
};
diff --git a/gcc/plugin.c b/gcc/plugin.c
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -493,6 +493,7 @@ register_callback (const char *plugin_na
case PLUGIN_FINISH_TYPE:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
+ case PLUGIN_ATTRIBUTES:
case PLUGIN_FINISH:
{
struct callback_info *new_callback;
@@ -534,6 +535,7 @@ invoke_plugin_callbacks (enum plugin_eve
case PLUGIN_FINISH_TYPE:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
+ case PLUGIN_ATTRIBUTES:
case PLUGIN_FINISH:
{
/* Iterate over every callback registered with this event and
diff --git a/gcc/plugin.h b/gcc/plugin.h
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.
#include "gcc-plugin.h"
+struct attribute_spec;
+
extern void add_new_plugin (const char *);
extern void parse_plugin_arg_opt (const char *);
extern void invoke_plugin_callbacks (enum plugin_event, void *);
@@ -33,4 +35,8 @@ extern void print_plugins_versions (FILE
extern void print_plugins_help (FILE *file, const char *indent);
extern void finalize_plugins (void);
+/* in attribs.c */
+
+extern void register_attribute (const struct attribute_spec *attr);
+
#endif /* PLUGIN_H */
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C b/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C
new file mode 100644
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C
@@ -0,0 +1,16 @@
+// { dg-warning "Callback to register attributes" }
+
+void normal_func (char c, char c2);
+void normal_func (char __attribute__((user("param"))) c, char);
+void normal_func (char c, char __attribute__((user("param"))) c2)
+{
+} // { dg-warning "attribute 'user' on param 'c' of function normal_func" "" { xfail *-*-* } }
+// { dg-warning "attribute 'user' on param 'c2' of function normal_func" "" { target *-*-* } 7 }
+
+class Foo {
+ void method (char __attribute__((user("param"))) c);
+};
+
+void Foo::method(char c)
+{
+} // { dg-warning "attribute 'user' on param 'c' of function method" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
new file mode 100644
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
@@ -0,0 +1,66 @@
+/* Demonstrates how to add custom attributes */
+
+#include <stdlib.h>
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "gcc-plugin.h"
+
+/* Attribute handler callback */
+
+static tree
+handle_user_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ return NULL_TREE;
+}
+
+/* Attribute definition */
+
+static struct attribute_spec user_attr =
+ { "user", 1, 1, false, false, false, handle_user_attribute };
+
+/* Plugin callback called during attribute registration */
+
+static void
+register_attributes (void *event_data, void *data)
+{
+ warning (0, G_("Callback to register attributes"));
+ register_attribute (&user_attr);
+}
+
+/* Callback function to invoke before the function body is genericized. */
+
+void
+handle_pre_generic (void *event_data, void *data)
+{
+ tree fndecl = (tree) event_data;
+ tree arg;
+ for (arg = DECL_ARGUMENTS(fndecl); arg; arg = TREE_CHAIN (arg)) {
+ tree attr;
+ for (attr = DECL_ATTRIBUTES (arg); attr; attr = TREE_CHAIN (attr)) {
+ tree attrname = TREE_PURPOSE (attr);
+ tree attrargs = TREE_VALUE (attr);
+ warning (0, G_("attribute '%s' on param '%s' of function %s"),
+ IDENTIFIER_POINTER (attrname),
+ IDENTIFIER_POINTER (DECL_NAME (arg)),
+ IDENTIFIER_POINTER (DECL_NAME (fndecl))
+ );
+ }
+ }
+}
+
+int
+plugin_init (const char *plugin_name,
+ struct plugin_gcc_version *version,
+ int argc, struct plugin_argument *argv)
+{
+ register_callback (plugin_name, PLUGIN_CXX_CP_PRE_GENERICIZE,
+ handle_pre_generic, NULL);
+
+ register_callback (plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
--- a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
@@ -21,7 +21,7 @@ handle_struct (void *event_data, void *d
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}
-/* Callback function to invoke before the program is genericized. */
+/* Callback function to invoke before the function body is genericized. */
void
handle_pre_generic (void *event_data, void *data)
diff --git a/gcc/testsuite/g++.dg/plugin/plugin.exp b/gcc/testsuite/g++.dg/plugin/plugin.exp
--- a/gcc/testsuite/g++.dg/plugin/plugin.exp
+++ b/gcc/testsuite/g++.dg/plugin/plugin.exp
@@ -47,6 +47,7 @@ load_lib plugin-support.exp
# Specify the plugin source file and the associated test files in a list.
# plugin_test_list={ {plugin1 test1 test2 ...} {plugin2 test1 ...} ... }
set plugin_test_list [list \
+ { attribute_plugin.c attribute_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 } ]