@@ -6141,6 +6141,7 @@ extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void cp_finish_decl (tree, tree, bool, tree, int);
extern tree lookup_decomp_type (tree);
+extern void cp_maybe_mangle_decomp (tree, tree, unsigned int);
extern void cp_finish_decomp (tree, tree, unsigned int);
extern int cp_complete_array_type (tree *, tree, bool);
extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t);
@@ -7359,6 +7359,25 @@ lookup_decomp_type (tree v)
return *decomp_type_table->get (v);
}
+/* Mangle a decomposition declaration if needed. Arguments like
+ in cp_finish_decomp. */
+
+void
+cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
+{
+ if (!processing_template_decl
+ && !error_operand_p (decl)
+ && DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ auto_vec<tree, 16> v;
+ v.safe_grow (count);
+ tree d = first;
+ for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
+ v[count - i - 1] = d;
+ SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
+ }
+}
+
/* Finish a decomposition declaration. DECL is the underlying declaration
"e", FIRST is the head of a chain of decls for the individual identifiers
chained through DECL_CHAIN in reverse order and COUNT is the number of
@@ -7630,8 +7649,6 @@ cp_finish_decomp (tree decl, tree first,
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
}
- else if (DECL_NAMESPACE_SCOPE_P (decl))
- SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
}
/* Returns a declaration for a VAR_DECL as if:
@@ -11926,6 +11926,9 @@ cp_convert_range_for (tree statement, tr
tf_warning_or_error);
finish_for_expr (expression, statement);
+ if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
+ cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt);
+
/* The declaration is initialized with *__begin inside the loop body. */
cp_finish_decl (range_decl,
build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
@@ -13269,6 +13272,7 @@ cp_parser_decomposition_declaration (cp_
if (decl != error_mark_node)
{
+ cp_maybe_mangle_decomp (decl, prev, v.length ());
cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT);
cp_finish_decomp (decl, prev, v.length ());
@@ -16096,19 +16096,23 @@ tsubst_expr (tree t, tree args, tsubst_f
if (VAR_P (decl))
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
- cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
if (VAR_P (decl)
&& DECL_DECOMPOSITION_P (decl)
&& TREE_TYPE (pattern_decl) != error_mark_node)
{
unsigned int cnt;
tree first;
- decl = tsubst_decomp_names (decl, pattern_decl, args,
- complain, in_decl, &first,
- &cnt);
- if (decl != error_mark_node)
- cp_finish_decomp (decl, first, cnt);
+ tree ndecl
+ = tsubst_decomp_names (decl, pattern_decl, args,
+ complain, in_decl, &first, &cnt);
+ if (ndecl != error_mark_node)
+ cp_maybe_mangle_decomp (ndecl, first, cnt);
+ cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+ if (ndecl != error_mark_node)
+ cp_finish_decomp (ndecl, first, cnt);
}
+ else
+ cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
}
}
}
@@ -1291,7 +1291,56 @@ write_unqualified_name (tree decl)
{
found = true;
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
- write_source_name (DECL_ASSEMBLER_NAME (decl));
+ if (VAR_P (decl)
+ && DECL_DECOMPOSITION_P (decl)
+ && DECL_NAME (decl) == NULL_TREE
+ && DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+ bool nested = false;
+ /* The list of identifiers is likely gone at this point, so find the
+ DC <source-name>+ E part in the mangled name. */
+ if (!strncmp (p, "_Z", 2))
+ {
+ p += 2;
+ if (!strncmp (p, "St", 2))
+ p += 2;
+ else if (*p == 'N')
+ {
+ nested = true;
+ ++p;
+ while (ISDIGIT (p[0]))
+ {
+ char *e;
+ long num = strtol (p, &e, 10);
+ if (num >= 1 && num < end - e)
+ p = e + num;
+ else
+ break;
+ }
+ }
+ if (strncmp (p, "DC", 2))
+ p = NULL;
+ if (nested)
+ {
+ if (end[-1] != 'E')
+ p = NULL;
+ else
+ --end;
+ }
+ if (end[-1] != 'E')
+ p = NULL;
+ }
+ else
+ p = NULL;
+ if (p == NULL)
+ write_source_name (DECL_ASSEMBLER_NAME (decl));
+ else
+ write_chars (p, end - p);
+ }
+ else
+ write_source_name (DECL_ASSEMBLER_NAME (decl));
}
else if (DECL_DECLARES_FUNCTION_P (decl))
{
@@ -0,0 +1,11 @@
+// PR c++/81197
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct X { int a; };
+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" } }