| Issue |
79087
|
| Summary |
Clang's error for missing `template` in `this->base_func<false>(args...)` is unusually terrible
|
| Labels |
clang
|
| Assignees |
|
| Reporter |
StephanTLavavej
|
# 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.
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs