<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56099>56099</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Clang: Incomplete representation of type sugar for expanded argument packs in the AST.
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:frontend
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            mizvekov
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mizvekov
      </td>
    </tr>
</table>

<pre>
    When expanding template argument packs, clang does not synthesize TemplateTypeParmTypes for the SubstTemplateTypeParmTypes which correspond to the argument's position in the expanded form.

Consider example 1: https://godbolt.org/z/KvMTbh5T7
```C++
template <typename... As> struct Y;
template <typename ...Bs> using Z = Y<Bs...>;
template <typename ...Cs> struct foo {
  template <typename ...Ds> using bind = Z<Ds..., Cs...>;
};
using U = foo<int, short>::bind<char, float>;
```
AST:
```
TemplateSpecializationType 0x559e6e0cafa0 'Y<char, float, int, short>' sugar Y
          |-TemplateArgument type 'char':'char'
          | `-SubstTemplateTypeParmType 0x559e6e0cada0 'char' sugar
          |   |-TemplateTypeParmType 0x559e6e0acb60 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
          |   | `-TemplateTypeParm 0x559e6e0acb08 'Bs'
          |   `-BuiltinType 0x559e6e066e80 'char'
          |-TemplateArgument type 'float':'float'
          | `-SubstTemplateTypeParmType 0x559e6e0cade0 'float' sugar
          |   |-TemplateTypeParmType 0x559e6e0acb60 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
          |   | `-TemplateTypeParm 0x559e6e0acb08 'Bs'
          |   `-BuiltinType 0x559e6e066fe0 'float'
          |-TemplateArgument type 'int':'int'
          | `-SubstTemplateTypeParmType 0x559e6e0ca810 'int' sugar
          |   |-TemplateTypeParmType 0x559e6e0acb60 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
          |   | `-TemplateTypeParm 0x559e6e0acb08 'Bs'
          |   `-BuiltinType 0x559e6e066ee0 'int'
          |-TemplateArgument type 'short':'short'
          | `-SubstTemplateTypeParmType 0x559e6e0ca850 'short' sugar
          |   |-TemplateTypeParmType 0x559e6e0acb60 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
          |   | `-TemplateTypeParm 0x559e6e0acb08 'Bs'
          |   `-BuiltinType 0x559e6e066ec0 'short'
          `-RecordType 0x559e6e0caf80 'Y<char, float, int, short>'
            `-ClassTemplateSpecialization 0x559e6e0cae98 'Y'
```

Example 2: https://godbolt.org/z/r7v8hYdKx
```C++
template<typename ...T> struct D {
  template<typename... U> using B = int(int (*...p)(T, U));
  template<typename U1, typename U2> D(B<U1, U2>*);
};
using foo = D<float, char>::B<int, short>;
```
AST:
```
FunctionProtoType 0x564b6179e8e0 'int (int (*)(float, int), int (*)(char, short))' cdecl
        |-BuiltinType 0x564b61738ee0 'int'
        |-PointerType 0x564b6179e620 'int (*)(float, int)'
        | `-ParenType 0x564b6179e5c0 'int (float, int)' sugar
        |   `-FunctionProtoType 0x564b6179e580 'int (float, int)' cdecl
        |     |-BuiltinType 0x564b61738ee0 'int'
        |     |-SubstTemplateTypeParmType 0x564b6179cef0 'float' sugar
        |     | |-TemplateTypeParmType 0x564b6177e6b0 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
        |     | | `-TemplateTypeParm 0x564b6177e630 'T'
        |     | `-BuiltinType 0x564b61738fe0 'float'
        |     `-SubstTemplateTypeParmType 0x564b6179e500 'int' sugar
        |       |-TemplateTypeParmType 0x564b6179c750 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
        |       | `-TemplateTypeParm 0x564b6179c6f8 'U'
        |       `-BuiltinType 0x564b61738ee0 'int'
        `-PointerType 0x564b6179e830 'int (*)(char, short)'
          `-ParenType 0x564b6179e7d0 'int (char, short)' sugar
            `-FunctionProtoType 0x564b6179e790 'int (char, short)' cdecl
              |-BuiltinType 0x564b61738ee0 'int'
              |-SubstTemplateTypeParmType 0x564b6179dd90 'char' sugar
              | |-TemplateTypeParmType 0x564b6177e6b0 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
              | | `-TemplateTypeParm 0x564b6177e630 'T'
              | `-BuiltinType 0x564b61738e80 'char'
              `-SubstTemplateTypeParmType 0x564b6179e710 'short' sugar
                |-TemplateTypeParmType 0x564b6179c750 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
                | `-TemplateTypeParm 0x564b6179c6f8 'U'
                `-BuiltinType 0x564b61738ec0 'short'
