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

    <tr>
        <th>Summary</th>
        <td>
            Clang's error for missing `template` in `this->base_func<false>(args...)` is unusually terrible
        </td>
    </tr>

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

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

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

<pre>
    # Original repro: Derived class

The error for forgetting the `template` disambiguator here is unusually terrible - it confused me for a few minutes (and I know a thing or two about template errors):

```
C:\Temp>type meow.cpp
```
```cpp
template <typename T>
struct Base {
    template <bool B, typename Types>
 void base_func(Types...) {}
};

template <typename T>
struct Derived : Base<T> {
    template <typename... Types>
    void meow(Types... args) {
        this->/* OOPS, FORGOT template */ base_func<false>(args...);
    }
};

int main() {
 Derived<int> d;
    d.meow(3.14, 1729);
}
```
```
C:\Temp>clang-cl -v
clang version 17.0.3
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\Llvm\x64\bin

C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++latest meow.cpp
meow.cpp(11,64): error: expected ')'
   11 |         this->/* OOPS, FORGOT template */ base_func<false>(args...);
      | ^
meow.cpp(11,59): note: to match this '('
   11 |         this->/* OOPS, FORGOT template */ base_func<false>(args...);
 | ^
meow.cpp(11,9): error: expression contains unexpanded parameter pack 'args'
   11 |         this->/* OOPS, FORGOT template */ base_func<false>(args...);
      |         ^ ~~~~
2 errors generated.
```

# Altered repro: Function template

It's not specific to derived classes, here's an ordinary function template:

```
C:\Temp>type woof.cpp
```
```cpp
template <typename T>
struct Base {
 template <bool B, typename U>
    using NestedType = U;
};

template <typename T>
auto func() {
    using Ret = Base<T>::/* OOPS, FORGOT template */ NestedType<false, double>;
    return Ret{};
}

int main() {
 func<int>();
}
```
```
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++latest woof.cpp
woof.cpp(9,64): error: expected ';' after alias declaration
    9 |     using Ret = Base<T>::/* OOPS, FORGOT template */ NestedType<false, double>;
      | ^
      | ;
woof.cpp(9,54): error: typename specifier refers to alias template member in 'Base<int>'; argument deduction not allowed
 here
    9 |     using Ret = Base<T>::/* OOPS, FORGOT template */ NestedType<false, double>;
      | ^
woof.cpp(14,5): note: in instantiation of function template specialization 'func<int>' requested here
   14 |     func<int>();
 |     ^
woof.cpp(4,5): note: template is declared here
    4 | using NestedType = U;
      |     ^
2 errors generated.
```

# Non-type template parameter is relevant

If I remove the non-type template parameter `bool B`, then Clang is able to give the good diagnostics that I expect (they happen to be warnings instead of the errors that I deserve according to the Standard, I believe):

```
C:\Temp>type purr1.cpp
```
```cpp
template <typename T>
struct Base {
 template <typename Purr, typename Types>
    void base_func(Types...) {}
};

template <typename T>
struct Derived : Base<T> {
 template <typename... Types>
    void meow(Types... args) {
 this->/* OOPS, FORGOT template */ base_func<bool>(args...);
 }
};

int main() {
    Derived<int> d;
    d.meow(3.14, 1729);
}
```
```
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++latest purr1.cpp
purr1.cpp(11,43): warning: use 'template' keyword to treat 'base_func' as a dependent template name
   11 |         this->/* OOPS, FORGOT template */ base_func<bool>(args...);
      | ^
      | template
1 warning generated.

C:\Temp>type purr2.cpp
```
```cpp
template <typename T>
struct Base {
 template <typename Purr, typename U>
    using NestedType = U;
};

template <typename T>
auto func() {
    using Ret = Base<T>::/* OOPS, FORGOT template */ NestedType<bool, double>;
    return Ret{};
}

int main() {
 func<int>();
}
```
```
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++latest purr2.cpp
purr2.cpp(9,54): warning: use 'template' keyword to treat 'NestedType' as a dependent template name
    9 |     using Ret = Base<T>::/* OOPS, FORGOT template */ NestedType<bool, double>;
      | ^
      | template
1 warning generated.
```


