This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix decomp ICEs in templates (PR c++/80370)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 10 Apr 2017 22:35:02 +0200
- Subject: [C++ PATCH] Fix decomp ICEs in templates (PR c++/80370)
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 525F281236
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 525F281236
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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