diff mbox

[C++] Fix decomp ICEs in templates (PR c++/80370)

Message ID 20170410203502.GJ1809@tucnak
State New
Headers show

Commit Message

Jakub Jelinek April 10, 2017, 8:35 p.m. UTC
Hi!

The following testcase ICEs, because when cp_finish_decomp is called
during parsing with processing_template_decl, but decl is not type
dependent, we finalize it at that point and when we try to do it again
during tsubst time, it doesn't find the expected trees (e.g. DECL_VALUE_EXPR
of the expected form on the corresponding user decls).

The following patch changes cp_finish_decomp processing_template_decl
handling when decl is not type dependent, such that it performs diagnostics
and sets types on the individual decls, but doesn't otherwise finalize them
(modify their DECL_VALUE_EXPR or clear them and cp_finish_decl them).

I think this way we can treat the decls as no longer type dependent, but
will let the final decomp finalization still to tsubst time.

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

2017-04-10  Jakub Jelinek  <jakub@redhat.com>

	PR c++/80370
	* decl.c (cp_finish_decomp): If processing_template_decl on
	non-dependent decl, only set TREE_TYPE on the v[i] decls, but don't
	change their DECL_VALUE_EXPR nor cp_finish_decl them.  Instead make
	sure DECL_VALUE_EXPR is the canonical NULL type ARRAY_REF for tsubst
	processing.
	* constexpr.c (cxx_eval_constant_expression) <case VAR_DECL>: Don't
	recurse on DECL_VALUE_EXPR if the value expr has NULL type on a
	decomposition decl.

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


	Jakub

Comments

Jason Merrill April 10, 2017, 8:48 p.m. UTC | #1
On Mon, Apr 10, 2017 at 4:35 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> -         store_decomp_type (v[i], eltype);
> +         if (!processing_template_decl)
> +           store_decomp_type (v[i], eltype);

This spot shouldn't change; we do want to remember the decltype even
in a template.

