Commit b7f0df71 by Jakub Jelinek

P1091R3 - Extending structured bindings to be more like var decls P1381R1 -…

P1091R3 - Extending structured bindings to be more like var decls P1381R1 - Reference capture of structured bindings

	P1091R3 - Extending structured bindings to be more like var decls
	P1381R1 - Reference capture of structured bindings
	* decl.c (cp_maybe_mangle_decomp): Handle TREE_STATIC decls even at
	function scope.
	(cp_finish_decomp): Copy over various decl properties from decl to
	v[i] in the tuple case.
	(grokdeclarator): Allow static, thread_local and __thread for C++2a
	and use pedwarn instead of error for older standard revisions.
	Make other structured binding diagnostic messages more i18n friendly.

	* g++.dg/cpp1z/decomp3.C (test): For static, expect only warning
	instead of error and only for c++17_down.  Add a thread_local test.
	(z2): Add a __thread test.
	* g++.dg/cpp2a/decomp1.C: New test.
	* g++.dg/cpp2a/decomp1-aux.cc: New file.
	* g++.dg/cpp2a/decomp2.C: New test.
	* g++.dg/cpp2a/decomp3.C: New test.

From-SVN: r271730
parent 2186b5d0
......@@ -7626,7 +7626,7 @@ cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
{
if (!processing_template_decl
&& !error_operand_p (decl)
&& DECL_NAMESPACE_SCOPE_P (decl))
&& TREE_STATIC (decl))
{
auto_vec<tree, 16> v;
v.safe_grow (count);
......@@ -7857,9 +7857,28 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
}
if (!processing_template_decl)
{
TREE_PUBLIC (v[i]) = TREE_PUBLIC (decl);
TREE_STATIC (v[i]) = TREE_STATIC (decl);
DECL_COMMON (v[i]) = DECL_COMMON (decl);
DECL_COMDAT (v[i]) = DECL_COMDAT (decl);
if (TREE_STATIC (v[i]))
{
CP_DECL_THREAD_LOCAL_P (v[i])
= CP_DECL_THREAD_LOCAL_P (decl);
set_decl_tls_model (v[i], DECL_TLS_MODEL (decl));
if (DECL_ONE_ONLY (decl))
make_decl_one_only (v[i], cxx_comdat_group (v[i]));
if (TREE_PUBLIC (decl))
DECL_WEAK (v[i]) = DECL_WEAK (decl);
DECL_VISIBILITY (v[i]) = DECL_VISIBILITY (decl);
DECL_VISIBILITY_SPECIFIED (v[i])
= DECL_VISIBILITY_SPECIFIED (decl);
}
cp_finish_decl (v[i], init, /*constexpr*/false,
/*asm*/NULL_TREE, LOOKUP_NORMAL);
}
}
/* Ignore reads from the underlying decl performed during initialization
of the individual variables. If those will be read, we'll mark
the underlying decl as read at that point. */
......@@ -11067,40 +11086,43 @@ grokdeclarator (const cp_declarator *declarator,
? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep)
error_at (declspecs->locations[ds_inline],
"structured binding declaration cannot be %<inline%>");
"structured binding declaration cannot be %qs", "inline");
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
"structured binding declaration cannot be %<typedef%>");
"structured binding declaration cannot be %qs", "typedef");
if (constexpr_p)
error_at (declspecs->locations[ds_constexpr], "structured "
"binding declaration cannot be %<constexpr%>");
if (thread_p)
error_at (declspecs->locations[ds_thread],
"structured binding declaration cannot be %qs",
"binding declaration cannot be %qs", "constexpr");
if (thread_p && cxx_dialect < cxx2a)
pedwarn (declspecs->locations[ds_thread], 0,
"structured binding declaration can be %qs only in "
"%<-std=c++2a%> or %<-std=gnu++2a%>",
declspecs->gnu_thread_keyword_p
? "__thread" : "thread_local");
if (concept_p)
error_at (declspecs->locations[ds_concept],
"structured binding declaration cannot be %<concept%>");
"structured binding declaration cannot be %qs", "concept");
switch (storage_class)
{
case sc_none:
break;
case sc_register:
error_at (loc, "structured binding declaration cannot be "
"%<register%>");
error_at (loc, "structured binding declaration cannot be %qs",
"register");
break;
case sc_static:
error_at (loc, "structured binding declaration cannot be "
"%<static%>");
if (cxx_dialect < cxx2a)
pedwarn (loc, 0,
"structured binding declaration can be %qs only in "
"%<-std=c++2a%> or %<-std=gnu++2a%>", "static");
break;
case sc_extern:
error_at (loc, "structured binding declaration cannot be "
"%<extern%>");
error_at (loc, "structured binding declaration cannot be %qs",
"extern");
break;
case sc_mutable:
error_at (loc, "structured binding declaration cannot be "
"%<mutable%>");
error_at (loc, "structured binding declaration cannot be %qs",
"mutable");
break;
case sc_auto:
error_at (loc, "structured binding declaration cannot be "
......@@ -11126,12 +11148,12 @@ grokdeclarator (const cp_declarator *declarator,
inlinep = 0;
typedef_p = 0;
constexpr_p = 0;
thread_p = 0;
concept_p = 0;
if (storage_class != sc_static)
{
storage_class = sc_none;
staticp = 0;
declspecs->storage_class = sc_none;
declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
}
}
/* Static anonymous unions are dealt with here. */
......
......@@ -35,12 +35,17 @@ test (A &b, B c)
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
explicit auto [ w ] = c; // { dg-error "'explicit' outside class declaration" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
static auto [ x ] = c; // { dg-error "structured binding declaration cannot be 'static'" }
static auto [ x ] = c; // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
extern auto [ y ] { c }; // { dg-error "structured binding declaration cannot be 'extern'" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
thread_local auto [ z ] = c; // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
}
__thread auto [ z2 ] = B (); // { dg-warning "structured binding declaration can be '__thread' only in" "" { target c++17_down } }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
void
test2 (auto & [ p ] = bar ()) // { dg-error "'p' was not declared in this scope" }
{ // { dg-warning "auto" "" { target { ! concepts } } .-1 }
......
// P1091R3
// { dg-do compile { target { c++17 && c++14_down } } }
namespace std {
template<typename T> struct tuple_size;
template<int, typename> struct tuple_element;
}
struct A {
int i;
A(int x) : i(x) {}
template <int I> int& get() { return i; }
};
struct B { int a, b, c; };
template<> struct std::tuple_size<A> { static const int value = 2; };
template<int I> struct std::tuple_element<I,A> { using type = int; };
B s = { 1, 2, 3 };
#line 1
static auto [ d, e, f ] = s;
static auto [ g, h ] = A (42);
int &
foo (int x)
{
switch (x)
{
case 0: return d;
case 1: return e;
case 2: return f;
case 3: return g;
default: return h;
}
}
int
bar (int x)
{
#line 3
static auto [ m, n, o ] = s;
static auto [ p, q ] = A (43);
switch (x)
{
case 0: return ++m;
case 1: return ++n;
case 2: return ++o;
case 3: return ++p;
default: return ++q;
}
}
// P1091R3
// { dg-do run { target c++11 } }
// { dg-options "" }
// { dg-additional-sources decomp1-aux.cc }
namespace std {
template<typename T> struct tuple_size;
template<int, typename> struct tuple_element;
}
struct A {
int i;
A(int x) : i(x) {}
template <int I> int& get() { return i; }
};
struct B { int a, b, c; };
template<> struct std::tuple_size<A> { static const int value = 2; };
template<int I> struct std::tuple_element<I,A> { using type = int; };
extern int &foo (int);
extern int bar (int);
extern B s;
extern "C" void abort ();
B t = { 4, 5, 6 };
static auto [ d, e, f ] = t; // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
static auto [ g, h ] = A (44); // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
// The following warnings are in decomp1-aux.cc with #line directive.
// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 1 }
// { dg-warning "structured bindings only available with" "" { target c++14_down } 1 }
// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 2 }
// { dg-warning "structured bindings only available with" "" { target c++14_down } 2 }
// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 3 }
// { dg-warning "structured bindings only available with" "" { target c++14_down } 3 }
// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 4 }
// { dg-warning "structured bindings only available with" "" { target c++14_down } 4 }
int &
baz (int x)
{
switch (x)
{
case 0: return d;
case 1: return e;
case 2: return f;
case 3: return g;
default: return h;
}
}
int
qux (int x)
{
static auto [ m, n, o ] = t; // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
static auto [ p, q ] = A (45); // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
switch (x)
{
case 0: return ++m;
case 1: return ++n;
case 2: return ++o;
case 3: return ++p;
default: return ++q;
}
}
int
main ()
{
int *a[10];
for (int i = 0; i < 5; ++i)
{
a[i] = &foo (i);
a[i + 5] = &baz (i);
}
for (int i = 0; i < 10; ++i)
for (int j = i + 1; j < 10; ++j)
if (a[i] == a[j] && (j != i + 1 || (i % 5) != 3))
abort ();
if (a[1] != a[0] + 1 || a[2] != a[0] + 2 || a[4] != a[3]
|| a[6] != a[5] + 1 || a[7] != a[5] + 2 || a[9] != a[8])
abort ();
int b[] = { 1, 2, 3, 43, 43 + 6, 4, 5, 6, 45, 45 + 11 };
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 3 + i; ++j)
if ((i < 5 ? bar (i) : qux (i - 5)) != b[i] + 1 + j)
abort ();
}
// P1091R3
// { dg-do run { target c++11 } }
// { dg-options "" }
// { dg-require-effective-target tls }
namespace std {
template<typename T> struct tuple_size;
template<int, typename> struct tuple_element;
}
struct A {
int i;
A(int x) : i(x) {}
template <int I> int& get() { return i; }
};
struct B { int a, b, c; };
template<> struct std::tuple_size<A> { static const int value = 2; };
template<int I> struct std::tuple_element<I,A> { using type = int; };
extern "C" void abort ();
B t = { 4, 5, 6 };
thread_local auto [ d, e, f ] = t; // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
thread_local auto [ g, h ] = A (44); // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
int &
baz (int x)
{
switch (x)
{
case 0: return d;
case 1: return e;
case 2: return f;
case 3: return g;
default: return h;
}
}
int
qux (int x)
{
thread_local auto [ m, n, o ] = t; // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
thread_local auto [ p, q ] = A (45); // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
// { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
switch (x)
{
case 0: return ++m;
case 1: return ++n;
case 2: return ++o;
case 3: return ++p;
default: return ++q;
}
}
int
main ()
{
int *a[5];
for (int i = 0; i < 5; ++i)
a[i] = &baz (i);
for (int i = 0; i < 5; ++i)
for (int j = i + 1; j < 5; ++j)
if (a[i] == a[j] && (j != i + 1 || i != 3))
abort ();
if (a[1] != a[0] + 1 || a[2] != a[0] + 2 || a[4] != a[3])
abort ();
int b[] = { 4, 5, 6, 45, 45 + 6 };
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 3 + i; ++j)
if (qux (i) != b[i] + 1 + j)
abort ();
}
// P1381R1
// { dg-do compile { target c++11 } }
// { dg-options "" }
struct Foo { int a : 1; int b; };
int main() {
auto[a, b] = Foo(); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
auto f1 = [&] { return a; }; // { dg-error "cannot bind bitfield" }
auto f2 = [&a = a] { return a; }; // { dg-error "cannot bind bitfield" }
// { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
auto f3 = [&a] { return a; }; // { dg-error "cannot bind bitfield" }
auto g1 = [&] { return b; };
auto g2 = [&b = b] { return b; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
auto g3 = [&b] { return b; };
auto h1 = [=] { return a; };
auto h2 = [a = a] { return a; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
auto h3 = [a] { return a; };
auto i1 = [=] { return b; };
auto i2 = [b = b] { return b; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
auto i3 = [b] { return b; };
}
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