Hi

2011/9/12 Dodji Seketeli <do...@seketeli.org>:
> Romain Geissler <romain.geiss...@gmail.com> a écrit:
>> When i recontributed the PLUGIN_FINISH_DECL patch from the original
>> Brian Hackett, i didn't exactly checked  what may or may not trigger
>> this new event. I know for example that declaring a function triggers
>> this event, but defining it does not.
>>
>> I don't really know when those event should be triggered, we should
>> clarify the meaning of those.
>>
>> According to me:
>> PLUGIN_FINISH_DECL should be triggered anytime the parser parse a
>> declaration (which includes declaration + definition of function,
>> typedef definition, namespaces, ..., all DECL_P trees built by the
>> parser).
>
> The general idea sounds sensible, IMHO.  However, we must keep in mind
> that there are cases like, e.g, 'struct C;' where G++ creates a typedef
> 'typedef struct C C;' so that you can name that type 'C' instead of
> having to type "struct C' all the time.  For these cases, I don't think
> the PLUGIN_FINISH_DECL event should be emitted.

I agree.

>
>> For, PLUGIN_FINISH_TYPE i don't really know it means a new type
>> declaration (or declaration + definition) or if it means usage of a
>> type (in a function prototype, the type of a local variable.
>
> I'd say it's a definition of a new type, IMHO.

Ok, so it only involves struct, unions, enum and class declaration / 
definitions.

>
>> I would rather vote for new type definition (including typedefs)
>
> My understanding is that a typedef declaration doesn't define a new
> type.  Rather, it declares an alias for an existing type.  As such, I
> would think that notifying typedef declarations via PLUGIN_FINISH_DECL
> would be the way to go.

Ok

>
>> but for special cases of struct, you can declare and use them at the
>> same time:
>
> Just to be sure I understand, do you need to be notified about *uses* of
> types and decls as well?  If so, maybe a new kind of event should
> probably be defined, because PLUGIN_FINISH_DECL and PLUGIN_FINISH_TYPE
> seem to have more to do with declaring/defining decls and types than
> using them.
>

Personally i don't need to catch all struct uses, but i need to catch struct 
declarations.
I want to apply some __attributes__ to a given struct type, for example let's say i need to mark *struct my_struct* as deprecated thanks to a plugin. I know how to apply some attributes to a type or a decl. See the plugin (test_plugin.c) and the test files attached.

With test_pass.c, my_struct is declared first, then defined after, applying the deprecated attribute works. With test_fail.c, my_struct is declared and defined at the same time, applying the deprecated attribute doesn't work with the current trunk (and also with my patch).
I got:
test_fail.c:4:1: warning: type attributes ignored after type is already defined 
[-Wattributes]

So i may need a PLUGIN_FINISH_TYPE_DECLARATION triggered when the type is declared but before it is finally defined.

Does two different events PLUGIN_FINISH_TYPE_DECLARATION and PLUGIN_FINISH_TYPE_DEFINITION make sens to you ?

> --
>                Dodji
>

Romain Geissler
struct my_struct {
        int field_1;
        int field_2;
};

struct my_struct *my_function();

struct my_struct x = {1, 2};

struct my_struct *my_function(){
        return &x;
}
struct my_struct *my_function();

struct my_struct {
        int field_1;
        int field_2;
};

struct my_struct x = {1, 2};

struct my_struct *my_function(){
        return &x;
}
#include "gcc-plugin.h"
#include "plugin-version.h"
#include "tree.h"
#include "cp/cp-tree.h"

#pragma weak cplus_decl_attributes

bool my_struct_found = false;
void finish_type_callback (void *gcc_data, void *data ATTRIBUTE_UNUSED) {
        tree type = (tree)gcc_data;
        const char *type_name;

        if (my_struct_found || type == error_mark_node || DECL_P (type)) {
                //current PLUGIN_FINISH_TYPE is buggy in C++
                //and my current patch may return TYPE_DECL for typedefs

                return;
        }

        if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) {
                type_name = IDENTIFIER_POINTER (TYPE_NAME (type));
        } else {
                type_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
        }

        if (strcmp (type_name, "my_struct")) {
                //only affect my_struct type
                return;
        }

        my_struct_found = true;
        tree deprecated_attribute = tree_cons (get_identifier ("deprecated"), 
NULL_TREE, NULL_TREE);
        inform(input_location,  "my_struct found");


        //apply the deprecated attribute to the my_struct type.
        if (cplus_decl_attributes) {
                cplus_decl_attributes (&type, deprecated_attribute, 
ATTR_FLAG_TYPE_IN_PLACE);
        } else {
                decl_attributes (&type, deprecated_attribute, 
ATTR_FLAG_TYPE_IN_PLACE);
        }
}

int plugin_is_GPL_compatible;

int plugin_init (struct plugin_name_args *plugin_info,
        struct plugin_gcc_version *version ATTRIBUTE_UNUSED)
{
        register_callback (plugin_info->base_name, PLUGIN_FINISH_TYPE, 
&finish_type_callback, NULL);

        return 0;
}

Reply via email to