diff mbox

Do not output references from external vtables into LTO symbol table

Message ID 20130312124117.GA9858@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka March 12, 2013, 12:41 p.m. UTC
Hi,
this patch fixes GCC side of PR 56557 where we fail to link

#include <fstream>

int main()
{
  std::fstream x;
}

with -flto -rdynamic because we do not see definition of
_ZTCSt13basic_fstreamIcSt11char_traitsIcEE0_Sd.  This symbol mistakely appears
in lto symbol table because it is used from external constructor that is kept
around only for optimization.  There is also BFD linker bug that create stale
dynamic table entries for these kind of symbols.

Bootstrapped&regtested x86_64-linux, tested on Mozilla and Qt LTO build, comitted.

Honza

	PR lto/56557
	* lto-streamer-out.c (output_symbol_p): Skip references from
	constructors of external variables.
diff mbox

Patch

Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 196611)
+++ lto-streamer-out.c	(working copy)
@@ -1265,17 +1265,36 @@  bool
 output_symbol_p (symtab_node node)
 {
   struct cgraph_node *cnode;
-  struct ipa_ref *ref;
-
   if (!symtab_real_symbol_p (node))
     return false;
   /* We keep external functions in symtab for sake of inlining
      and devirtualization.  We do not want to see them in symbol table as
-     references.  */
+     references unless they are really used.  */
   cnode = dyn_cast <cgraph_node> (node);
-  if (cnode && DECL_EXTERNAL (cnode->symbol.decl))
-    return (cnode->callers
-	    || ipa_ref_list_referring_iterate (&cnode->symbol.ref_list, 0, ref));
+  if (cnode && DECL_EXTERNAL (cnode->symbol.decl)
+      && cnode->callers)
+    return true;
+
+ /* Ignore all references from external vars initializers - they are not really
+    part of the compilation unit until they are used by folding.  Some symbols,
+    like references to external construction vtables can not be referred to at all.
+    We decide this at can_refer_decl_in_current_unit_p.  */
+ if (DECL_EXTERNAL (node->symbol.decl))
+    {
+      int i;
+      struct ipa_ref *ref;
+      for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+					          i, ref); i++)
+	{
+	  if (ref->use == IPA_REF_ALIAS)
+	    continue;
+          if (is_a <cgraph_node> (ref->referring))
+	    return true;
+	  if (!DECL_EXTERNAL (ref->referring->symbol.decl))
+	    return true;
+	}
+      return false;
+    }
   return true;
 }