diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3b9aa266bb2c6321bcabe58621605fb702cb0d0e..cfdd938fb3e0da82b8876fc0f6fc4198db159ef0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2010-07-23  Jan Hubicka  <jh@suse.cz>
+
+	* lto-streamer-out.c (write_symbol): Fix visibilities of external
+	references.
+
 2010-07-23  Le-Chun Wu  <lcwu@google.com>
 
 	* omega.c (omega_eliminate_redundant): Remove a self-assign statement.
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index c96c13aeefe6ca34bed1fe3a1f2c3c44067ce789..98d94428e57f67a36bc50ed061cd3b2afe1305c1 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2352,21 +2352,32 @@ write_symbol (struct lto_streamer_cache_d *cache,
 		      && cgraph_get_node (t)->analyzed));
     }
 
-  switch (DECL_VISIBILITY(t))
-    {
-    case VISIBILITY_DEFAULT:
-      visibility = GCCPV_DEFAULT;
-      break;
-    case VISIBILITY_PROTECTED:
-      visibility = GCCPV_PROTECTED;
-      break;
-    case VISIBILITY_HIDDEN:
-      visibility = GCCPV_HIDDEN;
-      break;
-    case VISIBILITY_INTERNAL:
-      visibility = GCCPV_INTERNAL;
-      break;
-    }
+  /* Imitate what default_elf_asm_output_external do.
+     When symbol is external, we need to output it with DEFAULT visibility
+     when compiling with -fvisibility=default, while with HIDDEN visibility
+     when symbol has attribute (visibility("hidden")) specified.
+     targetm.binds_local_p check DECL_VISIBILITY_SPECIFIED and gets this
+     right. */
+     
+  if (DECL_EXTERNAL (t)
+      && !targetm.binds_local_p (t))
+    visibility = GCCPV_DEFAULT;
+  else
+    switch (DECL_VISIBILITY(t))
+      {
+      case VISIBILITY_DEFAULT:
+	visibility = GCCPV_DEFAULT;
+	break;
+      case VISIBILITY_PROTECTED:
+	visibility = GCCPV_PROTECTED;
+	break;
+      case VISIBILITY_HIDDEN:
+	visibility = GCCPV_HIDDEN;
+	break;
+      case VISIBILITY_INTERNAL:
+	visibility = GCCPV_INTERNAL;
+	break;
+      }
 
   if (kind == GCCPK_COMMON
       && DECL_SIZE (t)