* [C++ PATCH] PR c++/93286 - ICE with __is_constructible and variadic template.
@ 2020-01-17 7:03 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2020-01-17 7:03 UTC (permalink / raw)
To: gcc-patches
Here we had been recursing in tsubst_copy_and_build if type2 was a TREE_LIST
because that function knew how to deal with pack expansions, and tsubst
didn't. But tsubst_copy_and_build expects to be dealing with expressions,
so we crash when trying to convert_from_reference a type.
Tested x86_64-pc-linux-gnu, applying to trunk.
* pt.c (tsubst) [TREE_LIST]: Handle pack expansion.
(tsubst_copy_and_build) [TRAIT_EXPR]: Always use tsubst for type2.
---
gcc/cp/pt.c | 74 ++++++++++++++++++--
gcc/testsuite/g++.dg/ext/is_constructible4.C | 18 +++++
2 files changed, 85 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/ext/is_constructible4.C
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9bb8cc13e5f..872f8ff8f52 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15350,6 +15350,71 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (t == void_list_node)
return t;
+ if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
+ || (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
+ {
+ /* We have pack expansions, so expand those and
+ create a new list out of it. */
+
+ /* Expand the argument expressions. */
+ tree purposevec = NULL_TREE;
+ if (TREE_PURPOSE (t))
+ purposevec = tsubst_pack_expansion (TREE_PURPOSE (t), args,
+ complain, in_decl);
+ if (purposevec == error_mark_node)
+ return error_mark_node;
+
+ tree valuevec = NULL_TREE;
+ if (TREE_VALUE (t))
+ valuevec = tsubst_pack_expansion (TREE_VALUE (t), args,
+ complain, in_decl);
+ if (valuevec == error_mark_node)
+ return error_mark_node;
+
+ /* Build the rest of the list. */
+ tree chain = TREE_CHAIN (t);
+ if (chain && chain != void_type_node)
+ chain = tsubst (chain, args, complain, in_decl);
+ if (chain == error_mark_node)
+ return error_mark_node;
+
+ /* Determine the number of arguments. */
+ int len = -1;
+ if (purposevec && TREE_CODE (purposevec) == TREE_VEC)
+ {
+ len = TREE_VEC_LENGTH (purposevec);
+ gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
+ }
+ else if (TREE_CODE (valuevec) == TREE_VEC)
+ len = TREE_VEC_LENGTH (valuevec);
+ else
+ {
+ /* Since we only performed a partial substitution into
+ the argument pack, we only RETURN (a single list
+ node. */
+ if (purposevec == TREE_PURPOSE (t)
+ && valuevec == TREE_VALUE (t)
+ && chain == TREE_CHAIN (t))
+ return t;
+
+ return tree_cons (purposevec, valuevec, chain);
+ }
+
+ /* Convert the argument vectors into a TREE_LIST. */
+ for (int i = len; i-- > 0; )
+ {
+ purpose = (purposevec ? TREE_VEC_ELT (purposevec, i)
+ : NULL_TREE);
+ value = (valuevec ? TREE_VEC_ELT (valuevec, i)
+ : NULL_TREE);
+
+ /* Build the list (backwards). */
+ chain = hash_tree_cons (purpose, value, chain);
+ }
+
+ return chain;
+ }
+
purpose = TREE_PURPOSE (t);
if (purpose)
{
@@ -20158,13 +20223,8 @@ tsubst_copy_and_build (tree t,
{
tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args,
complain, in_decl);
-
- tree type2 = TRAIT_EXPR_TYPE2 (t);
- if (type2 && TREE_CODE (type2) == TREE_LIST)
- type2 = RECUR (type2);
- else if (type2)
- type2 = tsubst (type2, args, complain, in_decl);
-
+ tree type2 = tsubst (TRAIT_EXPR_TYPE2 (t), args,
+ complain, in_decl);
RETURN (finish_trait_expr (TRAIT_EXPR_LOCATION (t),
TRAIT_EXPR_KIND (t), type1, type2));
}
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible4.C b/gcc/testsuite/g++.dg/ext/is_constructible4.C
new file mode 100644
index 00000000000..6dfe3c01661
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible4.C
@@ -0,0 +1,18 @@
+// PR c++/93286
+// { dg-do compile { target c++14 } }
+
+struct A { static const bool value = true; };
+template <bool> using __bool_constant = A;
+template <typename... _Args>
+struct B : __bool_constant<__is_constructible(int, _Args...)> {};
+template <bool> using enable_if_t = int;
+template <typename... _Args> bool is_constructible_v = B<_Args...>::value;
+class C {
+ template <typename _Tp, typename = enable_if_t<is_constructible_v<_Tp>>>
+ C(_Tp &&);
+};
+using Effect_t = C;
+void fn1(Effect_t effect) {
+ int i;
+ [](int &effect) {}(i);
+}
base-commit: 801f5b96775288e55193a66a746caab1ddd56f4a
--
2.18.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-01-17 3:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-17 7:03 [C++ PATCH] PR c++/93286 - ICE with __is_constructible and variadic template Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).