This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR41257
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 4 Sep 2009 20:49:25 +0200 (CEST)
- Subject: [PATCH] Fix PR41257
This fixes PR41257 - we were removing functions from the cgraph even
though a vtable still referenced it via an alias. Fixed by moving
finish_aliases_1 earlier, before removing any cgraph nodes.
The patch also includes a small cleanup - move emitting things before
the first analysis phase. I also needed to adjust the check that
identifies C++ thunk aliases - but in the end with gimplification
unit-at-a-time we should be able to promote the alias-pairs to
full featured cgraph nodes and edges. Not something for me though.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
PR middle-end/41257
* (cgraph_finalize_compilation_unit): Move finalizing aliases
after emitting tunks. Move emitting thunks and ctors from ...
(cgraph_optimize): ... here. Remove redundant
cgraph_analyze_functions.
* varasm.c (find_decl_and_mark_needed): Remove no longer
necessary check.
(finish_aliases_1): Adjust check for thunk aliases.
* g++.dg/torture/pr41257.C: New testcase.
Index: gcc/varasm.c
===================================================================
*** gcc/varasm.c (revision 151419)
--- gcc/varasm.c (working copy)
*************** find_decl_and_mark_needed (tree decl, tr
*** 5395,5407 ****
if (fnode)
{
! /* We can't mark function nodes as used after cgraph global info
! is finished. This wouldn't generally be necessary, but C++
! virtual table thunks are introduced late in the game and
! might seem like they need marking, although in fact they
! don't. */
! if (! cgraph_global_info_ready)
! cgraph_mark_needed_node (fnode);
return fnode->decl;
}
else if (vnode)
--- 5395,5401 ----
if (fnode)
{
! cgraph_mark_needed_node (fnode);
return fnode->decl;
}
else if (vnode)
*************** finish_aliases_1 (void)
*** 5571,5577 ****
to bind locally. Of course this is a hack - to keep it
working do the following (which is not strictly correct). */
&& (! TREE_CODE (target_decl) == FUNCTION_DECL
! || ! TREE_STATIC (target_decl))
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
error ("%q+D aliased to external symbol %qE",
p->decl, p->target);
--- 5565,5571 ----
to bind locally. Of course this is a hack - to keep it
working do the following (which is not strictly correct). */
&& (! TREE_CODE (target_decl) == FUNCTION_DECL
! || ! DECL_VIRTUAL_P (target_decl))
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
error ("%q+D aliased to external symbol %qE",
p->decl, p->target);
Index: gcc/testsuite/g++.dg/torture/pr41257.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr41257.C (revision 0)
--- gcc/testsuite/g++.dg/torture/pr41257.C (revision 0)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+
+ struct A
+ {
+ virtual void foo();
+ virtual ~A();
+ int i;
+ };
+
+ struct B : virtual A {};
+
+ struct C : B
+ {
+ virtual void foo();
+ };
+
+ void bar()
+ {
+ C().foo();
+ }
Index: gcc/cgraphunit.c
===================================================================
*** gcc/cgraphunit.c (revision 151419)
--- gcc/cgraphunit.c (working copy)
*************** cgraph_analyze_functions (void)
*** 1018,1023 ****
--- 1018,1047 ----
ggc_collect ();
}
+
+ /* Emit thunks for every node in the cgraph.
+ FIXME: We really ought to emit thunks only for functions that are needed. */
+
+ static void
+ cgraph_emit_thunks (void)
+ {
+ struct cgraph_node *n;
+
+ for (n = cgraph_nodes; n; n = n->next)
+ {
+ /* Only emit thunks on functions defined in this TU.
+ Note that this may emit more thunks than strictly necessary.
+ During optimization some nodes may disappear. It would be
+ nice to only emit thunks only for the functions that will be
+ emitted, but we cannot know that until the inliner and other
+ IPA passes have run (see the sequencing of the call to
+ cgraph_mark_functions_to_output in cgraph_optimize). */
+ if (!DECL_EXTERNAL (n->decl))
+ lang_hooks.callgraph.emit_associated_thunks (n->decl);
+ }
+ }
+
+
/* Analyze the whole compilation unit once it is parsed completely. */
void
*************** cgraph_finalize_compilation_unit (void)
*** 1026,1033 ****
/* Do not skip analyzing the functions if there were errors, we
miss diagnostics for following functions otherwise. */
finalize_size_functions ();
! finish_aliases_1 ();
if (!quiet_flag)
{
--- 1050,1065 ----
/* Do not skip analyzing the functions if there were errors, we
miss diagnostics for following functions otherwise. */
+ /* Emit size functions we didn't inline. */
finalize_size_functions ();
!
! /* Emit thunks, if needed. */
! if (lang_hooks.callgraph.emit_associated_thunks)
! cgraph_emit_thunks ();
!
! /* Call functions declared with the "constructor" or "destructor"
! attribute. */
! cgraph_build_cdtor_fns ();
if (!quiet_flag)
{
*************** cgraph_finalize_compilation_unit (void)
*** 1035,1040 ****
--- 1067,1076 ----
fflush (stderr);
}
+ /* Mark alias targets necessary and emit diagnostics. */
+ finish_aliases_1 ();
+
+ /* Gimplify and lower all functions. */
timevar_push (TV_CGRAPH);
cgraph_analyze_functions ();
timevar_pop (TV_CGRAPH);
*************** ipa_passes (void)
*** 1322,1350 ****
}
- /* Emit thunks for every node in the cgraph.
- FIXME: We really ought to emit thunks only for functions that are needed. */
-
- static void
- cgraph_emit_thunks (void)
- {
- struct cgraph_node *n;
-
- for (n = cgraph_nodes; n; n = n->next)
- {
- /* Only emit thunks on functions defined in this TU.
- Note that this may emit more thunks than strictly necessary.
- During optimization some nodes may disappear. It would be
- nice to only emit thunks only for the functions that will be
- emitted, but we cannot know that until the inliner and other
- IPA passes have run (see the sequencing of the call to
- cgraph_mark_functions_to_output in cgraph_optimize). */
- if (!DECL_EXTERNAL (n->decl))
- lang_hooks.callgraph.emit_associated_thunks (n->decl);
- }
- }
-
-
/* Perform simple optimizations based on callgraph. */
static void
--- 1358,1363 ----
*************** cgraph_optimize (void)
*** 1357,1378 ****
verify_cgraph ();
#endif
- /* Emit thunks, if needed. */
- if (lang_hooks.callgraph.emit_associated_thunks)
- {
- cgraph_emit_thunks ();
- if (errorcount || sorrycount)
- return;
- }
-
- /* Call functions declared with the "constructor" or "destructor"
- attribute. */
- cgraph_build_cdtor_fns ();
-
/* Frontend may output common variables after the unit has been finalized.
It is safe to deal with them here as they are always zero initialized. */
varpool_analyze_pending_decls ();
- cgraph_analyze_functions ();
timevar_push (TV_CGRAPHOPT);
if (pre_ipa_mem_report)
--- 1370,1378 ----