diff mbox

[C++] Fix decomp ICE with invalid initializer (PR c++/81258)

Message ID 20170630172424.GN2123@tucnak
State New
Headers show

Commit Message

Jakub Jelinek June 30, 2017, 5:24 p.m. UTC
Hi!

The initializer for structured binding has to be one of:
= assignment-expression
( assignment-expression )
{ assignment-expression }
but cp_parser_initializer can parse other forms, with fewer or more
expressions in there.  Some cases we caught with various cryptic errors
or pedwarns, but others we just ICEd on.

The following patch attempts to check this.

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

2017-06-30  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81258
	* parser.c (cp_parser_decomposition_declaration): Diagnose invalid
	forms of structured binding initializers.

	* g++.dg/cpp1z/decomp21.C (foo): Adjust expected diagnostics.
	* g++.dg/cpp1z/decomp30.C: New test.


	Jakub

Comments

Nathan Sidwell June 30, 2017, 5:38 p.m. UTC | #1
On 06/30/2017 01:24 PM, Jakub Jelinek wrote:

> The initializer for structured binding has to be one of:
> = assignment-expression
> ( assignment-expression )
> { assignment-expression }
> but cp_parser_initializer can parse other forms, with fewer or more
> expressions in there.  Some cases we caught with various cryptic errors
> or pedwarns, but others we just ICEd on.
> 
> The following patch attempts to check this.

ok, but ...

> --- gcc/testsuite/g++.dg/cpp1z/decomp21.C.jj	2017-01-19 17:01:21.000000000 +0100
> +++ gcc/testsuite/g++.dg/cpp1z/decomp21.C	2017-06-30 11:07:04.786746784 +0200
> @@ -12,5 +12,5 @@ foo ()
>     auto [ n, o, p ] { a };
>     auto [ q, r, t ] ( s );
>     auto [ u, v, w ] ( s, );      // { dg-error "expected primary-expression before '.' token" }
> -  auto [ x, y, z ] ( a );       // { dg-error "expression list treated as compound expression in initializer" "" { target *-*-* } .-1 }
> +  auto [ x, y, z ] ( a );       // { dg-error "invalid initializer for structured binding" "" { target *-*-* } .-1 }
>   }

The .-1 on the final error is actually about the previous statement, not 
the line it's lexically on.  Could you put it on a line on its own, 
while you're there?
diff mbox

Patch

--- gcc/cp/parser.c.jj	2017-06-30 09:49:25.000000000 +0200
+++ gcc/cp/parser.c	2017-06-30 11:03:18.526521000 +0200
@@ -13196,6 +13196,15 @@  cp_parser_decomposition_declaration (cp_
       *init_loc = cp_lexer_peek_token (parser->lexer)->location;
       tree initializer = cp_parser_initializer (parser, &is_direct_init,
 						&non_constant_p);
+      if (initializer == NULL_TREE
+	  || (TREE_CODE (initializer) == TREE_LIST
+	      && TREE_CHAIN (initializer))
+	  || (TREE_CODE (initializer) == CONSTRUCTOR
+	      && CONSTRUCTOR_NELTS (initializer) != 1))
+	{
+	  error_at (loc, "invalid initializer for structured binding");
+	  initializer = error_mark_node;
+	}
 
       if (decl != error_mark_node)
 	{
--- gcc/testsuite/g++.dg/cpp1z/decomp21.C.jj	2017-01-19 17:01:21.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp1z/decomp21.C	2017-06-30 11:07:04.786746784 +0200
@@ -12,5 +12,5 @@  foo ()
   auto [ n, o, p ] { a };
   auto [ q, r, t ] ( s );
   auto [ u, v, w ] ( s, );      // { dg-error "expected primary-expression before '.' token" }
-  auto [ x, y, z ] ( a );       // { dg-error "expression list treated as compound expression in initializer" "" { target *-*-* } .-1 }
+  auto [ x, y, z ] ( a );       // { dg-error "invalid initializer for structured binding" "" { target *-*-* } .-1 }
 }
--- gcc/testsuite/g++.dg/cpp1z/decomp30.C.jj	2017-06-30 11:09:31.934942575 +0200
+++ gcc/testsuite/g++.dg/cpp1z/decomp30.C	2017-06-30 11:09:22.000000000 +0200
@@ -0,0 +1,12 @@ 
+// PR c++/81258
+// { dg-options -std=c++1z }
+
+int a[2];
+auto [b, c] (a);
+auto [d, e] { a };
+auto [f, g] = a;
+auto [h, i] ( a, a );	// { dg-error "invalid initializer for structured binding" }
+auto [j, k] { a, a };	// { dg-error "invalid initializer for structured binding" }
+auto [l, m] = { a };	// { dg-error "deducing from brace-enclosed initializer list requires" }
+auto [n, o] {};		// { dg-error "invalid initializer for structured binding" }
+auto [p, q] ();		// { dg-error "invalid initializer for structured binding" }