Backports to 7.3
Jakub Jelinek
jakub@redhat.com
Sat Dec 16 00:41:00 GMT 2017
On Fri, Dec 15, 2017 at 11:23:21PM +0100, Jakub Jelinek wrote:
> Hi!
>
> I've backported today following 23 patches after bootstrapping/regtesting
> them on x86_64-linux and i686-linux.
And 2 more:
Jakub
-------------- next part --------------
2017-12-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
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.
* g++.dg/cpp1z/decomp34.C: New test.
--- gcc/cp/decl.c (revision 255704)
+++ gcc/cp/decl.c (revision 255705)
@@ -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,
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:
--- gcc/cp/pt.c (revision 255704)
+++ gcc/cp/pt.c (revision 255705)
@@ -16135,19 +16135,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);
}
}
}
--- gcc/cp/parser.c (revision 255704)
+++ gcc/cp/parser.c (revision 255705)
@@ -11735,6 +11735,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_NULL,
@@ -13059,6 +13062,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 ());
--- gcc/cp/mangle.c (revision 255704)
+++ gcc/cp/mangle.c (revision 255705)
@@ -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))
{
--- gcc/cp/cp-tree.h (revision 255704)
+++ gcc/cp/cp-tree.h (revision 255705)
@@ -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);
--- gcc/testsuite/g++.dg/cpp1z/decomp34.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp34.C (revision 255705)
@@ -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 "decomposition declaration only available with" "" { target c++14_down } }
+namespace A { namespace B { auto&& [u, v, ww] = Y{}; } } // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+
+// { dg-final { scan-assembler "_ZGRDC1tE0" } }
+// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } }
-------------- next part --------------
2017-12-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2017-12-15 Jakub Jelinek <jakub@redhat.com>
PR c++/83205
* decl.c (cp_finish_decomp): Handle the case when tsize is not
error_mark_node, but doesn't fit into uhwi. Split up count != eltscnt
and !tree_fits_uhwi_p (tsize) error_at calls into error_n and inform_n
to handle plural forms properly.
* g++.dg/cpp1z/decomp3.C: Adjust for structured binding count
mismatch diagnostics split into error and warning with plural
forms.
* g++.dg/cpp1z/decomp10.C: Likewise.
* g++.dg/cpp1z/decomp32.C: New test.
--- gcc/cp/decl.c (revision 255705)
+++ gcc/cp/decl.c (revision 255706)
@@ -7446,11 +7446,20 @@ cp_finish_decomp (tree decl, tree first,
{
cnt_mismatch:
if (count > eltscnt)
- error_at (loc, "%u names provided while %qT decomposes into "
- "%wu elements", count, type, eltscnt);
+ error_n (loc, count,
+ "%u name provided for structured binding",
+ "%u names provided for structured binding", count);
else
- error_at (loc, "only %u names provided while %qT decomposes into "
- "%wu elements", count, type, eltscnt);
+ error_n (loc, count,
+ "only %u name provided for structured binding",
+ "only %u names provided for structured binding", count);
+ /* Some languages have special plural rules even for large values,
+ but it is periodic with period of 10, 100, 1000 etc. */
+ inform_n (loc, eltscnt > INT_MAX
+ ? (eltscnt % 1000000) + 1000000 : eltscnt,
+ "while %qT decomposes into %wu element",
+ "while %qT decomposes into %wu elements",
+ type, eltscnt);
goto error_out;
}
eltype = TREE_TYPE (type);
@@ -7519,6 +7528,15 @@ cp_finish_decomp (tree decl, tree first,
"constant expression", type);
goto error_out;
}
+ if (!tree_fits_uhwi_p (tsize))
+ {
+ error_n (loc, count,
+ "%u name provided for structured binding",
+ "%u names provided for structured binding", count);
+ inform (loc, "while %qT decomposes into %E elements",
+ type, tsize);
+ goto error_out;
+ }
eltscnt = tree_to_uhwi (tsize);
if (count != eltscnt)
goto cnt_mismatch;
--- gcc/testsuite/g++.dg/cpp1z/decomp3.C (revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp3.C (revision 255706)
@@ -51,16 +51,21 @@ int arr[4];
void
test3 (A &b, B c)
{
- auto [ d, e, f ] = arr; // { dg-error "only 3 names provided while 'int .4.' decomposes into 4 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided while 'int .4.' decomposes into 4 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [ l, m ] = b; // { dg-error "only 2 names provided while 'A' decomposes into 3 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto & [ n, o, p, q ] = b; // { dg-error "4 names provided while 'A' decomposes into 3 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [ d, e, f ] = arr; // { dg-error "only 3 names provided" }
+ // { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+ auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided" }
+ // { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+ auto [ l, m ] = b; // { dg-error "only 2 names provided" }
+ // { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
+ auto & [ n, o, p, q ] = b; // { dg-error "4 names provided" }
+ // { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
auto [] { c }; // { dg-error "empty decomposition declaration" }
// { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [ r, s ] = c; // { dg-error "2 names provided while 'B' decomposes into 1 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [ r, s ] = c; // { dg-error "2 names provided" }
+ // { dg-message "while 'B' decomposes into 1 element" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 }
}
--- gcc/testsuite/g++.dg/cpp1z/decomp10.C (revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp10.C (revision 255706)
@@ -11,7 +11,8 @@ void f1() { auto [ x ] = a1; } // { dg-e
struct A2 { int i,j; } a2;
template<> struct std::tuple_size<A2> { enum { value = 5 }; };
-void f2() { auto [ x ] = a2; } // { dg-error "decomposes into 5" }
+void f2() { auto [ x ] = a2; } // { dg-error "only 1 name provided" }
+ // { dg-message "decomposes into 5" "" { target *-*-* } .-1 }
struct A3 { int i,j; } a3;
template<> struct std::tuple_size<A3> { enum { value = 1 }; };
--- gcc/testsuite/g++.dg/cpp1z/decomp32.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp32.C (revision 255706)
@@ -0,0 +1,32 @@
+// PR c++/83205
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A { int i; };
+struct B { int i; };
+namespace std {
+ template <typename T> struct tuple_size;
+ template <> struct tuple_size<A> {
+ static constexpr int value = -1;
+ };
+#ifdef __SIZEOF_INT128__
+ template <> struct tuple_size<B> {
+ static constexpr unsigned __int128 value = -1;
+ };
+#endif
+}
+
+auto [a] = A{}; // { dg-error "1 name provided" }
+ // { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-2 }
+#ifdef __SIZEOF_INT128__
+auto [b] = B{}; // { dg-error "1 name provided" "" { target int128 } }
+ // { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 }
+ // { dg-warning "decomposition declaration only available with" "" { target { c++14_down && int128 } } .-2 }
+auto [c, d] = B{}; // { dg-error "2 names provided" "" { target int128 } }
+ // { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 }
+ // { dg-warning "decomposition declaration only available with" "" { target { c++14_down && int128 } } .-2 }
+#endif
+auto [e, f, g] = A{}; // { dg-error "3 names provided" }
+ // { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 }
+ // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-2 }
More information about the Gcc-patches
mailing list