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) ...@@ -7626,7 +7626,7 @@ cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
{ {
if (!processing_template_decl if (!processing_template_decl
&& !error_operand_p (decl) && !error_operand_p (decl)
&& DECL_NAMESPACE_SCOPE_P (decl)) && TREE_STATIC (decl))
{ {
auto_vec<tree, 16> v; auto_vec<tree, 16> v;
v.safe_grow (count); v.safe_grow (count);
...@@ -7857,8 +7857,27 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) ...@@ -7857,8 +7857,27 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
DECL_HAS_VALUE_EXPR_P (v[i]) = 0; DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
} }
if (!processing_template_decl) if (!processing_template_decl)
cp_finish_decl (v[i], init, /*constexpr*/false, {
/*asm*/NULL_TREE, LOOKUP_NORMAL); 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 /* Ignore reads from the underlying decl performed during initialization
of the individual variables. If those will be read, we'll mark of the individual variables. If those will be read, we'll mark
...@@ -11067,40 +11086,43 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -11067,40 +11086,43 @@ grokdeclarator (const cp_declarator *declarator,
? declarator->declarator->id_loc : declarator->id_loc); ? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep) if (inlinep)
error_at (declspecs->locations[ds_inline], error_at (declspecs->locations[ds_inline],
"structured binding declaration cannot be %<inline%>"); "structured binding declaration cannot be %qs", "inline");
if (typedef_p) if (typedef_p)
error_at (declspecs->locations[ds_typedef], error_at (declspecs->locations[ds_typedef],
"structured binding declaration cannot be %<typedef%>"); "structured binding declaration cannot be %qs", "typedef");
if (constexpr_p) if (constexpr_p)
error_at (declspecs->locations[ds_constexpr], "structured " error_at (declspecs->locations[ds_constexpr], "structured "
"binding declaration cannot be %<constexpr%>"); "binding declaration cannot be %qs", "constexpr");
if (thread_p) if (thread_p && cxx_dialect < cxx2a)
error_at (declspecs->locations[ds_thread], pedwarn (declspecs->locations[ds_thread], 0,
"structured binding declaration cannot be %qs", "structured binding declaration can be %qs only in "
declspecs->gnu_thread_keyword_p "%<-std=c++2a%> or %<-std=gnu++2a%>",
? "__thread" : "thread_local"); declspecs->gnu_thread_keyword_p
? "__thread" : "thread_local");
if (concept_p) if (concept_p)
error_at (declspecs->locations[ds_concept], error_at (declspecs->locations[ds_concept],
"structured binding declaration cannot be %<concept%>"); "structured binding declaration cannot be %qs", "concept");
switch (storage_class) switch (storage_class)
{ {
case sc_none: case sc_none:
break; break;
case sc_register: case sc_register:
error_at (loc, "structured binding declaration cannot be " error_at (loc, "structured binding declaration cannot be %qs",
"%<register%>"); "register");
break; break;
case sc_static: case sc_static:
error_at (loc, "structured binding declaration cannot be " if (cxx_dialect < cxx2a)
"%<static%>"); pedwarn (loc, 0,
"structured binding declaration can be %qs only in "
"%<-std=c++2a%> or %<-std=gnu++2a%>", "static");
break; break;
case sc_extern: case sc_extern:
error_at (loc, "structured binding declaration cannot be " error_at (loc, "structured binding declaration cannot be %qs",
"%<extern%>"); "extern");
break; break;
case sc_mutable: case sc_mutable:
error_at (loc, "structured binding declaration cannot be " error_at (loc, "structured binding declaration cannot be %qs",
"%<mutable%>"); "mutable");
break; break;
case sc_auto: case sc_auto:
error_at (loc, "structured binding declaration cannot be " error_at (loc, "structured binding declaration cannot be "
...@@ -11126,12 +11148,12 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -11126,12 +11148,12 @@ grokdeclarator (const cp_declarator *declarator,
inlinep = 0; inlinep = 0;
typedef_p = 0; typedef_p = 0;
constexpr_p = 0; constexpr_p = 0;
thread_p = 0;
concept_p = 0; concept_p = 0;
storage_class = sc_none; if (storage_class != sc_static)
staticp = 0; {
declspecs->storage_class = sc_none; storage_class = sc_none;
declspecs->locations[ds_thread] = UNKNOWN_LOCATION; declspecs->storage_class = sc_none;
}
} }
/* Static anonymous unions are dealt with here. */ /* Static anonymous unions are dealt with here. */
......
...@@ -35,12 +35,17 @@ test (A &b, B c) ...@@ -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 } // { 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" } 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 } // { 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 } // { 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'" } 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 } // { 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 void
test2 (auto & [ p ] = bar ()) // { dg-error "'p' was not declared in this scope" } test2 (auto & [ p ] = bar ()) // { dg-error "'p' was not declared in this scope" }
{ // { dg-warning "auto" "" { target { ! concepts } } .-1 } { // { 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