From patchwork Mon Sep 12 08:01:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain GEISSLER X-Patchwork-Id: 114298 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id C7D2AB708F for ; Mon, 12 Sep 2011 18:02:09 +1000 (EST) Received: (qmail 29274 invoked by alias); 12 Sep 2011 08:02:04 -0000 Received: (qmail 29241 invoked by uid 22791); 12 Sep 2011 08:01:58 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,TW_FN X-Spam-Check-By: sourceware.org Received: from eu1sys200aog104.obsmtp.com (HELO eu1sys200aog104.obsmtp.com) (207.126.144.117) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 12 Sep 2011 08:01:39 +0000 Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob104.postini.com ([207.126.147.11]) with SMTP ID DSNKTm28YWCgeen/ZEt4ghrBNeAOdzg0M4Vr@postini.com; Mon, 12 Sep 2011 08:01:38 UTC Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id DBC85115 for ; Mon, 12 Sep 2011 08:01:36 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas1.st.com [10.75.90.14]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8B1A7171C for ; Mon, 12 Sep 2011 08:01:36 +0000 (GMT) Received: from [164.129.122.91] (164.129.122.91) by webmail-eu.st.com (10.75.90.13) with Microsoft SMTP Server (TLS) id 8.2.234.1; Mon, 12 Sep 2011 10:01:35 +0200 Message-ID: <4E6DBC5F.6070408@st.com> Date: Mon, 12 Sep 2011 10:01:35 +0200 From: Romain Geissler User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.18) Gecko/20110616 Thunderbird/3.1.11 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org" Subject: [PLUGIN] Fix PLUGIN_FINISH_TYPE X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * 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 * 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 * 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 +#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= and ref-pass-instance-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: