This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]