> @@ -3935,7 +3935,10 @@ cxx_eval_constant_expression (const cons
>        return (*ctx->values->get (t));
>
>      case VAR_DECL:
> -      if (DECL_HAS_VALUE_EXPR_P (t))
> +      if (DECL_HAS_VALUE_EXPR_P (t)
> +         /* Don't recurse on DECL_VALUE_EXPR of decomposition decls
> +            that have not been finalized yet.  */
> +         && (!DECL_DECOMPOSITION_P (t) || TREE_TYPE (DECL_VALUE_EXPR (t))))

Hmm, we shouldn't get here in this case.  I think
value_dependent_expression_p should return true for a VAR_DECL with
type-dependent DECL_VALUE_EXPR.

Jason
Jakub Jelinek April 10, 2017, 8:52 p.m. UTC | #2
On Mon, Apr 10, 2017 at 04:48:43PM -0400, Jason Merrill wrote:
> On Mon, Apr 10, 2017 at 4:35 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> > -         store_decomp_type (v[i], eltype);
> > +         if (!processing_template_decl)
> > +           store_decomp_type (v[i], eltype);
> 
> This spot shouldn't change; we do want to remember the decltype even
> in a template.

Ok.

> > @@ -3935,7 +3935,10 @@ cxx_eval_constant_expression (const cons
> >        return (*ctx->values->get (t));
> >
> >      case VAR_DECL:
> > -      if (DECL_HAS_VALUE_EXPR_P (t))
> > +      if (DECL_HAS_VALUE_EXPR_P (t)
> > +         /* Don't recurse on DECL_VALUE_EXPR of decomposition decls
> > +            that have not been finalized yet.  */
> > +         && (!DECL_DECOMPOSITION_P (t) || TREE_TYPE (DECL_VALUE_EXPR (t))))
> 
> Hmm, we shouldn't get here in this case.  I think
> value_dependent_expression_p should return true for a VAR_DECL with
> type-dependent DECL_VALUE_EXPR.

Will try that tomorrow.

	Jakub
diff mbox

Patch

--- gcc/cp/decl.c.jj	2017-03-30 15:24:22.000000000 +0200
+++ gcc/cp/decl.c	2017-04-10 12:15:44.156022403 +0200
@@ -7473,6 +7473,8 @@  cp_finish_decomp (tree decl, tree first,
 	{
 	  TREE_TYPE (v[i]) = eltype;
 	  layout_decl (v[i], 0);
+	  if (processing_template_decl)
+	    continue;
 	  tree t = unshare_expr (dexp);
 	  t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF,
 			  eltype, t, size_int (i), NULL_TREE,
@@ -7492,6 +7494,8 @@  cp_finish_decomp (tree decl, tree first,
 	{
 	  TREE_TYPE (v[i]) = eltype;
 	  layout_decl (v[i], 0);
+	  if (processing_template_decl)
+	    continue;
 	  tree t = unshare_expr (dexp);
 	  t = build1_loc (DECL_SOURCE_LOCATION (v[i]),
 			  i ? IMAGPART_EXPR : REALPART_EXPR, eltype,
@@ -7510,6 +7514,8 @@  cp_finish_decomp (tree decl, tree first,
 	{
 	  TREE_TYPE (v[i]) = eltype;
 	  layout_decl (v[i], 0);
+	  if (processing_template_decl)
+	    continue;
 	  tree t = unshare_expr (dexp);
 	  convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]),
 						 &t, size_int (i));
@@ -7549,7 +7555,8 @@  cp_finish_decomp (tree decl, tree first,
 	      goto error_out;
 	    }
 	  /* Save the decltype away before reference collapse.  */
-	  store_decomp_type (v[i], eltype);
+	  if (!processing_template_decl)
+	    store_decomp_type (v[i], eltype);
 	  eltype = cp_build_reference_type (eltype, !lvalue_p (init));
 	  TREE_TYPE (v[i]) = eltype;
 	  layout_decl (v[i], 0);
@@ -7559,8 +7566,9 @@  cp_finish_decomp (tree decl, tree first,
 	      SET_DECL_VALUE_EXPR (v[i], NULL_TREE);
 	      DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
 	    }
-	  cp_finish_decl (v[i], init, /*constexpr*/false,
-			  /*asm*/NULL_TREE, LOOKUP_NORMAL);
+	  if (!processing_template_decl)
+	    cp_finish_decl (v[i], init, /*constexpr*/false,
+			    /*asm*/NULL_TREE, LOOKUP_NORMAL);
 	}
     }
   else if (TREE_CODE (type) == UNION_TYPE)
@@ -7615,12 +7623,26 @@  cp_finish_decomp (tree decl, tree first,
 	      tt = TREE_OPERAND (tt, 0);
 	    TREE_TYPE (v[i]) = TREE_TYPE (tt);
 	    layout_decl (v[i], 0);
-	    SET_DECL_VALUE_EXPR (v[i], tt);
-	    DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
+	    if (!processing_template_decl)
+	      {
+		SET_DECL_VALUE_EXPR (v[i], tt);
+		DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
+	      }
 	    i++;
 	  }
     }
-  if (DECL_NAMESPACE_SCOPE_P (decl))
+  if (processing_template_decl)
+    {
+      for (unsigned int i = 0; i < count; i++)
+	if (!DECL_HAS_VALUE_EXPR_P (v[i]))
+	  {
+	    tree a = build_nt (ARRAY_REF, decl, size_int (i),
+			       NULL_TREE, NULL_TREE);
+	    SET_DECL_VALUE_EXPR (v[i], a);
+	    DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
+	  }
+    }
+  else if (DECL_NAMESPACE_SCOPE_P (decl))
     SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
 }
 
--- gcc/cp/constexpr.c.jj	2017-03-21 07:57:00.000000000 +0100
+++ gcc/cp/constexpr.c	2017-04-10 12:24:11.849717112 +0200
@@ -3935,7 +3935,10 @@  cxx_eval_constant_expression (const cons
       return (*ctx->values->get (t));
 
     case VAR_DECL:
-      if (DECL_HAS_VALUE_EXPR_P (t))
+      if (DECL_HAS_VALUE_EXPR_P (t)
+	  /* Don't recurse on DECL_VALUE_EXPR of decomposition decls
+	     that have not been finalized yet.  */
+	  && (!DECL_DECOMPOSITION_P (t) || TREE_TYPE (DECL_VALUE_EXPR (t))))
 	return cxx_eval_constant_expression (ctx, DECL_VALUE_EXPR (t),
 					     lval, non_constant_p, overflow_p);
       /* fall through */
--- gcc/testsuite/g++.dg/cpp1z/decomp28.C.jj	2017-04-10 11:40:39.209346743 +0200
+++ gcc/testsuite/g++.dg/cpp1z/decomp28.C	2017-04-10 11:42:15.939128016 +0200
@@ -0,0 +1,39 @@ 
+// PR c++/80370
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+namespace std {
+  template <typename> struct tuple_size;
+  template <long, typename> struct tuple_element;
+  template <typename...> struct tuple {};
+  template <typename... T> struct tuple_size<tuple<T...>> { static constexpr int value = 1; };
+  template <typename T, typename... U> struct tuple_element<0, tuple<T, U...>> { typedef T type; };
+  template <int, typename... T> int& get (tuple<T...>);
+}
+
+template <int N>
+void
+foo (std::tuple<int> b)
+{
+  auto [c] = b;		// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+}
+
+template <typename T>
+void
+bar (std::tuple<T> b)
+{
+  auto [c] = b;		// { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+}
+
+void
+baz (std::tuple<int> b)
+{
+  foo <5> (b);
+  bar (b);
+}
+
+int
+main ()
+{
+  [](auto) { [](std::tuple<int> b) { auto[c] = b; }; } (0); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+}