+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
&& (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));
/* 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;
#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. */
}
/* 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)
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 ();
}
&& 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.
--- /dev/null
+// 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" } }
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_" } }