diff mbox

PR rtl-optimization/32219: optimizer causes wrong code in pic/hidden/weak symbol checking

Message ID 20150206162314.GA12597@intel.com
State New
Headers show

Commit Message

H.J. Lu Feb. 6, 2015, 4:23 p.m. UTC
If a hidden weak symbol isn't defined in the TU, we can't assume it will
be defined in another TU at link time.  It makes a difference in code
generation when compiling for PIC. If we assume that a hidden weak
undefined symbol is local, the address checking may be optimized out and
leads to the wrong code.  This means that a symbol with user specified
visibility is local only if it is locally resolved or defined, not weak
or not compiling for PIC.  When symbol visibility is specified in the
source, we should always output symbol visibility even if symbol isn't
local to the TU.

If a global data symbol is defined in the TU, it is always local to the
executable, regardless if it is a common symbol or not.  If we aren't
compiling for shared library, locally defined global data symbol binds
locally.

Tested on Linux/x86-64.  OK for trunk?

Thanks.


H.J.
---
gcc/

	PR rtl-optimization/32219
	* cgraphunit.c (varpool_node::finalize_decl): Set definition
	first before calling notice_global_symbol so that it is
	available to notice_global_symbol.
	* varasm.c (default_binds_local_p_1): Resolve defined data
	symbol locally if not building shared library.  Resolve symbol
	with user specified visibility locally only if it is locally
	resolved or defined, not weak or not compiling for PIC.
	(default_elf_asm_output_external): Always output visibility
	specified in the source.

gcc/testsuite/

	PR rtl-optimization/32219
	* gcc.dg/visibility-22.c: New test.
	* gcc.dg/visibility-23.c: Likewise.
	* gcc.target/i386/pr32219-1.c: Likewise.
	* gcc.target/i386/pr32219-2.c: Likewise.
	* gcc.target/i386/pr32219-3.c: Likewise.
	* gcc.target/i386/pr32219-4.c: Likewise.
	* gcc.target/i386/pr32219-5.c: Likewise.
	* gcc.target/i386/pr32219-6.c: Likewise.
	* gcc.target/i386/pr32219-7.c: Likewise.
	* gcc.target/i386/pr32219-8.c: Likewise.
	* gcc.target/i386/pr64317.c: Expect GOTOFF relocation instead
	of GOT relocation.
---
 gcc/cgraphunit.c                          |  4 +++-
 gcc/testsuite/gcc.dg/visibility-22.c      | 14 +++++++++++++
 gcc/testsuite/gcc.dg/visibility-23.c      | 15 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-1.c | 16 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-2.c | 16 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-3.c | 17 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-4.c | 17 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-5.c | 16 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-6.c | 16 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-7.c | 17 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-8.c | 17 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr64317.c   |  2 +-
 gcc/varasm.c                              | 35 ++++++++++++++++++-------------
 13 files changed, 185 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/visibility-22.c
 create mode 100644 gcc/testsuite/gcc.dg/visibility-23.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-7.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-8.c

Comments

Jack Howarth Feb. 6, 2015, 9:31 p.m. UTC | #1
H.J.,
    On x86_64-apple-darwin14, your patch applied to r220481 results in...

FAIL: gcc.dg/visibility-22.c (test for excess errors)
FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo

with...

Executing on host:
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
 -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
-m32  -o ./visibility-22.exe    (timeout = 300)
spawn -ignore SIGHUP
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
-fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
-o ./visibility-22.exe^M
Undefined symbols for architecture i386:^M
  "_foo", referenced from:^M
      _main in ccMD1qjz.o^M
      _main in ccMD1qjz.o^M
ld: symbol(s) not found for architecture i386^M
collect2: error: ld returned 1 exit status^M
compiler exited with status 1
output is:
Undefined symbols for architecture i386:^M
  "_foo", referenced from:^M
      _main in ccMD1qjz.o^M
      _main in ccMD1qjz.o^M
ld: symbol(s) not found for architecture i386^M
collect2: error: ld returned 1 exit status^M

FAIL: gcc.dg/visibility-22.c (test for excess errors)

Executing on host:
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
 -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
-m32  -o visibility-23.s    (timeout = 300)
spawn -ignore SIGHUP
/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
-fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
visibility-23.s^M
PASS: gcc.dg/visibility-23.c (test for excess errors)
FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo

        Jack

