Skip to content

Clang's error for missing template in this->base_func<false>(args...) is unusually terrible #79087

@StephanTLavavej

Description

@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
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
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
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
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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:diagnosticsNew/improved warning or error message in Clang, but not in clang-tidy or static analyzer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions