Fix can_refer_decl_in_current_unit_p wrt optimized out statics

Message ID
State New
Headers show

Commit Message

Jan Hubicka Sept. 16, 2013, 11:53 a.m.
this patch solves problem with can_refer_decl_in_current_unit_p always
returning true for static functions.  The devirtualization code can look
up a method in anonymous namespace that has been optimized out due to
lack of references to any of vtables mentioning it.  In this case we need
to make the methods as unreferable that I check by presence of cgraph node
in ipa-devirt.c.

It turns out that this is not enough - fold_ctor_reference constructs cgraph
nodes for functions not seen in symbol table and this may confuse LTO

This patch makes can_refer_decl_in_current_unit_p to do the right thing.
Incrementally I will check if I can now remove the construction of cgraph
nodes in fold_ctor_reference - I think virtual tables are the last case
where reference can come in a way not visible in symbol table and that
I am going to fix soon by making the vtables explicitely represented.
In any case we however should not try to invent refernece to already optimized
out static, so I am fixing it bellow.

I also added DECL_ABSTRACT check - abstrace methods may appear in external
vtables in case they has not been instantiated.  Trying to referr them is
going to fail.

Bootstrapped/regtested x86_64-linux, comitted.

	* gimple-fold.c (can_refer_decl_in_current_unit_p): Do not accept
	abstract functions; for static functions check the presence
	of body.


Index: gimple-fold.c
--- gimple-fold.c	(revision 202625)
+++ gimple-fold.c	(working copy)
@@ -60,6 +60,24 @@  can_refer_decl_in_current_unit_p (tree d
   struct cgraph_node *node;
   symtab_node snode;
+  if (DECL_ABSTRACT (decl))
+    return false;
+  /* We are concerned only about static/external vars and functions.  */
+  if ((!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+      || (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL))
+    return true;
+  /* Static objects can be referred only if they was not optimized out yet.  */
+  if (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
+    {
+      snode = symtab_get_node (decl);
+      if (!snode)
+	return false;
+      node = dyn_cast <cgraph_node> (snode);
+      return !node || !node->global.inlined_to;
+    }
   /* We will later output the initializer, so we can refer to it.
      So we are concerned only when DECL comes from initializer of
      external var.  */
@@ -69,10 +87,6 @@  can_refer_decl_in_current_unit_p (tree d
       || (flag_ltrans
 	  && symtab_get_node (from_decl)->symbol.in_other_partition))
     return true;
-  /* We are concerned only about static/external vars and functions.  */
-  if ((!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
-      || (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL))
-    return true;
   /* We are folding reference from external vtable.  The vtable may reffer
      to a symbol keyed to other compilation unit.  The other compilation
      unit may be in separate DSO and the symbol may be hidden.  */