Bug 62252 - a callback to event PLUGIN_FINISH_TYPE should be moved such that it is only after checking definitely parsing is done
Summary: a callback to event PLUGIN_FINISH_TYPE should be moved such that it is only a...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: plugin
Depends on:
Blocks:
 
Reported: 2014-08-24 17:38 UTC by klemen.jan.enova
Modified: 2022-01-09 17:06 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-08-24 00:00:00


Attachments
cp-parser-patch (333 bytes, patch)
2014-08-25 08:02 UTC, klemen.jan.enova
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description klemen.jan.enova 2014-08-24 17:38:40 UTC
The following plugin is a reduced version of "testsuite/g++.dg/plugin/dumb_plugin.c".

I tested it with

- the ubuntu binary version of gcc-4.9
- ubuntu binary version of gcc-4.8 (g++-4.8 (Ubuntu 4.8.2-19ubuntu1) 4.8.2)
- the compiled version of gcc-4.9 taken from the 4.9 release (https://github.com/gcc-mirror/gcc/releases/tag/gcc-4_9_0-release)

All tests segfault. 

---
kje@kje:~$ uname -a
Linux kje 3.13.0-34-generic #60-Ubuntu SMP Wed Aug 13 15:45:27 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
kje@kje:~/example$ cat example.c
#include "gcc-plugin.h"
//#include <stdlib.h>
#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"
#include "context.h"

int plugin_is_GPL_compatible;

void
handle_struct (void *event_data, void *data)
{
	tree type = (tree) event_data;
	warning(0, G_("Process struct %s"),
		IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}

int
plugin_init (struct plugin_name_args *plugin_info,
             struct plugin_gcc_version *version)
{
  register_callback ("example", PLUGIN_FINISH_TYPE, handle_struct, NULL);

	return 0;
}
kje@kje:~/example$ cat example_test.c
struct S {
	int x;
};

int main(void)
{
	struct S s;
	s.x = 5;

	return 0;
}
kje@kje:~/example$ g++-4.9 --version
g++-4.9 (Ubuntu 4.9.1-3ubuntu2~14.04.1) 4.9.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

kje@kje:~/example$ g++-4.9 -fPIC -g -I/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.9.0/plugin/include -c example.c
kje@kje:~/example$ g++-4.9 -fPIC -g -I/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.9.0/plugin/include -shared example.o -o example_plugin.so
kje@kje:~/example$ g++-4.9 -fplugin=./example_plugin.so example_test.c
example_test.c:3:1: warning: Process struct S
 };
 ^
*** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins.
Event                            | Plugins
PLUGIN_FINISH_TYPE               | example
example_test.c: In function ‘int main()’:
example_test.c:7:9: internal compiler error: Segmentation fault
  struct S s;
         ^
0x7f1d3226c780 handle_struct(void*, void*)
	/home/kje/example/example.c:20
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <file:///usr/share/doc/gcc-4.9/README.Bugs> for instructions.
The bug is not reproducible, so it is likely a hardware or OS problem.

---

If I use g++ compiled from (configure with --enable-languagues=c,c++) the github repository 4.9 release, I get the whole call stack:

---

kje@kje:~/example$ g++ --version
g++ (GCC) 4.9.0
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

kje@kje:~/example$ g++ -fplugin=./example_plugin.so example_test.c
example_test.c:3:1: warning: Process struct S
 };
 ^
*** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins.
Event                            | Plugins
PLUGIN_FINISH_TYPE               | example
example_test.c: In function ‘int main()’:
example_test.c:7:9: internal compiler error: Segmentation fault
  struct S s;
         ^
0x98cc2f crash_signal
	../../../gcc4.9/gcc/toplev.c:337
0x7f520d010780 handle_struct(void*, void*)
	/home/kje/example/example.c:20
0x8fb0b9 invoke_plugin_callbacks_full(int, void*)
	../../../gcc4.9/gcc/plugin.c:542
0x5e82b5 invoke_plugin_callbacks
	../../../gcc4.9/gcc/plugin.h:59
