What I would love to have is FixIt for this kind of situation:
template <class T> void foo() {
T::bar<int*>(); /* missing template keyword */
}which currently gets not that helpful diagnostics:
> clang misleading.cpp
misleading.cpp:2:15: error: expected '(' for function-style cast or type construction
T::bar<int*>();
~~~^
misleading.cpp:2:16: error: expected expression
T::bar<int*>();
^
misleading.cpp:2:18: error: expected expression
T::bar<int*>();
^
3 errors generated.while
template <class T> void foo() {
T::bar<int>();
}gets a good one:
good.cpp:2:8: error: use 'template' keyword to treat 'bar' as a dependent template name
T::bar<int>();
^
template
1 error generated.If I understand it correctly than current implementation of
bool Parser::IsTemplateArgumentList(unsigned Skip)
relies on the fact that if there's a '<' token followed by declaration specifier it has to be a template. Which is true but produces false negatives for non-type parameters (array<1>) or pointer type parameters (vector<int*>) (among others).
One particular thing to keep on mind is that there's the [over.over] rule about resolving names to function pointers - best explained by test test/SemaTemplate/dependent-template-recover.cpp (look for snippet below):
// Note: no diagnostic here, this is actually valid as a comparison between // the decayed pointer to Y::g<> and mb! T::g<mb>(0);
What I did so far is that in case the simple approach doesn't validate there's a template I try to use speculative parsing. The only problem remaining is diagnostics - I am able to use TentativeParsingAction which is later reverted but I still get all the diagnostics which is incorrect in case my speculation about how to parse the code was wrong.