diff mbox

[C++] Fix ICE in invalid decomposition (PR c++/79372)

Message ID 20170206193405.GO1849@tucnak
State New
Headers show

Commit Message

Jakub Jelinek Feb. 6, 2017, 7:34 p.m. UTC
Hi!

The following patch fixes ICE when cp_finish_decomp already when parsing
template manages to diagnose the decomposition as errorneous, then
the types of all the decls for the decomp identifiers are all
error_mark_node, but they don't have DECL_VALUE_EXPR tsubst_decl_names
has been asserting.  Fixed thusly, bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk?

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

	PR c++/79372
	* decl.c (cp_finish_decomp): On error set decl type to error_mark_node.
	* pt.c (tsubst_expr): Don't call tsubst_decomp_names on decompositions
	with error_mark_node type.

	* g++.dg/cpp1z/decomp25.C: New test.


	Jakub

Comments

Jason Merrill Feb. 6, 2017, 7:53 p.m. UTC | #1
OK.

On Mon, Feb 6, 2017 at 2:34 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> The following patch fixes ICE when cp_finish_decomp already when parsing
> template manages to diagnose the decomposition as errorneous, then
> the types of all the decls for the decomp identifiers are all
> error_mark_node, but they don't have DECL_VALUE_EXPR tsubst_decl_names
> has been asserting.  Fixed thusly, bootstrapped/regtested on x86_64-linux
> and i686-linux, ok for trunk?
>
> 2017-02-06  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/79372
>         * decl.c (cp_finish_decomp): On error set decl type to error_mark_node.
>         * pt.c (tsubst_expr): Don't call tsubst_decomp_names on decompositions
>         with error_mark_node type.
>
>         * g++.dg/cpp1z/decomp25.C: New test.
>
> --- gcc/cp/decl.c.jj    2017-01-31 09:26:02.000000000 +0100
> +++ gcc/cp/decl.c       2017-02-06 18:02:02.115840352 +0100
> @@ -7378,6 +7378,7 @@ cp_finish_decomp (tree decl, tree first,
>             }
>           first = DECL_CHAIN (first);
>         }
> +      TREE_TYPE (decl) = error_mark_node;
>        if (DECL_P (decl) && DECL_NAMESPACE_SCOPE_P (decl))
>         SET_DECL_ASSEMBLER_NAME (decl, get_identifier ("<decomp>"));
>        return;
> --- gcc/cp/pt.c.jj      2017-02-03 23:35:37.000000000 +0100
> +++ gcc/cp/pt.c 2017-02-06 18:12:17.533828738 +0100
> @@ -15765,7 +15765,9 @@ tsubst_expr (tree t, tree args, tsubst_f
>                       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))
> +                   if (VAR_P (decl)
> +                       && DECL_DECOMPOSITION_P (decl)
> +                       && TREE_TYPE (pattern_decl) != error_mark_node)
>                       {
>                         unsigned int cnt;
>                         tree first;
> --- gcc/testsuite/g++.dg/cpp1z/decomp25.C.jj    2017-02-06 18:03:40.318562362 +0100
> +++ gcc/testsuite/g++.dg/cpp1z/decomp25.C       2017-02-06 18:15:37.000000000 +0100
> @@ -0,0 +1,20 @@
> +// PR c++/79372
> +// { dg-do compile { target c++11 } }
> +// { dg-options "" }
> +
> +template <typename T>
> +struct S
> +{
> +  enum E { A };
> +  void f () { auto [x] = 0; x++; }     // { dg-error "cannot decompose non-array non-class type" }
> +                                       // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
> +  void g (T t) { auto [y] = t; y++; }  // { dg-error "cannot decompose non-array non-class type" }
> +};                                     // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
> +
> +int
> +main ()
> +{
> +  S <int> s;
> +  s.f ();
> +  s.g (5);
> +}
>
>         Jakub
diff mbox

Patch

--- gcc/cp/decl.c.jj	2017-01-31 09:26:02.000000000 +0100
+++ gcc/cp/decl.c	2017-02-06 18:02:02.115840352 +0100
@@ -7378,6 +7378,7 @@  cp_finish_decomp (tree decl, tree first,
 	    }
 	  first = DECL_CHAIN (first);
 	}
+      TREE_TYPE (decl) = error_mark_node;
       if (DECL_P (decl) && DECL_NAMESPACE_SCOPE_P (decl))
 	SET_DECL_ASSEMBLER_NAME (decl, get_identifier ("<decomp>"));
       return;
--- gcc/cp/pt.c.jj	2017-02-03 23:35:37.000000000 +0100
+++ gcc/cp/pt.c	2017-02-06 18:12:17.533828738 +0100
@@ -15765,7 +15765,9 @@  tsubst_expr (tree t, tree args, tsubst_f
 		      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))
+		    if (VAR_P (decl)
+			&& DECL_DECOMPOSITION_P (decl)
+			&& TREE_TYPE (pattern_decl) != error_mark_node)
 		      {
 			unsigned int cnt;
 			tree first;
--- gcc/testsuite/g++.dg/cpp1z/decomp25.C.jj	2017-02-06 18:03:40.318562362 +0100
+++ gcc/testsuite/g++.dg/cpp1z/decomp25.C	2017-02-06 18:15:37.000000000 +0100
@@ -0,0 +1,20 @@ 
+// PR c++/79372
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+struct S
+{
+  enum E { A };
+  void f () { auto [x] = 0; x++; }	// { dg-error "cannot decompose non-array non-class type" }
+					// { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+  void g (T t) { auto [y] = t; y++; }	// { dg-error "cannot decompose non-array non-class type" }
+};					// { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+
+int
+main ()
+{
+  S <int> s;
+  s.f ();
+  s.g (5);
+}