On 1/21/20 10:17 AM, Jason Merrill wrote:
The problem in the PR was that make_temporary_var_for_ref_to_temp ran before
determine_visibility, so when we copied the linkage of the reference
variable it had not yet been restricted by its anonymous namespace context,
so the temporary wrongly ended up with TREE_PUBLIC set.  The natural
solution is to run determine_visibility earlier.  But that needs to happen
after maybe_commonize_var increases the linkage of some local variables, and
on targets without weak symbol support, that function does different things
based on the results of check_initializer, which is what calls
make_temporary_var_for_ref_to_temp.  To break this circular dependency I'm
calling maybe_commonize_var early, and then again later if the target
doesn't support weak symbols.

It also occurred to me that make_temporary_var_for_ref_to_temp wasn't
handling DECL_VISIBILITY at all, and verified that we were doing the wrong
thing.  So I've combined the linkage-copying code from there and two other
places.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * decl2.c (copy_linkage): Factor out of get_guard.
        * call.c (make_temporary_var_for_ref_to_temp): Use it.
        * decl.c (cp_finish_decomp): Use it.
        (cp_finish_decl): determine_visibility sooner.

And a much simpler patch for GCC 9, that doesn't address visibility:
commit 1669a68c844ec91dff4e9054327f2f5234e1614e
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Jan 20 14:09:03 2020 -0500

    PR c++/91476 - anon-namespace reference temp clash between TUs.
    
            * call.c (make_temporary_var_for_ref_to_temp): Clear TREE_PUBLIC
            if DECL is in the anonymous namespace.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bc182e2f6da..8e14e89d5d4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -11424,6 +11424,8 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
 
       TREE_STATIC (var) = TREE_STATIC (decl);
       TREE_PUBLIC (var) = TREE_PUBLIC (decl);
+      if (decl_anon_ns_mem_p (decl))
+	TREE_PUBLIC (var) = 0;
       if (vague_linkage_p (decl))
 	comdat_linkage (var);
 
diff --git a/gcc/testsuite/g++.dg/ext/visibility/ref-temp1.C b/gcc/testsuite/g++.dg/ext/visibility/ref-temp1.C
new file mode 100644
index 00000000000..b56bb52a73c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/ref-temp1.C
@@ -0,0 +1,11 @@
+// PR c++/91476
+// Test that hidden and internal visibility propagates to reference temps.
+
+// { dg-final { scan-assembler-not "(weak|globl)\[^\n\]*_ZGRN12_GLOBAL__N_13fooE_" } }
+namespace { const int &foo = 1; }
+
+const void *volatile p;
+int main()
+{
+  p = &foo;
+}

Reply via email to