[cfe-commits] [PATCH][MS][Review request] - Optional template keyword in Microsoft mode.
Douglas Gregor
dgregor at apple.com
Sun Mar 27 03:09:31 PDT 2011
On Mar 24, 2011, at 5:47 AM, Francois Pichet wrote:
> Hi,
>
> Small parser hack to be able to parse type dependent template name
> without the "template" keyword in Microsoft mode.
> This patch fixes about a dozen compile errors when parsing MSVC STL
> headers with clang.
>
> For example:
> =========
> template <class A>
> class C1 {
> public:
> template <int B>
> class Iterator {
> };
> };
>
> template<class T>
> class C2 {
> // template is optional in microsoft mode.
> typename C1<T>:: /*template*/ Iterator<0> Mypos;
> };
>
> ok to commit?
This particular parser recovery would be great, not just for Microsoft mode but in general. So, I'd like to see this handled by making the parser recover well from a missing 'template' keyword (diagnostic + Fix-It) and then either downgrading the diagnostic (to a warning) or omitting it entirely for Microsoft mode.
+ // Microsoft mode parser hack to be able to parse type dependent
+ // template name without the "template" keyword.
+ bool IsImplicitTemplate = getLang().Microsoft && IsTypename &&
+ Tok.is(tok::identifier) &&
+ NextToken().is(tok::less) &&
+ (getCurScope()->getFlags() & Scope::DeclScope) &&
+ (HasScopeSpecifier || ObjectType);
+
// nested-name-specifier:
// nested-name-specifier 'template'[opt] simple-template-id '::'
// Parse the optional 'template' keyword, then make sure we have
// 'identifier <' after it.
- if (Tok.is(tok::kw_template)) {
+ if (Tok.is(tok::kw_template) || IsImplicitTemplate) {
// If we don't have a scope specifier or an object type, this isn't a
// nested-name-specifier, since they aren't allowed to start with
// 'template'.
I think this is the wrong place to perform the recovery, because we're forcing Clang to go down the dependent template-name path even in cases where we might be looking at a non-dependent template name.
Instead, I suggest improving recovery down in the identifier case, by improving the heuristics for the current diagnostic that inserts a dependent 'template' keyword:
if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
IsTemplateArgumentList(1)) {
// We have something like t::getAs<T>, where getAs is a
// member of an unknown specialization. However, this will only
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword)
<< II.getName()
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
It might be as easy as turning that last condition into "(IsTypename || IsTemplateArgumentList(1))".
- Doug
More information about the cfe-commits
mailing list