We track when we see a name-shaped expression followed by a < token that we parse as a comparison. Then:
- if we see a token sequence that cannot possibly be an expression but can be a template argument (in particular, a type-id) that follows either a , or the <, diagnose that the < was supposed to start a template argument list
- if we see <>, diagnose that the <> was supposed to be a template argument list
- if we see >(), diagnose that the <[...]> was supposed to be a template argument list
This only changes the diagnostic for error cases, and in practice appears to catch the most common cases where a missing template keyword leads to parse errors within a template.