When we have
using foo<T>::operator T...;
tsubst_decl/USING_DECL calls tsubst_pack_expansion twice and
then builds up a USING_DECL via do_class_using_decl. But we
crash here with
using foo<T>::operator T...;
using foo<T>::operator T*...;
because tsubst/TEMPLATE_TYPE_PARM gets an identifier node for
__conv_op which is not TYPE_P.
When we are substituting the first using, args is
<tree_vec 0x7fffe99c6e20 length:1
elt:0 <type_argument_pack 0x7fffe99e6690
type <tree_vec 0x7fffe99c6e40 length:1 elt:0 <integer_type 0x7fffe98235e8 int>>
VOID
align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffe99e6690>>
and tsubst_pack_expansion gives us
<tree_vec 0x7fffe99c6e40 length:1
elt:0 <integer_type 0x7fffe98235e8 int public type_6 SI
size <integer_cst 0x7fffe981b528 constant 32>
unit-size <integer_cst 0x7fffe981b540 constant 4>
align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffe98235e8 precision:32 min <integer_cst 0x7fffe981b4e0 -
2147483648> max <integer_cst 0x7fffe981b4f8
2147483647>
pointer_to_this <pointer_type 0x7fffe982ab28>>>
Note that the tree_vecs are the same one. So when we rewrite the
arguments from tsubst_pack_expansion using make_conv_op_name, we
also rewrite args.
PR c++/125284
PR c++/125333
gcc/cp/ChangeLog:
* pt.cc (tsubst_decl) <case USING_DECL>: Copy targs before
modifying them.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/using-variadic4.C: New test.
* g++.dg/cpp1z/using-variadic5.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
r = error_mark_node;
break;
}
+ name = copy_node (name);
for (tree& elt : tree_vec_range (name))
elt = make_conv_op_name (elt);
variadic_p = true;
--- /dev/null
+// PR c++/125284
+// { dg-do compile { target c++17 } }
+
+template<typename T>
+struct foo {
+ operator T();
+ operator T*();
+};
+
+template<typename... T>
+struct bar : foo<T>... {
+ using foo<T>::operator T...;
+ using foo<T>::operator T*...;
+};
+
+bar<int> z;
--- /dev/null
+// PR c++/125333
+// { dg-do compile { target c++17 } }
+
+template<typename... T>
+struct X {};
+
+template <typename U>
+struct Y {
+ operator U();
+};
+
+template <typename... V>
+struct Z : Y<V>... {
+ using Y<V>::operator V...;
+
+ X<V...> x;
+};
+
+Z<int, double> z;