public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls
@ 2019-05-20 21:44 Jakub Jelinek
  2019-05-27 13:55 ` Patch ping (was Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls) Jakub Jelinek
  2019-05-28 14:19 ` [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jason Merrill
  0 siblings, 2 replies; 5+ messages in thread
From: Jakub Jelinek @ 2019-05-20 21:44 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

The following patch is an attempt at implementing these two papers.
I must be missing something important, because in P1091R3 the rationale
talks about the intent to support structured bindings with static,
thread_local, constexpr, inline and extern, but the actual wording
changes in the paper are only about static and thread_local, because dcl.dcl
still says
If the decl-specifier-seq contains any decl-specifier other than static,
thread_local, auto, or cv-qualifiers, the program is ill-formed. 

Another thing are the lambda captures of the structured bindings.
The end result is that they are allowed, both capturing values and capturing
references, except when capturing bitfields, but that is actually what gcc
has been implementing for quite a while.  The question is if we shouldn't
reject those for -std=c++17 or -std=c++17 -pedantic-errors, seems e.g.
clang++ rejects those, but looking at the C++17 standard I don't see any
wording that would say those are not allowed.  It was only P0588R1 that
added 
"or captures a structured binding (explicitly or implicitly), the program is
ill-formed."
Is P0588R1 a DR that would be applied to older standards?

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-05-20  Jakub Jelinek  <jakub@redhat.com>

	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.

--- gcc/cp/decl.c.jj	2019-05-20 14:52:26.871375569 +0200
+++ gcc/cp/decl.c	2019-05-20 15:48:33.563599150 +0200
@@ -7625,7 +7625,7 @@ cp_maybe_mangle_decomp (tree decl, tree
 {
   if (!processing_template_decl
       && !error_operand_p (decl)
-      && DECL_NAMESPACE_SCOPE_P (decl))
+      && (DECL_NAMESPACE_SCOPE_P (decl) || TREE_STATIC (decl)))
     {
       auto_vec<tree, 16> v;
       v.safe_grow (count);
@@ -7856,8 +7856,27 @@ cp_finish_decomp (tree decl, tree first,
 	      DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
 	    }
 	  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
 	 of the individual variables.  If those will be read, we'll mark
@@ -11069,40 +11088,43 @@ grokdeclarator (const cp_declarator *dec
 			? 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",
-		  declspecs->gnu_thread_keyword_p
-		  ? "__thread" : "thread_local");
+		  "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 "
@@ -11128,12 +11150,12 @@ grokdeclarator (const cp_declarator *dec
       inlinep = 0;
       typedef_p = 0;
       constexpr_p = 0;
-      thread_p = 0;
       concept_p = 0;
-      storage_class = sc_none;
-      staticp = 0;
-      declspecs->storage_class = sc_none;
-      declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
+      if (storage_class != sc_static)
+	{
+	  storage_class = sc_none;
+	  declspecs->storage_class = sc_none;
+	}
     }
 
   /* Static anonymous unions are dealt with here.  */
--- gcc/testsuite/g++.dg/cpp1z/decomp3.C.jj	2019-03-11 22:56:50.077761472 +0100
+++ gcc/testsuite/g++.dg/cpp1z/decomp3.C	2019-05-20 16:42:18.820165706 +0200
@@ -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 }
--- gcc/testsuite/g++.dg/cpp2a/decomp1.C.jj	2019-05-20 15:30:04.521643439 +0200
+++ gcc/testsuite/g++.dg/cpp2a/decomp1.C	2019-05-20 15:38:20.895566717 +0200
@@ -0,0 +1,92 @@
+// 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 ();
+}
--- gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc.jj	2019-05-20 15:30:01.351695020 +0200
+++ gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc	2019-05-20 15:38:32.683374939 +0200
@@ -0,0 +1,52 @@
+// 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;
+    }
+}
--- gcc/testsuite/g++.dg/cpp2a/decomp2.C.jj	2019-05-20 16:53:47.130988616 +0200
+++ gcc/testsuite/g++.dg/cpp2a/decomp2.C	2019-05-20 16:56:33.840282248 +0200
@@ -0,0 +1,76 @@
+// 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 ();
+}
--- gcc/testsuite/g++.dg/cpp2a/decomp3.C.jj	2019-05-20 17:04:27.610731192 +0200
+++ gcc/testsuite/g++.dg/cpp2a/decomp3.C	2019-05-20 17:09:46.243938552 +0200
@@ -0,0 +1,26 @@
+// 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; };
+}

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Patch ping (was Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls)
  2019-05-20 21:44 [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jakub Jelinek
@ 2019-05-27 13:55 ` Jakub Jelinek
  2019-05-28 14:19 ` [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jason Merrill
  1 sibling, 0 replies; 5+ messages in thread
From: Jakub Jelinek @ 2019-05-27 13:55 UTC (permalink / raw)
  To: Jason Merrill, Nathan Sidwell; +Cc: gcc-patches

Hi!

On Mon, May 20, 2019 at 11:44:18PM +0200, Jakub Jelinek wrote:
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2019-05-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	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.

I'd like to ping this patch.

Thanks.

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls
  2019-05-20 21:44 [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jakub Jelinek
  2019-05-27 13:55 ` Patch ping (was Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls) Jakub Jelinek
@ 2019-05-28 14:19 ` Jason Merrill
  2019-05-28 14:47   ` Jakub Jelinek
  1 sibling, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2019-05-28 14:19 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 5/20/19 5:44 PM, Jakub Jelinek wrote:
> Hi!
> 
> The following patch is an attempt at implementing these two papers.
> I must be missing something important, because in P1091R3 the rationale
> talks about the intent to support structured bindings with static,
> thread_local, constexpr, inline and extern, but the actual wording
> changes in the paper are only about static and thread_local, because dcl.dcl
> still says
> If the decl-specifier-seq contains any decl-specifier other than static,
> thread_local, auto, or cv-qualifiers, the program is ill-formed.

Right, the original proposal was for more, but it was limited to static 
and thread_local by the committee.

> Another thing are the lambda captures of the structured bindings.
> The end result is that they are allowed, both capturing values and capturing
> references, except when capturing bitfields, but that is actually what gcc
> has been implementing for quite a while.  The question is if we shouldn't
> reject those for -std=c++17 or -std=c++17 -pedantic-errors, seems e.g.
> clang++ rejects those, but looking at the C++17 standard I don't see any
> wording that would say those are not allowed.  It was only P0588R1 that
> added
> "or captures a structured binding (explicitly or implicitly), the program is
> ill-formed."
> Is P0588R1 a DR that would be applied to older standards?

P0588 was certainly intended to apply to C++17, but I'd treat this as 
overriding it, and not complain.

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2019-05-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	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.
> 
> --- gcc/cp/decl.c.jj	2019-05-20 14:52:26.871375569 +0200
> +++ gcc/cp/decl.c	2019-05-20 15:48:33.563599150 +0200
> +      && (DECL_NAMESPACE_SCOPE_P (decl) || TREE_STATIC (decl)))
 > +	      if (TREE_STATIC (v[i]))

When can a structured binding not be TREE_STATIC?

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls
  2019-05-28 14:19 ` [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jason Merrill
@ 2019-05-28 14:47   ` Jakub Jelinek
  2019-05-28 15:01     ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2019-05-28 14:47 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Tue, May 28, 2019 at 10:07:12AM -0400, Jason Merrill wrote:
> > "or captures a structured binding (explicitly or implicitly), the program is
> > ill-formed."
> > Is P0588R1 a DR that would be applied to older standards?
> 
> P0588 was certainly intended to apply to C++17, but I'd treat this as
> overriding it, and not complain.

Ok.

> > --- gcc/cp/decl.c.jj	2019-05-20 14:52:26.871375569 +0200
> > +++ gcc/cp/decl.c	2019-05-20 15:48:33.563599150 +0200
> > +      && (DECL_NAMESPACE_SCOPE_P (decl) || TREE_STATIC (decl)))
> > +	      if (TREE_STATIC (v[i]))
> 
> When can a structured binding not be TREE_STATIC?

All the block scope structured bindings that aren't explicitly static
nor thread_local are not TREE_STATIC, and we really can't mangle them (and
cp_maybe_mangle_decomp is called on them).  And newly we need to mangle
even block scope structured bindings that are static or thread_local.

As extern isn't allowed (yet), perhaps all DECL_NAMESPACE_SCOPE_P (decl)
structured bindings are TREE_STATIC and I could replace the
DECL_NAMESPACE_SCOPE_P (decl) test in cp_maybe_mangle_decomp
with TREE_STATIC (decl) instead.

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls
  2019-05-28 14:47   ` Jakub Jelinek
@ 2019-05-28 15:01     ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2019-05-28 15:01 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 5/28/19 10:19 AM, Jakub Jelinek wrote:
> On Tue, May 28, 2019 at 10:07:12AM -0400, Jason Merrill wrote:
>>> "or captures a structured binding (explicitly or implicitly), the program is
>>> ill-formed."
>>> Is P0588R1 a DR that would be applied to older standards?
>>
>> P0588 was certainly intended to apply to C++17, but I'd treat this as
>> overriding it, and not complain.
> 
> Ok.
> 
>>> --- gcc/cp/decl.c.jj	2019-05-20 14:52:26.871375569 +0200
>>> +++ gcc/cp/decl.c	2019-05-20 15:48:33.563599150 +0200
>>> +      && (DECL_NAMESPACE_SCOPE_P (decl) || TREE_STATIC (decl)))
>>> +	      if (TREE_STATIC (v[i]))
>>
>> When can a structured binding not be TREE_STATIC?
> 
> All the block scope structured bindings that aren't explicitly static
> nor thread_local are not TREE_STATIC

Right, of course!

> As extern isn't allowed (yet), perhaps all DECL_NAMESPACE_SCOPE_P (decl)
> structured bindings are TREE_STATIC and I could replace the
> DECL_NAMESPACE_SCOPE_P (decl) test in cp_maybe_mangle_decomp
> with TREE_STATIC (decl) instead.

OK with that change.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-05-28 14:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-20 21:44 [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jakub Jelinek
2019-05-27 13:55 ` Patch ping (was Re: [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls) Jakub Jelinek
2019-05-28 14:19 ` [C++ PATCH] P1091R3 - Extending structured bindings to be more like var decls Jason Merrill
2019-05-28 14:47   ` Jakub Jelinek
2019-05-28 15:01     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).