This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.

--- 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 } }
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]