зеркало из https://github.com/microsoft/clang-1.git
Improved fix for PR3844, which recovers better for class template
partial specializations and explicit instantiations of non-templates. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85620 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
12e6f03412
Коммит
c78c06d81f
|
@ -283,7 +283,8 @@ def err_typename_refers_to_non_type_template : Error<
|
|||
def err_expected_type_name_after_typename : Error<
|
||||
"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">;
|
||||
"explicit %select{specialization|instantiation}0 of non-template "
|
||||
"%select{class|struct|union}1 %2">;
|
||||
|
||||
def err_variadic_templates : Error<
|
||||
"variadic templates are only allowed in C++0x">;
|
||||
|
|
|
@ -603,14 +603,17 @@ private:
|
|||
: Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
|
||||
|
||||
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
|
||||
bool isSpecialization)
|
||||
bool isSpecialization,
|
||||
bool lastParameterListWasEmpty = false)
|
||||
: Kind(isSpecialization? ExplicitSpecialization : Template),
|
||||
TemplateParams(TemplateParams) { }
|
||||
TemplateParams(TemplateParams),
|
||||
LastParameterListWasEmpty(lastParameterListWasEmpty) { }
|
||||
|
||||
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
|
||||
SourceLocation TemplateLoc)
|
||||
: Kind(ExplicitInstantiation), TemplateParams(0),
|
||||
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
|
||||
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
|
||||
LastParameterListWasEmpty(false){ }
|
||||
|
||||
/// \brief The kind of template we are parsing.
|
||||
enum {
|
||||
|
@ -635,6 +638,9 @@ private:
|
|||
/// \brief The location of the 'template' keyword, for an explicit
|
||||
/// instantiation.
|
||||
SourceLocation TemplateLoc;
|
||||
|
||||
/// \brief Whether the last template parameter list was empty.
|
||||
bool LastParameterListWasEmpty;
|
||||
};
|
||||
|
||||
void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
|
||||
|
|
|
@ -617,22 +617,36 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
}
|
||||
|
||||
Diag(NameLoc, diag::err_explicit_spec_non_template)
|
||||
<< (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
|
||||
<< (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 {
|
||||
// Strip off the last template parameter list if it was empty, since
|
||||
// we've removed its template argument list.
|
||||
if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
|
||||
if (TemplateParams && TemplateParams->size() > 1) {
|
||||
TemplateParams->pop_back();
|
||||
} else {
|
||||
TemplateParams = 0;
|
||||
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
|
||||
= ParsedTemplateInfo::NonTemplate;
|
||||
}
|
||||
} else if (TemplateInfo.Kind
|
||||
== ParsedTemplateInfo::ExplicitInstantiation) {
|
||||
// Pretend this is just a forward declaration.
|
||||
TemplateParams = 0;
|
||||
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
|
||||
= ParsedTemplateInfo::NonTemplate;
|
||||
const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
|
||||
= SourceLocation();
|
||||
const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
|
||||
= SourceLocation();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} else if (Tok.is(tok::annot_template_id)) {
|
||||
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
||||
|
|
|
@ -101,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
|||
// (and retrieves the outer template parameter list from its
|
||||
// context).
|
||||
bool isSpecialization = true;
|
||||
bool LastParamListWasEmpty = false;
|
||||
TemplateParameterLists ParamLists;
|
||||
TemplateParameterDepthCounter Depth(TemplateParameterDepth);
|
||||
do {
|
||||
|
@ -140,13 +141,16 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
|||
if (!TemplateParams.empty()) {
|
||||
isSpecialization = false;
|
||||
++Depth;
|
||||
} else {
|
||||
LastParamListWasEmpty = true;
|
||||
}
|
||||
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
|
||||
|
||||
// Parse the actual template declaration.
|
||||
return ParseSingleDeclarationAfterTemplate(Context,
|
||||
ParsedTemplateInfo(&ParamLists,
|
||||
isSpecialization),
|
||||
isSpecialization,
|
||||
LastParamListWasEmpty),
|
||||
DeclEnd, AS);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace N {
|
|||
};
|
||||
}
|
||||
|
||||
template class Z<int>; // expected-error{{non-template class 'Z'}}
|
||||
template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}
|
||||
|
||||
// FIXME: This example from the standard is wrong; note posted to CWG reflector
|
||||
// on 10/27/2009
|
||||
|
|
Загрузка…
Ссылка в новой задаче