forked from OSchip/llvm-project
Improve diagnostics when parsing something like
template<> struct foo<int> { ... }; where "foo" does not refer to a template. Fixes PR3844. llvm-svn: 85616
This commit is contained in:
parent
95e6e933ed
commit
916462b2f7
|
@ -282,6 +282,8 @@ def err_typename_refers_to_non_type_template : Error<
|
||||||
"typename specifier refers to a non-template">;
|
"typename specifier refers to a non-template">;
|
||||||
def err_expected_type_name_after_typename : Error<
|
def err_expected_type_name_after_typename : Error<
|
||||||
"expected an identifier or template-id after '::'">;
|
"expected an identifier or template-id after '::'">;
|
||||||
|
def err_explicit_spec_non_template : Error<
|
||||||
|
"explicit specialization of non-template %select{class|struct|union}0 %1">;
|
||||||
|
|
||||||
def err_variadic_templates : Error<
|
def err_variadic_templates : Error<
|
||||||
"variadic templates are only allowed in C++0x">;
|
"variadic templates are only allowed in C++0x">;
|
||||||
|
|
|
@ -589,6 +589,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||||
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
|
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
|
||||||
Diag(Tok, diag::err_expected_ident);
|
Diag(Tok, diag::err_expected_ident);
|
||||||
|
|
||||||
|
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
|
||||||
|
|
||||||
// Parse the (optional) class name or simple-template-id.
|
// Parse the (optional) class name or simple-template-id.
|
||||||
IdentifierInfo *Name = 0;
|
IdentifierInfo *Name = 0;
|
||||||
SourceLocation NameLoc;
|
SourceLocation NameLoc;
|
||||||
|
@ -596,6 +598,42 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||||
if (Tok.is(tok::identifier)) {
|
if (Tok.is(tok::identifier)) {
|
||||||
Name = Tok.getIdentifierInfo();
|
Name = Tok.getIdentifierInfo();
|
||||||
NameLoc = ConsumeToken();
|
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)) {
|
} else if (Tok.is(tok::annot_template_id)) {
|
||||||
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
||||||
NameLoc = ConsumeToken();
|
NameLoc = ConsumeToken();
|
||||||
|
@ -660,7 +698,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||||
// Create the tag portion of the class or class template.
|
// Create the tag portion of the class or class template.
|
||||||
Action::DeclResult TagOrTempResult = true; // invalid
|
Action::DeclResult TagOrTempResult = true; // invalid
|
||||||
Action::TypeResult TypeResult = true; // invalid
|
Action::TypeResult TypeResult = true; // invalid
|
||||||
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
|
|
||||||
|
|
||||||
// FIXME: When TUK == TUK_Reference and we have a template-id, we need
|
// FIXME: When TUK == TUK_Reference and we have a template-id, we need
|
||||||
// to turn that template-id into a type.
|
// to turn that template-id into a type.
|
||||||
|
|
|
@ -4,8 +4,7 @@ namespace N {
|
||||||
template<class T> class X;
|
template<class T> class X;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this diagnostic is terrible (PR3844).
|
template<> class X<int> { /* ... */ }; // expected-error {{non-template class 'X'}}
|
||||||
template<> class X<int> { /* ... */ }; // expected-error {{unqualified-id}}
|
|
||||||
|
|
||||||
namespace N {
|
namespace N {
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ namespace N {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: poor diagnostic
|
template class Z<int>; // expected-error{{non-template class 'Z'}}
|
||||||
template class Z<int>; // expected-error{{unqualified-id}}
|
|
||||||
|
|
||||||
// FIXME: This example from the standard is wrong; note posted to CWG reflector
|
// FIXME: This example from the standard is wrong; note posted to CWG reflector
|
||||||
// on 10/27/2009
|
// on 10/27/2009
|
||||||
|
|
|
@ -92,3 +92,7 @@ void f2() {
|
||||||
int x;
|
int x;
|
||||||
A< typeof(x>1) > a;
|
A< typeof(x>1) > a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PR3844
|
||||||
|
template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}}
|
||||||
|
|
Loading…
Reference in New Issue