</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkWE9z27gV_zTQ5Y00FCiK4kEHi7Zaz2zXmY27Pe6AxCOFDQiwACjZPeSzd0BSFC0rSpxmk51uJpYEAnj4vb-_BzJrRakQ1yTakOh2whq302b93mG9Y-rxJ7Zne_x9kmn-vCY0hAcjSqGYBIO10SS8gVs0Yo8ccsmsJcEtCW66z8cdAhqjDRTdX4nOCVWC2yGQZeCwqiVzSJYBcGFZlYmyYU4b2KFBEBYa1diGSfkMDo0RmUSYgnCQa1U0FjlU2MpmUOABKqEahxYIXTHF4R4-KH0ABm7nD9UG3EEDy3Tj4Hh0h88SmpDwZoydLIP-fztM_XSUPmJVk_DOPdcIFerDLK_ri-uH4bBgOJGEqd-vWIXwSMK7bto60-QONswikHjTPQQAGO_LtJawITSFk4TnGu0gBfZacMiYxd-KRuWErtr52WxGaNLKjW97gPEtCTdjjb8M4NHZ3vEeLAlTv-bTmI-iZrPZOViADq-35AgqMFPaI95hZSt3J-zU76dbQm_g4eHde2-M7cMvf3t4HJ1KbwjdjswQpgWTHuudDw1T9gYZDOBlX7GMUA4qJhShq5ewemOQMBXKeSvwFyL5rNcsnM0XHug8psn43NOZn4ieS8GXS6bKaS5huu-m2wewR2OFVjCPZ8Es7BOQ-ZTzrnpaLX9bLqZ1Pj0IxfXBTiu7z49papBxqDRH6dfW2oqnbupeWcekRH4rjJ_qkbwzujSsgq2QaEmU_kPkRltdOPhV-HyF967hQpMopQGl7QbcCzyQKP019ZpoLf2-n-S-IlH6tFyQKM2EGhv9E0oTur37u839t9JSl9r_-tfCf1rHSXiTE7ohdOMDwbqzJB1GdDWfE5ouF13id1Wg_fFUY-58fNPYz9F4cOd8DiRO4XvEIrQnkejuMuwo6WEr7dB_Ow0Vc_muBdVBX_0I6FdRJxdsbdC2QZtr5ZhQvuDjU80URw41M6xChwZqln_wWnV14Qd65PiPRHfw8ePHj9087UkESlRomEM-u5zV3ScN4UY6NMhPFLptVO68IQZKHO24d4TG1jsbbI25KETuPc7HtIvWq-pps13LFGjDhWLmGYpXst_KdAetiz-a6T5Dc_98wRqN9YT-M1qH3LMGkPDWL9l8JbexxmnoCfMV8XSH_YKuPWXEed5Q4c2XRdsJ6xBuNAWum0y2gTeONYOuMcqf2BP2a7q4Tkt9VHec1M1-I8p5Y_V9GTjDiK6SzxffcENoDKzwBYBJwSxwzCUzzMfyyVjJkJjf3U9nVXr06LjqTOPolcZDLPaJjQYMFmisT_BO6wFhhVWGBoTy5unVO7rYm8u3TU2FygFH3nQp72sGk1IfkPcg2xLxJ7TeyFRtrxSdUZxQIHwzopxoIwB08bqydWZkUvynW0NofJYLMRj8d9PCfGmK-WIwxbX0GRZdAn4J9wBNHAP4_GToTv5MTXtJQsPpb-een7WatlV9QHYiWmHBoMQ9U-4FARVwDwYrvcf26qauiCDLoC_fy6Ct4DtUkLYdqrDA_A3OaShFL6rUmgMXrFTaOpFbcDvm4L4vBf4m53b4DDtW16j8zgzhwIwSqrRtQPjOVRetrN4SvQSOFs0egeV5S4Wl3-2XvXdMcWa4R3cPGUqBe_yaC2DdGDP_nrw4bHrXGHPtFni8WP3Yi-A3vwV-fYPnQ_Ja2_r2qx_AD779vZGKz4L1NOy780XYF64-u_zPxkcijYe-kcbwAZ8P2vA2lwwyn6HxKMpiYBYYcKxRcU9Fg1O88799437dr9c4-mWjPT-q_bqOXst--ufI_v-r5rh16V-gNz6Ln9PwrFd8ez6OzPmlCfmHNoLXPfq_Z-ilTmfC1yFPwoRNcD2PgyhZBdEynOzWyWqZxyErFgkWcY5RHDIeh9FyNV9lSRGsJmJNA7oI5jQMQprQcBbFNFvliEmQLbJ8npNFgBUTciblvpppU06EtQ2u4yRYxRPJMpS2fZlOaRsbhFIS3U7M2q-fZk1pySKQwjp7kuCEk7hOu-WxHb01r4RtHXL2utzfApbBsXB-_l2G33LpdfqkMXK9c662R99uS-F2TTbLdUXo1iPsv6a10b9j7gjdtgpbQretzv8NAAD__zyY9mo">