```

The TemplateTypeParmType's used are the original ones from the packed template argument, and as such it's pretty hard to map these to the argument list as-written.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzlWFtvozgU_jXkxWpEoOHykIeETKXVaKVqm2rVeRkZ2wneITjCJtP21--xuQQIuU1Huw-t0gSwz3cO3znHfDgW9G32d8IyxF53OKM82yDFtrsUK4Zwvim2LFNoh8kPaTkRIimGCVQwiTKhkHzLVMIkf2doVRmt3nbsEedb_SvRWuQIZqCnIpZqeMrPhJMEEZHnTO5ERpESxqR2bjm-RDshueIiQzwzg2WwjGoH27FlLy17Xn5HIpOcshymYHDH0MRy5yhRaifhwHIe4LMRNBapGot8A2fv8P91_-cqTqYrv4Ly7PITWc5Cf8zVhhfLjRTEnuEtG4_HaA7IX5BUeUEUerHcM9MRzF-Y6YXUVH-DwaW2iRYShmDgonnU9rYWAll-ZYHQKZtly2XMgWPt9RtMWhqvkNio797yl81xafhsrMAj2HGdlwjJROTKWM3ho5FhjCQ414PrVGDVgaxZLU_nTyttNzRUV8rTjhGOU_6OdfJ1vSD7dToNmcdsgtfYRlAdL0c-4aAfoOMjWWxwDlxXXNV_lh_d1f7mdcFr8jR2ieubymlOjgEQRH53ssbbMdMy5gqqjGkIsBvXMBomsWfQoKIAizJIONXRE5EpzDP5vcjqRvmuW1hPUQmygR3KXuFXXzzp3dxUP4KOdztovJ9AAYRFwVPFe8nzPBa0ibgpKVWSq6w0Zx9KC7PbyJ84L-suEzclxjRdlZbq-CNJCSb2AfUTp4SxFg83JaRc_uqUNGcfSsrUbiN_5rSQDhNH9mD5FwNdQ4-eW8Etz60-bokcpVjK4cdk2xULg9KV01c2bc30pZJKzjVSKff3QfJCv75eI5V6OmTVki7LIeHSU1bPB9myMOrD0BPAN9xVYDlzmLSznBBOVpq2Z3McNopjEBg9T_Tcw6mjvSwBYwGzykFzDfDbYMeKyKgviAquR00GTUprSbQY0ko3y6GHIiM6s4-5UKKuJu8-9iZ-yIJmdUAdakpauoUVVkedKXUNVoVsCIRmJJSRtFt8uqF7zVBG4QZn1iht9ShghOX92D2nHfvpoI8RTRNAO7OsjzklbcxjqKEV69DrZ6meBheghzn7GHeN9dnluQqRsPVFIdPCPLtEl5A-82IDufptK3QvgJOrdBOA2wRwBuh4oa75PStpGoxLD8CmCOwLqqRGPP8ArBPml8_T59_O7vknYO3eWwe1-5Mwp5k9V7m6P4e7PnAHu_54HRp8pg42vU_bkANIwzrlip73w0vIA01_SP_txB1srylHSsPLL5T_a7d33P96r3dL-hStZ18q63xf1eb-5Aqde8jVf97mfUZ-qcnbrJyidEjlDqrIVTK8C2g28ArJKILONbt3IucbnuEUiUzvEeZiay7rm4RZR9uPuuGAG4QlZIEkiFd7gjlT6g1Brs2e4RbvNIpk_Q1ElHKpwPjuZ86VYtl4RGcuDd0QjxRXKZtFelNTS98_MiK0EAbfOQN4CdalpBbr8p2q3EPSu5rNDmR3k7TeoAQ1Nx4VeTrryWmukiIegxs4SdN9_XO3y8U_jMCNPXApCwYvJA9Tzw7DUTK7n8YhWVPbtz069b1JTNxgsvZYEOCY-p4zSnHMUjmzpqC_HVLdDLAKa29G4ZI1XY74zLEdx_YmgT1x721_TCbMDdfEZyEJXUpC695mW8zTsQ5Hy_1RPjORxcVGwqAmUR4G4e2DbzLGKq9b_r5nP8S-8oYLBfUyq6-OzD3NzA39C1Cpf2c">