]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: ICE with variadic using-decl with conv fn [PR125284]
authorMarek Polacek <polacek@redhat.com>
Wed, 20 May 2026 20:52:12 +0000 (16:52 -0400)
committerMarek Polacek <polacek@redhat.com>
Thu, 21 May 2026 15:49:50 +0000 (11:49 -0400)
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>
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp1z/using-variadic4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/using-variadic5.C [new file with mode: 0644]

index d19864774a3c4adc79f108c556c6f1ee7cdbe8ba..91aa9f5560228f8b42d258ff817fed4334e62832 100644 (file)
@@ -16086,6 +16086,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
                  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;
diff --git a/gcc/testsuite/g++.dg/cpp1z/using-variadic4.C b/gcc/testsuite/g++.dg/cpp1z/using-variadic4.C
new file mode 100644 (file)
index 0000000..1c0728e
--- /dev/null
@@ -0,0 +1,16 @@
+// 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;
diff --git a/gcc/testsuite/g++.dg/cpp1z/using-variadic5.C b/gcc/testsuite/g++.dg/cpp1z/using-variadic5.C
new file mode 100644 (file)
index 0000000..88b0337
--- /dev/null
@@ -0,0 +1,19 @@
+// 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;