Index: testsuite/g++.dg/lto/v1-plugin-api-not-supported.C
===================================================================
--- testsuite/g++.dg/lto/v1-plugin-api-not-supported.C	(revision 0)
+++ testsuite/g++.dg/lto/v1-plugin-api-not-supported.C	(revision 0)
@@ -0,0 +1,59 @@
+// { dg-lto-do run }
+// { dg-require-linker-plugin "" }
+// { dg-lto-options {{-O2 -fuse-linker-plugin -fno-early-inlining}}
+
+extern "C" void abort (void);
+extern "C" void linker_error ();
+
+class A
+{
+public:
+  int data;
+  virtual int foo (int i)
+    {
+      return i + 1;
+    }
+};
+
+class B : public A
+{
+public:
+  virtual int foo (int i)
+    {
+      return i + 2;
+    }
+};
+
+class C : public A
+{
+public:
+  virtual int foo (int i)
+    {
+      linker_error ();
+      return i + 3;
+    }
+};
+
+
+static int middleman (class A *obj, int i)
+{
+  return obj->foo (i);
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+int main (int argc, char *argv[])
+{
+  class B b;
+  if (middleman (&b, get_input ()) != 3)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo"  "cp"  } } */
+/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 192154)
+++ lto-streamer-out.c	(working copy)
@@ -1285,11 +1287,9 @@ produce_symtab (struct output_block *ob)
   struct streamer_tree_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
   struct pointer_set_t *seen;
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
   struct lto_output_stream stream;
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
-  int i;
+  lto_symtab_encoder_iterator lsei;
 
   lto_begin_section (section_name, false);
   free (section_name);
@@ -1297,78 +1297,26 @@ produce_symtab (struct output_block *ob)
   seen = pointer_set_create ();
   memset (&stream, 0, sizeof (stream));
 
-  /* Write all functions. 
-     First write all defined functions and then write all used functions.
-     This is done so only to handle duplicated symbols in cgraph.  */
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  /* Write the symbol table.
+     First write everything defined and then all declarations.
+     This is neccesary to handle cases where we have duplicated symbols.  */
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (node->symbol.decl))
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
+      symtab_node node = lsei_node (lsei);
+
+      if (!symtab_real_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
 	continue;
       write_symbol (cache, &stream, node->symbol.decl, seen, false);
     }
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (node->symbol.decl))
-	continue;
-      /* We keep around unused extern inlines in order to be able to inline
-	 them indirectly or via vtables.  Do not output them to symbol
-	 table: they end up being undefined and just consume space.  */
-      if (!node->symbol.address_taken && !node->callers)
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
-	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
-    }
+      symtab_node node = lsei_node (lsei);
 
-  /* Write all variables.  */
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-    {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (vnode->symbol.decl))
-	continue;
-      /* COMDAT virtual tables can be unshared.  Do not declare them
-	 in the LTO symbol table to prevent linker from forcing them
-	 into the output. */
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized 
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
-    }
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-    {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (vnode->symbol.decl))
+      if (!symtab_real_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
 	continue;
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized 
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+      write_symbol (cache, &stream, node->symbol.decl, seen, false);
     }
 
   lto_write_stream (&stream);
