https://gcc.gnu.org/g:e28d144e3492b93b5b09e365439758e7403a16d2

commit r17-651-ge28d144e3492b93b5b09e365439758e7403a16d2
Author: Marek Polacek <[email protected]>
Date:   Wed May 20 16:52:12 2026 -0400

    c++: ICE with variadic using-decl with conv fn [PR125284]
    
    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 <[email protected]>

Diff:
---
 gcc/cp/pt.cc                                 |  1 +
 gcc/testsuite/g++.dg/cpp1z/using-variadic4.C | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/cpp1z/using-variadic5.C | 19 +++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d19864774a3c..91aa9f556022 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -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
index 000000000000..1c0728e20817
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/using-variadic4.C
@@ -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
index 000000000000..88b03373bae6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/using-variadic5.C
@@ -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;

Reply via email to