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.