Commit b5d0294e by Jason Merrill Committed by Jason Merrill

PR c++/89001 - mangling of reference temporaries

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
parent d8b5a1a0
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> 2019-01-24 Jakub Jelinek <jakub@redhat.com>
PR c++/88976 PR c++/88976
......
...@@ -11174,9 +11174,21 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) ...@@ -11174,9 +11174,21 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
&& (TREE_STATIC (decl) || CP_DECL_THREAD_LOCAL_P (decl))) && (TREE_STATIC (decl) || CP_DECL_THREAD_LOCAL_P (decl)))
{ {
/* Namespace-scope or local static; give it a mangled name. */ /* 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_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); CP_DECL_THREAD_LOCAL_P (var) = CP_DECL_THREAD_LOCAL_P (decl);
set_decl_tls_model (var, DECL_TLS_MODEL (decl)); set_decl_tls_model (var, DECL_TLS_MODEL (decl));
......
...@@ -1640,6 +1640,7 @@ struct GTY(()) saved_scope { ...@@ -1640,6 +1640,7 @@ struct GTY(()) saved_scope {
/* If non-zero, implicit "omp declare target" attribute is added into the /* If non-zero, implicit "omp declare target" attribute is added into the
attribute lists. */ attribute lists. */
int omp_declare_target_attribute; int omp_declare_target_attribute;
int ref_temp_count;
struct stmt_tree_s x_stmt_tree; struct stmt_tree_s x_stmt_tree;
...@@ -1696,6 +1697,8 @@ extern GTY(()) struct saved_scope *scope_chain; ...@@ -1696,6 +1697,8 @@ extern GTY(()) struct saved_scope *scope_chain;
#define in_discarded_stmt scope_chain->discarded_stmt #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 /* RAII sentinel to handle clearing processing_template_decl and restoring
it when done. */ it when done. */
......
...@@ -4240,10 +4240,7 @@ decl_tls_wrapper_p (const tree fn) ...@@ -4240,10 +4240,7 @@ decl_tls_wrapper_p (const tree fn)
} }
/* Return an identifier for the name of a temporary variable used to /* 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 initialize a static reference. This is now part of the ABI. */
as well call them something readable. */
static GTY(()) int temp_count;
tree tree
mangle_ref_init_variable (const tree variable) mangle_ref_init_variable (const tree variable)
...@@ -4254,7 +4251,7 @@ 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); write_name (variable, /*ignore_local_scope=*/0);
/* Avoid name clashes with aggregate initialization of multiple /* Avoid name clashes with aggregate initialization of multiple
references at once. */ references at once. */
write_unsigned_number (temp_count++); write_compact_number (current_ref_temp_count++);
return finish_mangling_get_identifier (); return finish_mangling_get_identifier ();
} }
......
...@@ -829,6 +829,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) ...@@ -829,6 +829,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
&& TREE_CODE (value) == CONSTRUCTOR) && TREE_CODE (value) == CONSTRUCTOR)
value = braced_list_to_string (type, value); value = braced_list_to_string (type, value);
current_ref_temp_count = 0;
value = extend_ref_init_temps (decl, value, cleanups); value = extend_ref_init_temps (decl, value, cleanups);
/* In C++11 constant expression is a semantic, not syntactic, property. /* In C++11 constant expression is a semantic, not syntactic, property.
......
// 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" } }
...@@ -7,5 +7,5 @@ struct Y { int b, c, d; }; ...@@ -7,5 +7,5 @@ struct Y { int b, c, d; };
auto&& [t] = X{}; // { dg-warning "structured bindings only available with" "" { target c++14_down } } 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 } } 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 "_ZGRDC1tE_" } }
// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } } // { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE_" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment