PR c++/93286 - ICE with __is_constructible and variadic template.
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. * pt.c (tsubst) [TREE_LIST]: Handle pack expansion. (tsubst_copy_and_build) [TRAIT_EXPR]: Always use tsubst for type2.
This commit is contained in:
parent
1113de9499
commit
5194b51ed9
3 changed files with 89 additions and 7 deletions
|
@ -1,5 +1,9 @@
|
|||
2020-01-16 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/93286 - ICE with __is_constructible and variadic template.
|
||||
* pt.c (tsubst) [TREE_LIST]: Handle pack expansion.
|
||||
(tsubst_copy_and_build) [TRAIT_EXPR]: Always use tsubst for type2.
|
||||
|
||||
PR c++/93280 - ICE with aggregate assignment and DMI.
|
||||
* init.c (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P here.
|
||||
* typeck2.c (digest_nsdmi_init): Not here.
|
||||
|
|
74
gcc/cp/pt.c
74
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));
|
||||
}
|
||||
|
|
18
gcc/testsuite/g++.dg/ext/is_constructible4.C
Normal file
18
gcc/testsuite/g++.dg/ext/is_constructible4.C
Normal file
|
@ -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);
|
||||
}
|
Loading…
Add table
Reference in a new issue