diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-10-30 21:46:58 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-10-30 21:46:58 +0000 |
commit | 916462b2f7b28d676c42f4f1bb6fae5dd7d5b09a (patch) | |
tree | fdb63a8eb9bfe392492a14ecfc3c51ec10d1bf78 /clang/lib | |
parent | 95e6e933ed99250c346f453a04f0a1df8aedcef6 (diff) | |
download | bcm5719-llvm-916462b2f7b28d676c42f4f1bb6fae5dd7d5b09a.tar.gz bcm5719-llvm-916462b2f7b28d676c42f4f1bb6fae5dd7d5b09a.zip |
Improve diagnostics when parsing something like
template<> struct foo<int> { ... };
where "foo" does not refer to a template. Fixes PR3844.
llvm-svn: 85616
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d381e3e9747..72c9f33cd8d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -589,6 +589,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) Diag(Tok, diag::err_expected_ident); + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + // Parse the (optional) class name or simple-template-id. IdentifierInfo *Name = 0; SourceLocation NameLoc; @@ -596,6 +598,42 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); + + if (Tok.is(tok::less)) { + // The name was supposed to refer to a template, but didn't. + // Eat the template argument list and try to continue parsing this as + // a class (or template thereof). + TemplateArgList TemplateArgs; + TemplateArgIsTypeList TemplateArgIsType; + TemplateArgLocationList TemplateArgLocations; + SourceLocation LAngleLoc, RAngleLoc; + if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, + true, LAngleLoc, + TemplateArgs, TemplateArgIsType, + TemplateArgLocations, RAngleLoc)) { + // We couldn't parse the template argument list at all, so don't + // try to give any location information for the list. + LAngleLoc = RAngleLoc = SourceLocation(); + } + + Diag(NameLoc, diag::err_explicit_spec_non_template) + << (TagType == DeclSpec::TST_class? 0 + : TagType == DeclSpec::TST_struct? 1 + : 2) + << Name + << SourceRange(LAngleLoc, RAngleLoc); + + // If this is an explicit specialization, strip off the last template + // parameter list, since we've removed its template arguments. + if (TemplateParams && TemplateParams->size() > 1) { + TemplateParams->pop_back(); + } else { + TemplateParams = 0; + const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind + = ParsedTemplateInfo::NonTemplate; + } + + } } else if (Tok.is(tok::annot_template_id)) { TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); NameLoc = ConsumeToken(); @@ -660,7 +698,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Create the tag portion of the class or class template. Action::DeclResult TagOrTempResult = true; // invalid Action::TypeResult TypeResult = true; // invalid - TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; // FIXME: When TUK == TUK_Reference and we have a template-id, we need // to turn that template-id into a type. |