2017-12-15 Jakub Jelinek <jakub@redhat.com>
+ PR c++/81197
+ * cp-tree.h (cp_maybe_mangle_decomp): Declare.
+ * decl.c (cp_maybe_mangle_decomp): New function.
+ (cp_finish_decomp): Don't SET_DECL_ASSEMBLER_NAME here.
+ * parser.c (cp_convert_range_for,
+ cp_parser_decomposition_declaration): Call cp_maybe_mangle_decomp.
+ * pt.c (tsubst_expr): Likewise.
+ * mangle.c (find_decomp_unqualified_name): New function.
+ (write_unqualified_name): Handle DECL_DECOMPOSITION_P
+ where DECL_ASSEMBLER_NAME is already set.
+
PR c++/80135
PR c++/81922
* typeck2.c (digest_init_r): Change nested argument type from bool to
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);
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
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:
add_substitution (substitution);
}
+/* As the list of identifiers for the structured binding declaration
+ DECL is likely gone, try to recover the DC <source-name>+ E portion
+ from its mangled name. Return pointer to the DC and set len to
+ the length up to and including the terminating E. On failure
+ return NULL. */
+
+static const char *
+find_decomp_unqualified_name (tree decl, size_t *len)
+{
+ const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+ bool nested = false;
+ if (strncmp (p, "_Z", 2))
+ return NULL;
+ 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))
+ return NULL;
+ if (nested)
+ {
+ if (end[-1] != 'E')
+ return NULL;
+ --end;
+ }
+ if (end[-1] != 'E')
+ return NULL;
+ *len = end - p;
+ return p;
+}
+
/* We don't need to handle thunks, vtables, or VTTs here. Those are
mangled through special entry points.
{
found = true;
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
- write_source_name (DECL_ASSEMBLER_NAME (decl));
+ const char *decomp_str = NULL;
+ size_t decomp_len = 0;
+ if (VAR_P (decl)
+ && DECL_DECOMPOSITION_P (decl)
+ && DECL_NAME (decl) == NULL_TREE
+ && DECL_NAMESPACE_SCOPE_P (decl))
+ decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
+ if (decomp_str)
+ write_chars (decomp_str, decomp_len);
+ else
+ write_source_name (DECL_ASSEMBLER_NAME (decl));
}
else if (DECL_DECLARES_FUNCTION_P (decl))
{
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,
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 ());
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);
}
}
}
2017-12-15 Jakub Jelinek <jakub@redhat.com>
+ PR c++/81197
+ * g++.dg/cpp1z/decomp34.C: New test.
+
PR c++/80135
PR c++/81922
* g++.dg/warn/Wplacement-new-size-1.C (fBx1): Initialize nested
--- /dev/null
+// 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" } }