aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-12-15 22:39:20 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-12-15 22:39:20 +0100
commit70356f771a65b378362b08d5fdb926fbb88e4aa7 (patch)
treeb5ee5b2b815030b7f06772d64cb74ea7a4a26e7b
parenta8c55cacaf8fa1e90f9e26c467a78081ae152b50 (diff)
downloadgcc-70356f771a65b378362b08d5fdb926fbb88e4aa7.zip
gcc-70356f771a65b378362b08d5fdb926fbb88e4aa7.tar.gz
gcc-70356f771a65b378362b08d5fdb926fbb88e4aa7.tar.bz2
re PR c++/81197 (ICE with structured binding and lifetime-extended temporaries)
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. * g++.dg/cpp1z/decomp34.C: New test. From-SVN: r255705
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c21
-rw-r--r--gcc/cp/mangle.c57
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/cp/pt.c16
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp34.C11
8 files changed, 115 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 488b9f3..d96b679 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 05551df..f5f974d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6149,6 +6149,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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5df16bb..0e6ee05 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7339,6 +7339,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
@@ -7612,8 +7631,6 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
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:
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 6d4e591..ffd2b4c 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1247,6 +1247,51 @@ write_template_prefix (const tree node)
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.
@@ -1291,7 +1336,17 @@ write_unqualified_name (tree decl)
{
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))
{
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 94e87c2..e13e127 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11940,6 +11940,9 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
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,
@@ -13283,6 +13286,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
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 ());
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a6a7cf..dc50f31 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16135,19 +16135,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
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);
}
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e1e29f1..ba86d2f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
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
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp34.C b/gcc/testsuite/g++.dg/cpp1z/decomp34.C
new file mode 100644
index 0000000..c7f0b8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp34.C
@@ -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" } }