PR c++/89001 - mangling of reference temporaries
authorJason Merrill <jason@redhat.com>
Thu, 24 Jan 2019 21:23:33 +0000 (16:23 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 24 Jan 2019 21:23:33 +0000 (16:23 -0500)
It used to be the case that the mangled name of a reference temporary didn't
need to be standardized, because all access would be through the reference.
But now constant expressions can look through references and so different
translation units need to agree on the address of a temporary in the
initializer of a reference with vague linkage.

* cp-tree.h (struct saved_scope): Add ref_temp_count.
(current_ref_temp_count): New macro.
* mangle.c (mangle_ref_init_variable): Use it.
* typeck2.c (store_init_value): Clear it.
* call.c (make_temporary_var_for_ref_to_temp): Copy public and
comdat.

From-SVN: r268252

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/abi/ref-temp1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/decomp34.C

index 99d43c9d7a4e942e57ebe40cb9ac6dddd0be313f..82a893ad1701e29f0c5eda6b64a32651a18cda74 100644 (file)
@@ -1,3 +1,13 @@
+2019-01-24  Jason Merrill  <jason@redhat.com>
+
+       PR c++/89001 - mangling of reference temporaries
+       * cp-tree.h (struct saved_scope): Add ref_temp_count.
+       (current_ref_temp_count): New macro.
+       * mangle.c (mangle_ref_init_variable): Use it.
+       * typeck2.c (store_init_value): Clear it.
+       * call.c (make_temporary_var_for_ref_to_temp): Copy public and
+       comdat.
+
 2019-01-24  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/88976
index 16c3706cc5c71de720dc5128654331217d7b0435..5bad2634cb3b5136e4f7c9f20a47b984e4ac48ec 100644 (file)
@@ -11174,9 +11174,21 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
       && (TREE_STATIC (decl) || CP_DECL_THREAD_LOCAL_P (decl)))
     {
       /* Namespace-scope or local static; give it a mangled name.  */
-      /* FIXME share comdat with decl?  */
+
+      /* If an initializer is visible to multiple translation units, those
+        translation units must agree on the addresses of the
+        temporaries. Therefore the temporaries must be given a consistent name
+        and vague linkage. The mangled name of a temporary is the name of the
+        non-temporary object in whose initializer they appear, prefixed with
+        GR and suffixed with a sequence number mangled using the usual rules
+        for a seq-id. Temporaries are numbered with a pre-order, depth-first,
+        left-to-right walk of the complete initializer.  */
 
       TREE_STATIC (var) = TREE_STATIC (decl);
+      TREE_PUBLIC (var) = TREE_PUBLIC (decl);
+      if (vague_linkage_p (decl))
+       comdat_linkage (var);
+
       CP_DECL_THREAD_LOCAL_P (var) = CP_DECL_THREAD_LOCAL_P (decl);
       set_decl_tls_model (var, DECL_TLS_MODEL (decl));
 
index 23d4a0e3c690e7c4b376316a26028fcd6049be0e..cd902ce1cf601cda140ba2394192f101b494b7dc 100644 (file)
@@ -1640,6 +1640,7 @@ struct GTY(()) saved_scope {
   /* If non-zero, implicit "omp declare target" attribute is added into the
      attribute lists.  */
   int omp_declare_target_attribute;
+  int ref_temp_count;
 
   struct stmt_tree_s x_stmt_tree;
 
@@ -1696,6 +1697,8 @@ extern GTY(()) struct saved_scope *scope_chain;
 
 #define in_discarded_stmt scope_chain->discarded_stmt
 
+#define current_ref_temp_count scope_chain->ref_temp_count
+
 /* RAII sentinel to handle clearing processing_template_decl and restoring
    it when done.  */
 
index 00bde4ee59a5cae1b7b87cad83db4c92fefde301..f550b7550dbe554dc8d131be4a63f097b5fba99d 100644 (file)
@@ -4240,10 +4240,7 @@ decl_tls_wrapper_p (const tree fn)
 }
 
 /* Return an identifier for the name of a temporary variable used to
-   initialize a static reference.  This isn't part of the ABI, but we might
-   as well call them something readable.  */
-
-static GTY(()) int temp_count;
+   initialize a static reference.  This is now part of the ABI.  */
 
 tree
 mangle_ref_init_variable (const tree variable)
@@ -4254,7 +4251,7 @@ mangle_ref_init_variable (const tree variable)
   write_name (variable, /*ignore_local_scope=*/0);
   /* Avoid name clashes with aggregate initialization of multiple
      references at once.  */
-  write_unsigned_number (temp_count++);
+  write_compact_number (current_ref_temp_count++);
   return finish_mangling_get_identifier ();
 }
 
index cd4313295d5816cf4caf95d2e1489af178be15ab..0756eb64872638844a922fb4fd45ee3be1caf4ba 100644 (file)
@@ -829,6 +829,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       && TREE_CODE (value) == CONSTRUCTOR)
     value = braced_list_to_string (type, value);
 
+  current_ref_temp_count = 0;
   value = extend_ref_init_temps (decl, value, cleanups);
 
   /* In C++11 constant expression is a semantic, not syntactic, property.
diff --git a/gcc/testsuite/g++.dg/abi/ref-temp1.C b/gcc/testsuite/g++.dg/abi/ref-temp1.C
new file mode 100644 (file)
index 0000000..887f432
--- /dev/null
@@ -0,0 +1,18 @@
+// From ABI document
+// { dg-do compile { target c++14 } }
+// { dg-additional-options --save-temps }
+
+struct A { const int (&x)[3]; };
+struct B { const A (&x)[2]; };
+template <typename T> B &&b = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } };
+B &temp = b<void>;
+
+// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE_" } }
+// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE0_" } }
+// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE1_" } }
+// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE2_" } }
+
+// { dg-final { scan-assembler "_ZGR1bIvE_:\n\[^\n]+_ZGR1bIvE0_" } }
+// { dg-final { scan-assembler "_ZGR1bIvE0_:\n\[^\n]+_ZGR1bIvE1_" } }
+// { dg-final { scan-assembler "_ZGR1bIvE1_:\n\[^\n]+\[ \t\]1" } }
+// { dg-final { scan-assembler "_ZGR1bIvE2_:\n\[^\n]+\[ \t\]4" } }
index c7f0b8ac16e931be9cc109d9b76250f156e53071..9bd1b146fee74d6d8b5281fe6b90bc07ff4bb77e 100644 (file)
@@ -7,5 +7,5 @@ struct Y { int b, c, d; };
 auto&& [t] = X{};      // { dg-warning "structured bindings only available with" "" { target c++14_down } }
 namespace A { namespace B { auto&& [u, v, ww] = Y{}; } }       // { dg-warning "structured bindings only available with" "" { target c++14_down } }
 
-// { dg-final { scan-assembler "_ZGRDC1tE0" } }
-// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } }
+// { dg-final { scan-assembler "_ZGRDC1tE_" } }
+// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE_" } }