0x5e82b5 cp_parser_type_specifier
	../../../gcc4.9/gcc/cp/parser.c:14338
0x5fdbb0 cp_parser_decl_specifier_seq
	../../../gcc4.9/gcc/cp/parser.c:11573
0x602e79 cp_parser_simple_declaration
	../../../gcc4.9/gcc/cp/parser.c:11163
0x5ea903 cp_parser_block_declaration
	../../../gcc4.9/gcc/cp/parser.c:11112
0x5eb961 cp_parser_declaration_statement
	../../../gcc4.9/gcc/cp/parser.c:10759
0x5ebf9b cp_parser_statement
	../../../gcc4.9/gcc/cp/parser.c:9492
0x5ecdc9 cp_parser_statement_seq_opt
	../../../gcc4.9/gcc/cp/parser.c:9770
0x5ecf06 cp_parser_compound_statement
	../../../gcc4.9/gcc/cp/parser.c:9724
0x5fb7d3 cp_parser_function_body
	../../../gcc4.9/gcc/cp/parser.c:18751
0x5fb7d3 cp_parser_ctor_initializer_opt_and_function_body
	../../../gcc4.9/gcc/cp/parser.c:18787
0x601272 cp_parser_function_definition_after_declarator
	../../../gcc4.9/gcc/cp/parser.c:22912
0x6021ac cp_parser_function_definition_from_specifiers_and_declarator
	../../../gcc4.9/gcc/cp/parser.c:22824
0x6021ac cp_parser_init_declarator
	../../../gcc4.9/gcc/cp/parser.c:16634
0x603059 cp_parser_simple_declaration
	../../../gcc4.9/gcc/cp/parser.c:11231
0x5ea903 cp_parser_block_declaration
	../../../gcc4.9/gcc/cp/parser.c:11112
0x60a9c2 cp_parser_declaration
	../../../gcc4.9/gcc/cp/parser.c:11009
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

---
Comment 1 Manuel López-Ibáñez 2014-08-24 18:48:50 UTC
It seems it is your plugin crashing. Have you tried debugging why it crashes?

0x7f520d010780 handle_struct(void*, void*)
	/home/kje/example/example.c:20
0x8fb0b9 invoke_plugin_callbacks_full(int, void*)
Comment 2 klemen.jan.enova 2014-08-24 19:46:48 UTC
TREE_CODE(type) returns an ERROR_MARK. So, (tree) event_data must not alias with a tree. This plugin is from https://github.com/gcc-mirror/gcc/blob/master/gcc/testsuite/g%2B%2B.dg/plugin/dumb_plugin.c. There are no checks there, it just assumes it is a type represented as a tree.
Comment 3 klemen.jan.enova 2014-08-24 20:29:00 UTC
It works on gcc, though.

in gcc/c/c-parser.c:

>	  if (!typespec_ok)
>	    goto out;


>         invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
>	  declspecs_add_type (loc, specs, t);

in gcc/cp/parser.c:

>      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))
>	{
>	  if (declares_class_or_enum)
>	    *declares_class_or_enum = 2;
>	  if (decl_specs)
>	    cp_parser_set_decl_spec_type (decl_specs,
>					  type_spec,
>					  token,
>					  /*type_definition_p=*/true);
>	  return type_spec;
>	}


I see a pattern. The call to invoke_plugin_callbacks() should probably be before something_that_adds_the_type_to_decl_spec(). Also, there is a test in both cases (typespec_ok VS cp_parser_parse_definitely). I will try to compile gcc with this patch, and see what comes out.
Comment 4 klemen.jan.enova 2014-08-25 08:02:52 UTC
Created attachment 33391 [details]
cp-parser-patch

Fixes the bug. If I use debug_tree(type) in handle_struct(), it prints a RECORD_TYPE only once, because the type declaration and definition happens only once, other uses of the identifier "struct S" are variable declarations.
Comment 5 klemen.jan.enova 2014-08-25 12:40:09 UTC
The build passed make check, but I said invoke_plugin_callback() should be before cp_parser_set_decl_spec_type(), so I will try that way too.