On Fri, Feb 6, 2015 at 11:23 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> If a hidden weak symbol isn't defined in the TU, we can't assume it will
> be defined in another TU at link time.  It makes a difference in code
> generation when compiling for PIC. If we assume that a hidden weak
> undefined symbol is local, the address checking may be optimized out and
> leads to the wrong code.  This means that a symbol with user specified
> visibility is local only if it is locally resolved or defined, not weak
> or not compiling for PIC.  When symbol visibility is specified in the
> source, we should always output symbol visibility even if symbol isn't
> local to the TU.
>
> If a global data symbol is defined in the TU, it is always local to the
> executable, regardless if it is a common symbol or not.  If we aren't
> compiling for shared library, locally defined global data symbol binds
> locally.
>
> Tested on Linux/x86-64.  OK for trunk?
>
> Thanks.
>
>
> H.J.
> ---
> gcc/
>
>         PR rtl-optimization/32219
>         * cgraphunit.c (varpool_node::finalize_decl): Set definition
>         first before calling notice_global_symbol so that it is
>         available to notice_global_symbol.
>         * varasm.c (default_binds_local_p_1): Resolve defined data
>         symbol locally if not building shared library.  Resolve symbol
>         with user specified visibility locally only if it is locally
>         resolved or defined, not weak or not compiling for PIC.
>         (default_elf_asm_output_external): Always output visibility
>         specified in the source.
>
> gcc/testsuite/
>
>         PR rtl-optimization/32219
>         * gcc.dg/visibility-22.c: New test.
>         * gcc.dg/visibility-23.c: Likewise.
>         * gcc.target/i386/pr32219-1.c: Likewise.
>         * gcc.target/i386/pr32219-2.c: Likewise.
>         * gcc.target/i386/pr32219-3.c: Likewise.
>         * gcc.target/i386/pr32219-4.c: Likewise.
>         * gcc.target/i386/pr32219-5.c: Likewise.
>         * gcc.target/i386/pr32219-6.c: Likewise.
>         * gcc.target/i386/pr32219-7.c: Likewise.
>         * gcc.target/i386/pr32219-8.c: Likewise.
>         * gcc.target/i386/pr64317.c: Expect GOTOFF relocation instead
>         of GOT relocation.
> ---
>  gcc/cgraphunit.c                          |  4 +++-
>  gcc/testsuite/gcc.dg/visibility-22.c      | 14 +++++++++++++
>  gcc/testsuite/gcc.dg/visibility-23.c      | 15 +++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-1.c | 16 ++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-2.c | 16 ++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-3.c | 17 +++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-4.c | 17 +++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-5.c | 16 ++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-6.c | 16 ++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-7.c | 17 +++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr32219-8.c | 17 +++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr64317.c   |  2 +-
>  gcc/varasm.c                              | 35 ++++++++++++++++++-------------
>  13 files changed, 185 insertions(+), 17 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/visibility-22.c
>  create mode 100644 gcc/testsuite/gcc.dg/visibility-23.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-1.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-2.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-3.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-4.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-5.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-6.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-7.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-8.c
>
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index a2650f7..e1a6e41 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -792,8 +792,10 @@ varpool_node::finalize_decl (tree decl)
>
>    if (node->definition)
>      return;
> -  notice_global_symbol (decl);
> +  /* Set definition first before calling notice_global_symbol so that
> +     it is available to notice_global_symbol.  */
>    node->definition = true;
> +  notice_global_symbol (decl);
>    if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
>        /* Traditionally we do not eliminate static variables when not
>          optimizing and when not doing toplevel reoder.  */
> diff --git a/gcc/testsuite/gcc.dg/visibility-22.c b/gcc/testsuite/gcc.dg/visibility-22.c
> new file mode 100644
> index 0000000..30087de
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/visibility-22.c
> @@ -0,0 +1,14 @@
> +/* PR target/32219 */
> +/* { dg-do run } */
> +/* { dg-require-visibility "" } */
> +/* { dg-options "-fPIC" { target fpic } } */
> +
> +extern void foo () __attribute__((weak,visibility("hidden")));
> +int
> +main()
> +{
> +  if (foo)
> +    foo ();
> +  return 0;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/visibility-23.c b/gcc/testsuite/gcc.dg/visibility-23.c
> new file mode 100644
> index 0000000..070493f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/visibility-23.c
> @@ -0,0 +1,15 @@
> +/* PR target/32219 */
> +/* { dg-do compile } */
> +/* { dg-require-visibility "" } */
> +/* { dg-final { scan-hidden "foo" } } */
> +/* { dg-options "-fPIC" { target fpic } } */
> +
> +extern void foo () __attribute__((weak,visibility("hidden")));
> +int
> +main()
> +{
> +  if (foo)
> +    foo ();
> +  return 0;
> +}
> +
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
> new file mode 100644
> index 0000000..5bd80a0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpie" } */
> +
> +/* Common symbol with -fpie.  */
> +int xxx;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c
> new file mode 100644
> index 0000000..0cf2eb5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic" } */
> +
> +/* Common symbol with -fpic.  */
> +int xxx;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-3.c b/gcc/testsuite/gcc.target/i386/pr32219-3.c
> new file mode 100644
> index 0000000..911f2a5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-3.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpie" } */
> +
> +/* Weak common symbol with -fpie.  */
> +__attribute__((weak))
> +int xxx;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-4.c b/gcc/testsuite/gcc.target/i386/pr32219-4.c
> new file mode 100644
> index 0000000..3d43439
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-4.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic" } */
> +
> +/* Weak common symbol with -fpic.  */
> +__attribute__((weak))
> +int xxx;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-5.c b/gcc/testsuite/gcc.target/i386/pr32219-5.c
> new file mode 100644
> index 0000000..ee7442e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-5.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpie" } */
> +
> +/* Initialized symbol with -fpie.  */
> +int xxx = -1;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-6.c b/gcc/testsuite/gcc.target/i386/pr32219-6.c
> new file mode 100644
> index 0000000..f261433
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-6.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic" } */
> +
> +/* Initialized symbol with -fpic.  */
> +int xxx = -1;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-7.c b/gcc/testsuite/gcc.target/i386/pr32219-7.c
> new file mode 100644
> index 0000000..12aaf72
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-7.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpie" } */
> +
> +/* Weak initialized symbol with -fpie.  */
> +__attribute__((weak))
> +int xxx = -1;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr32219-8.c b/gcc/testsuite/gcc.target/i386/pr32219-8.c
> new file mode 100644
> index 0000000..2e4fba0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr32219-8.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic" } */
> +
> +/* Weak initialized symbol with -fpic.  */
> +__attribute__((weak))
> +int xxx = -1;
> +
> +int
> +foo ()
> +{
> +  return xxx;
> +}
> +
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
> index 46c3c6f..a23e996 100644
> --- a/gcc/testsuite/gcc.target/i386/pr64317.c
> +++ b/gcc/testsuite/gcc.target/i386/pr64317.c
> @@ -1,7 +1,7 @@
>  /* { dg-do compile { target { ia32 } } } */
>  /* { dg-options "-O2 -fPIE -pie" } */
>  /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
> -/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */
> +/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
>  /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
>  long c;
>
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index eb65b1f..f7c13af 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -6826,11 +6826,17 @@ default_binds_local_p_1 (const_tree exp, int shlib)
>        && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
>      {
>        varpool_node *vnode = varpool_node::get (exp);
> -      if (vnode && (resolution_local_p (vnode->resolution) || vnode->in_other_partition))
> -       resolved_locally = true;
> -      if (vnode
> -         && resolution_to_local_definition_p (vnode->resolution))
> -       resolved_to_local_def = true;
> +      /* If not building shared library, common or initialized symbols
> +        are also resolved locally, regardless they are weak or not.  */
> +      if (vnode)
> +       {
> +         if ((!shlib && vnode->definition)
> +             || vnode->in_other_partition
> +             || resolution_local_p (vnode->resolution))
> +           resolved_locally = true;
> +         if (resolution_to_local_definition_p (vnode->resolution))
> +           resolved_to_local_def = true;
> +       }
>      }
>    else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
>      {
> @@ -6859,9 +6865,14 @@ default_binds_local_p_1 (const_tree exp, int shlib)
>    else if (! TREE_PUBLIC (exp))
>      local_p = true;
>    /* A variable is local if the user has said explicitly that it will
> -     be.  */
> +     be and it is resolved or defined locally, not compiling for PIC or
> +     not weak.  */
>    else if ((DECL_VISIBILITY_SPECIFIED (exp)
>             || resolved_to_local_def)
> +          && (resolved_locally
> +              || !flag_pic
> +              || !DECL_EXTERNAL (exp)
> +              || !DECL_WEAK (exp))
>            && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
>      local_p = true;
>    /* Variables defined outside this object might not be local.  */
> @@ -6880,13 +6891,6 @@ default_binds_local_p_1 (const_tree exp, int shlib)
>       symbols resolved from other modules.  */
>    else if (shlib)
>      local_p = false;
> -  /* Uninitialized COMMON variable may be unified with symbols
> -     resolved from other modules.  */
> -  else if (DECL_COMMON (exp)
> -          && !resolved_locally
> -          && (DECL_INITIAL (exp) == NULL
> -              || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
> -    local_p = false;
>    /* Otherwise we're left with initialized (or non-common) global data
>       which is of necessity defined locally.  */
>    else
> @@ -7445,9 +7449,10 @@ default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
>  {
>    /* We output the name if and only if TREE_SYMBOL_REFERENCED is
>       set in order to avoid putting out names that are never really
> -     used. */
> +     used.   Always output visibility specified in the source.  */
>    if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
> -      && targetm.binds_local_p (decl))
> +      && (DECL_VISIBILITY_SPECIFIED (decl)
> +         || targetm.binds_local_p (decl)))
>      maybe_assemble_visibility (decl);
>  }
>
> --
> 1.9.3
>
H.J. Lu Feb. 6, 2015, 9:41 p.m. UTC | #2
On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
> H.J.,
>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>
> FAIL: gcc.dg/visibility-22.c (test for excess errors)
> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>
> with...
>
> Executing on host:
> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
> -m32  -o ./visibility-22.exe    (timeout = 300)
> spawn -ignore SIGHUP
> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
> -o ./visibility-22.exe^M
> Undefined symbols for architecture i386:^M
>   "_foo", referenced from:^M
>       _main in ccMD1qjz.o^M
>       _main in ccMD1qjz.o^M
> ld: symbol(s) not found for architecture i386^M
> collect2: error: ld returned 1 exit status^M
> compiler exited with status 1
> output is:
> Undefined symbols for architecture i386:^M
>   "_foo", referenced from:^M
>       _main in ccMD1qjz.o^M
>       _main in ccMD1qjz.o^M
> ld: symbol(s) not found for architecture i386^M
> collect2: error: ld returned 1 exit status^M
>
> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>
> Executing on host:
> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
> -m32  -o visibility-23.s    (timeout = 300)
> spawn -ignore SIGHUP
> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
> visibility-23.s^M
> PASS: gcc.dg/visibility-23.c (test for excess errors)
> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>

Does Darwin support undefined hidden weak symbol?
Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
with clang on Darwin?
Jack Howarth Feb. 6, 2015, 9:51 p.m. UTC | #3
H.J.,
     The clang compilers exhibit the same behavior on these test cases.

Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      _main in visibility-23-e1e564.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

however if I also pass "-Wl,-undefined -Wl,dynamic_lookup" to the
linker, both test
compile and run.
     FYI, the assembly from...

/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
-B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
-fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
visibility-23.s

contains...

        .text
        .globl _main
_main:
LFB0:
        pushl   %ebp
LCFI0:
        movl    %esp, %ebp
LCFI1:
        subl    $8, %esp
        call    ___x86.get_pc_thunk.ax
L1$pb:
        leal    L_foo$non_lazy_ptr-L1$pb(%eax), %eax
        movl    (%eax), %eax
        testl   %eax, %eax
        je      L2
        call    _foo
L2:
        movl    $0, %eax
        leave
LCFI2:
        ret
LFE0:
        .weak_reference _foo
        .section __TEXT,__textcoal_nt,coalesced,pure_instructions
        .weak_definition        ___x86.get_pc_thunk.ax
        .private_extern ___x86.get_pc_thunk.ax
___x86.get_pc_thunk.ax:
LFB1:
        movl    (%esp), %eax
        ret
LFE1:
        .section
__TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
        .set L$set$0,LECIE1-LSCIE1
        .long L$set$0
LSCIE1:
        .long   0
        .byte   0x1
        .ascii "zR\0"
        .byte   0x1
        .byte   0x7c
        .byte   0x8
        .byte   0x1
        .byte   0x10
        .byte   0xc
        .byte   0x5
        .byte   0x4
        .byte   0x88
        .byte   0x1
        .align 2
LECIE1:
LSFDE1:
        .set L$set$1,LEFDE1-LASFDE1
        .long L$set$1
LASFDE1:
        .long   LASFDE1-EH_frame1
        .long   LFB0-.
        .set L$set$2,LFE0-LFB0
        .long L$set$2
        .byte   0
        .byte   0x4
        .set L$set$3,LCFI0-LFB0
        .long L$set$3
        .byte   0xe
        .byte   0x8
        .byte   0x84
        .byte   0x2
        .byte   0x4
        .set L$set$4,LCFI1-LCFI0
        .long L$set$4
        .byte   0xd
        .byte   0x4
        .byte   0x4
        .set L$set$5,LCFI2-LCFI1
        .long L$set$5
        .byte   0xc4
        .byte   0xc
        .byte   0x5
        .byte   0x4
        .align 2
LEFDE1:
LSFDE3:
        .set L$set$6,LEFDE3-LASFDE3
        .long L$set$6
LASFDE3:
        .long   LASFDE3-EH_frame1
        .long   LFB1-.
        .set L$set$7,LFE1-LFB1
        .long L$set$7
        .byte   0
        .align 2
LEFDE3:
        .section __IMPORT,__pointers,non_lazy_symbol_pointers
        .weak_reference _foo
L_foo$non_lazy_ptr:
        .indirect_symbol _foo
        .long   0
        .subsections_via_symbols


On Fri, Feb 6, 2015 at 4:41 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>> H.J.,
>>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>>
>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>
>> with...
>>
>> Executing on host:
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
>> -m32  -o ./visibility-22.exe    (timeout = 300)
>> spawn -ignore SIGHUP
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
>> -o ./visibility-22.exe^M
>> Undefined symbols for architecture i386:^M
>>   "_foo", referenced from:^M
>>       _main in ccMD1qjz.o^M
>>       _main in ccMD1qjz.o^M
>> ld: symbol(s) not found for architecture i386^M
>> collect2: error: ld returned 1 exit status^M
>> compiler exited with status 1
>> output is:
>> Undefined symbols for architecture i386:^M
>>   "_foo", referenced from:^M
>>       _main in ccMD1qjz.o^M
>>       _main in ccMD1qjz.o^M
>> ld: symbol(s) not found for architecture i386^M
>> collect2: error: ld returned 1 exit status^M
>>
>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>
>> Executing on host:
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
>> -m32  -o visibility-23.s    (timeout = 300)
>> spawn -ignore SIGHUP
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
>> visibility-23.s^M
>> PASS: gcc.dg/visibility-23.c (test for excess errors)
>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>
>
> Does Darwin support undefined hidden weak symbol?
> Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
> with clang on Darwin?
>
> --
> H.J.
H.J. Lu Feb. 7, 2015, 1:50 a.m. UTC | #4
On Fri, Feb 6, 2015 at 1:51 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
> H.J.,
>      The clang compilers exhibit the same behavior on these test cases.
>
> Undefined symbols for architecture x86_64:
>   "_foo", referenced from:
>       _main in visibility-23-e1e564.o
> ld: symbol(s) not found for architecture x86_64
> clang: error: linker command failed with exit code 1 (use -v to see invocation)
>
> however if I also pass "-Wl,-undefined -Wl,dynamic_lookup" to the
> linker, both test
> compile and run.
>      FYI, the assembly from...
>
> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
> visibility-23.s

Can you give my updated patch:

https://gcc.gnu.org/git/?p=gcc.git;a=patch;h=81a3a94c146950d489e30d07161f6df47959ae7a

a try?

Thanks.
Jack Howarth Feb. 7, 2015, 1:51 a.m. UTC | #5
H.J.,
     This patch also seems to be causing a huge number of regressions
in the g++ test suite due to linkage warnings on darwin of the form...

ld: warning: direct access in Model::~Model() to global weak symbol
vtable for Model means the weak symbol cannot be overridden at
runtime. This was likely caused by different translation units being
compiled with different visibility settings.

Can this change wait until stage1?
            Jack

On Fri, Feb 6, 2015 at 4:41 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>> H.J.,
>>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>>
>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>
>> with...
>>
>> Executing on host:
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
>> -m32  -o ./visibility-22.exe    (timeout = 300)
>> spawn -ignore SIGHUP
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
>> -o ./visibility-22.exe^M
>> Undefined symbols for architecture i386:^M
>>   "_foo", referenced from:^M
>>       _main in ccMD1qjz.o^M
>>       _main in ccMD1qjz.o^M
>> ld: symbol(s) not found for architecture i386^M
>> collect2: error: ld returned 1 exit status^M
>> compiler exited with status 1
>> output is:
>> Undefined symbols for architecture i386:^M
>>   "_foo", referenced from:^M
>>       _main in ccMD1qjz.o^M
>>       _main in ccMD1qjz.o^M
>> ld: symbol(s) not found for architecture i386^M
>> collect2: error: ld returned 1 exit status^M
>>
>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>
>> Executing on host:
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
>> -m32  -o visibility-23.s    (timeout = 300)
>> spawn -ignore SIGHUP
>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
>> visibility-23.s^M
>> PASS: gcc.dg/visibility-23.c (test for excess errors)
>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>
>
> Does Darwin support undefined hidden weak symbol?
> Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
> with clang on Darwin?
>
> --
> H.J.
H.J. Lu Feb. 7, 2015, 1:55 a.m. UTC | #6
On Fri, Feb 6, 2015 at 5:51 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
> H.J.,
>      This patch also seems to be causing a huge number of regressions
> in the g++ test suite due to linkage warnings on darwin of the form...
>
> ld: warning: direct access in Model::~Model() to global weak symbol
> vtable for Model means the weak symbol cannot be overridden at
> runtime. This was likely caused by different translation units being
> compiled with different visibility settings.

Can you try my new patch?

> Can this change wait until stage1?
>             Jack
>
> On Fri, Feb 6, 2015 at 4:41 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>>> H.J.,
>>>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>>>
>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>
>>> with...
>>>
>>> Executing on host:
>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
>>> -m32  -o ./visibility-22.exe    (timeout = 300)
>>> spawn -ignore SIGHUP
>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
>>> -o ./visibility-22.exe^M
>>> Undefined symbols for architecture i386:^M
>>>   "_foo", referenced from:^M
>>>       _main in ccMD1qjz.o^M
>>>       _main in ccMD1qjz.o^M
>>> ld: symbol(s) not found for architecture i386^M
>>> collect2: error: ld returned 1 exit status^M
>>> compiler exited with status 1
>>> output is:
>>> Undefined symbols for architecture i386:^M
>>>   "_foo", referenced from:^M
>>>       _main in ccMD1qjz.o^M
>>>       _main in ccMD1qjz.o^M
>>> ld: symbol(s) not found for architecture i386^M
>>> collect2: error: ld returned 1 exit status^M
>>>
>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>>
>>> Executing on host:
>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
>>> -m32  -o visibility-23.s    (timeout = 300)
>>> spawn -ignore SIGHUP
>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
>>> visibility-23.s^M
>>> PASS: gcc.dg/visibility-23.c (test for excess errors)
>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>
>>
>> Does Darwin support undefined hidden weak symbol?
>> Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
>> with clang on Darwin?
>>
>> --
>> H.J.
Jack Howarth Feb. 7, 2015, 2:25 a.m. UTC | #7
H.J.,
    Where is this new patch?
              Jack

On Fri, Feb 6, 2015 at 8:55 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Feb 6, 2015 at 5:51 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>> H.J.,
>>      This patch also seems to be causing a huge number of regressions
>> in the g++ test suite due to linkage warnings on darwin of the form...
>>
>> ld: warning: direct access in Model::~Model() to global weak symbol
>> vtable for Model means the weak symbol cannot be overridden at
>> runtime. This was likely caused by different translation units being
>> compiled with different visibility settings.
>
> Can you try my new patch?
>
>> Can this change wait until stage1?
>>             Jack
>>
>> On Fri, Feb 6, 2015 at 4:41 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>>>> H.J.,
>>>>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>>>>
>>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>>
>>>> with...
>>>>
>>>> Executing on host:
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
>>>> -m32  -o ./visibility-22.exe    (timeout = 300)
>>>> spawn -ignore SIGHUP
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
>>>> -o ./visibility-22.exe^M
>>>> Undefined symbols for architecture i386:^M
>>>>   "_foo", referenced from:^M
>>>>       _main in ccMD1qjz.o^M
>>>>       _main in ccMD1qjz.o^M
>>>> ld: symbol(s) not found for architecture i386^M
>>>> collect2: error: ld returned 1 exit status^M
>>>> compiler exited with status 1
>>>> output is:
>>>> Undefined symbols for architecture i386:^M
>>>>   "_foo", referenced from:^M
>>>>       _main in ccMD1qjz.o^M
>>>>       _main in ccMD1qjz.o^M
>>>> ld: symbol(s) not found for architecture i386^M
>>>> collect2: error: ld returned 1 exit status^M
>>>>
>>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>>>
>>>> Executing on host:
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
>>>> -m32  -o visibility-23.s    (timeout = 300)
>>>> spawn -ignore SIGHUP
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
>>>> visibility-23.s^M
>>>> PASS: gcc.dg/visibility-23.c (test for excess errors)
>>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>>
>>>
>>> Does Darwin support undefined hidden weak symbol?
>>> Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
>>> with clang on Darwin?
>>>
>>> --
>>> H.J.
>
>
>
> --
> H.J.
Jack Howarth Feb. 7, 2015, 8:28 a.m. UTC | #8
H.J.,
     The new patch bootstraps okay on x86_64-apple-darwin14 but I
discovered that you need a small adjustment in the deja-gnu
statements...

 --- /Users/howarth/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
2015-02-06 21:45:04.000000000 -0500
+++ /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
2015-02-07 03:24:42.000000000 -0500
@@ -8,9 +8,9 @@
 /* For kernel modules and static RTPs, the loader treats undefined weak
    symbols in the same way as undefined strong symbols.  The test
    therefore fails to load, so skip it.  */
+/* { dg-options "-fPIC" { target fpic } } */
 /* { dg-additional-options "-Wl,-undefined,dynamic_lookup" { target
*-*-darwin* } } */
 /* { dg-additional-options "-Wl,-flat_namespace" { target
*-*-darwin[89]* } } */
-/* { dg-options "-fPIC" { target fpic } } */

 extern void foo () __attribute__((weak,visibility("hidden")));
 int

If you don't define a dg-options line first, the dg-additional-options
lines have no effect.
                 Jack

On Fri, Feb 6, 2015 at 8:55 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Feb 6, 2015 at 5:51 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>> H.J.,
>>      This patch also seems to be causing a huge number of regressions
>> in the g++ test suite due to linkage warnings on darwin of the form...
>>
>> ld: warning: direct access in Model::~Model() to global weak symbol
>> vtable for Model means the weak symbol cannot be overridden at
>> runtime. This was likely caused by different translation units being
>> compiled with different visibility settings.
>
> Can you try my new patch?
>
>> Can this change wait until stage1?
>>             Jack
>>
>> On Fri, Feb 6, 2015 at 4:41 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Fri, Feb 6, 2015 at 1:31 PM, Jack Howarth <howarth.at.gcc@gmail.com> wrote:
>>>> H.J.,
>>>>     On x86_64-apple-darwin14, your patch applied to r220481 results in...
>>>>
>>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>>
>>>> with...
>>>>
>>>> Executing on host:
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC  -lm
>>>> -m32  -o ./visibility-22.exe    (timeout = 300)
>>>> spawn -ignore SIGHUP
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-22.c
>>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -lm -m32
>>>> -o ./visibility-22.exe^M
>>>> Undefined symbols for architecture i386:^M
>>>>   "_foo", referenced from:^M
>>>>       _main in ccMD1qjz.o^M
>>>>       _main in ccMD1qjz.o^M
>>>> ld: symbol(s) not found for architecture i386^M
>>>> collect2: error: ld returned 1 exit status^M
>>>> compiler exited with status 1
>>>> output is:
>>>> Undefined symbols for architecture i386:^M
>>>>   "_foo", referenced from:^M
>>>>       _main in ccMD1qjz.o^M
>>>>       _main in ccMD1qjz.o^M
>>>> ld: symbol(s) not found for architecture i386^M
>>>> collect2: error: ld returned 1 exit status^M
>>>>
>>>> FAIL: gcc.dg/visibility-22.c (test for excess errors)
>>>>
>>>> Executing on host:
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>>>  -fno-diagnostics-show-caret -fdiagnostics-color=never   -fPIC -S
>>>> -m32  -o visibility-23.s    (timeout = 300)
>>>> spawn -ignore SIGHUP
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/xgcc
>>>> -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc/
>>>> /sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20150206/gcc/testsuite/gcc.dg/visibility-23.c
>>>> -fno-diagnostics-show-caret -fdiagnostics-color=never -fPIC -S -m32 -o
>>>> visibility-23.s^M
>>>> PASS: gcc.dg/visibility-23.c (test for excess errors)
>>>> FAIL: gcc.dg/visibility-23.c scan-hidden private_extern[ \t_]*_?foo
>>>>
>>>
>>> Does Darwin support undefined hidden weak symbol?
>>> Can you compile and gcc/testsuite/gcc.dg/visibility-22.c
>>> with clang on Darwin?
>>>
>>> --
>>> H.J.
>
>
>
> --
> H.J.
diff mbox

Patch

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index a2650f7..e1a6e41 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -792,8 +792,10 @@  varpool_node::finalize_decl (tree decl)
 
   if (node->definition)
     return;
-  notice_global_symbol (decl);
+  /* Set definition first before calling notice_global_symbol so that
+     it is available to notice_global_symbol.  */
   node->definition = true;
+  notice_global_symbol (decl);
   if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
       /* Traditionally we do not eliminate static variables when not
 	 optimizing and when not doing toplevel reoder.  */
diff --git a/gcc/testsuite/gcc.dg/visibility-22.c b/gcc/testsuite/gcc.dg/visibility-22.c
new file mode 100644
index 0000000..30087de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/visibility-22.c
@@ -0,0 +1,14 @@ 
+/* PR target/32219 */
+/* { dg-do run } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fPIC" { target fpic } } */
+
+extern void foo () __attribute__((weak,visibility("hidden")));
+int
+main()
+{
+  if (foo)
+    foo ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/visibility-23.c b/gcc/testsuite/gcc.dg/visibility-23.c
new file mode 100644
index 0000000..070493f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/visibility-23.c
@@ -0,0 +1,15 @@ 
+/* PR target/32219 */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "foo" } } */
+/* { dg-options "-fPIC" { target fpic } } */
+
+extern void foo () __attribute__((weak,visibility("hidden")));
+int
+main()
+{
+  if (foo)
+    foo ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
new file mode 100644
index 0000000..5bd80a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Common symbol with -fpie.  */
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c
new file mode 100644
index 0000000..0cf2eb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Common symbol with -fpic.  */
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-3.c b/gcc/testsuite/gcc.target/i386/pr32219-3.c
new file mode 100644
index 0000000..911f2a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-3.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Weak common symbol with -fpie.  */
+__attribute__((weak))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-4.c b/gcc/testsuite/gcc.target/i386/pr32219-4.c
new file mode 100644
index 0000000..3d43439
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-4.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Weak common symbol with -fpic.  */
+__attribute__((weak))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-5.c b/gcc/testsuite/gcc.target/i386/pr32219-5.c
new file mode 100644
index 0000000..ee7442e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-5.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Initialized symbol with -fpie.  */
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-6.c b/gcc/testsuite/gcc.target/i386/pr32219-6.c
new file mode 100644
index 0000000..f261433
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-6.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Initialized symbol with -fpic.  */
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-7.c b/gcc/testsuite/gcc.target/i386/pr32219-7.c
new file mode 100644
index 0000000..12aaf72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-7.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Weak initialized symbol with -fpie.  */
+__attribute__((weak))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-8.c b/gcc/testsuite/gcc.target/i386/pr32219-8.c
new file mode 100644
index 0000000..2e4fba0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-8.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+/* Weak initialized symbol with -fpic.  */
+__attribute__((weak))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
index 46c3c6f..a23e996 100644
--- a/gcc/testsuite/gcc.target/i386/pr64317.c
+++ b/gcc/testsuite/gcc.target/i386/pr64317.c
@@ -1,7 +1,7 @@ 
 /* { dg-do compile { target { ia32 } } } */
 /* { dg-options "-O2 -fPIE -pie" } */
 /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
-/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
 /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
 long c;
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index eb65b1f..f7c13af 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6826,11 +6826,17 @@  default_binds_local_p_1 (const_tree exp, int shlib)
       && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
     {
       varpool_node *vnode = varpool_node::get (exp);
-      if (vnode && (resolution_local_p (vnode->resolution) || vnode->in_other_partition))
-	resolved_locally = true;
-      if (vnode
-	  && resolution_to_local_definition_p (vnode->resolution))
-	resolved_to_local_def = true;
+      /* If not building shared library, common or initialized symbols
+	 are also resolved locally, regardless they are weak or not.  */
+      if (vnode)
+	{
+	  if ((!shlib && vnode->definition)
+	      || vnode->in_other_partition
+	      || resolution_local_p (vnode->resolution))
+	    resolved_locally = true;
+	  if (resolution_to_local_definition_p (vnode->resolution))
+	    resolved_to_local_def = true;
+	}
     }
   else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
     {
@@ -6859,9 +6865,14 @@  default_binds_local_p_1 (const_tree exp, int shlib)
   else if (! TREE_PUBLIC (exp))
     local_p = true;
   /* A variable is local if the user has said explicitly that it will
-     be.  */
+     be and it is resolved or defined locally, not compiling for PIC or
+     not weak.  */
   else if ((DECL_VISIBILITY_SPECIFIED (exp)
 	    || resolved_to_local_def)
+	   && (resolved_locally
+	       || !flag_pic
+	       || !DECL_EXTERNAL (exp)
+	       || !DECL_WEAK (exp))
 	   && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
     local_p = true;
   /* Variables defined outside this object might not be local.  */
@@ -6880,13 +6891,6 @@  default_binds_local_p_1 (const_tree exp, int shlib)
      symbols resolved from other modules.  */
   else if (shlib)
     local_p = false;
-  /* Uninitialized COMMON variable may be unified with symbols
-     resolved from other modules.  */
-  else if (DECL_COMMON (exp)
-	   && !resolved_locally
-	   && (DECL_INITIAL (exp) == NULL
-	       || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
-    local_p = false;
   /* Otherwise we're left with initialized (or non-common) global data
      which is of necessity defined locally.  */
   else
@@ -7445,9 +7449,10 @@  default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
 {
   /* We output the name if and only if TREE_SYMBOL_REFERENCED is
      set in order to avoid putting out names that are never really
-     used. */
+     used.   Always output visibility specified in the source.  */
   if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
-      && targetm.binds_local_p (decl))
+      && (DECL_VISIBILITY_SPECIFIED (decl)
+	  || targetm.binds_local_p (decl)))
     maybe_assemble_visibility (decl);
 }