Refactor all the checking for missing 'template<>'s when a declaration has a
template-id after its scope specifier into a single place. llvm-svn: 206442
This commit is contained in:
parent
0d963d6c49
commit
4b55a9c841
|
@ -5197,7 +5197,8 @@ public:
|
|||
TemplateParamListContext TPC);
|
||||
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
|
||||
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
|
||||
const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists,
|
||||
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
|
||||
ArrayRef<TemplateParameterList *> ParamLists,
|
||||
bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid);
|
||||
|
||||
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
|
@ -5279,12 +5280,7 @@ public:
|
|||
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
SourceLocation KWLoc,
|
||||
SourceLocation ModulePrivateLoc,
|
||||
CXXScopeSpec &SS,
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
TemplateIdAnnotation &TemplateId,
|
||||
AttributeList *Attr,
|
||||
MultiTemplateParamsArg TemplateParameterLists);
|
||||
|
||||
|
|
|
@ -1541,18 +1541,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
}
|
||||
|
||||
// Build the class template specialization.
|
||||
TagOrTempResult
|
||||
= Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
|
||||
StartLoc, DS.getModulePrivateSpecLoc(), SS,
|
||||
TemplateId->Template,
|
||||
TemplateId->TemplateNameLoc,
|
||||
TemplateId->LAngleLoc,
|
||||
TemplateArgsPtr,
|
||||
TemplateId->RAngleLoc,
|
||||
attrs.getList(),
|
||||
MultiTemplateParamsArg(
|
||||
TemplateParams? &(*TemplateParams)[0] : 0,
|
||||
TemplateParams? TemplateParams->size() : 0));
|
||||
TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
|
||||
getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
|
||||
*TemplateId, attrs.getList(),
|
||||
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : 0,
|
||||
TemplateParams ? TemplateParams->size() : 0));
|
||||
}
|
||||
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
|
||||
TUK == Sema::TUK_Declaration) {
|
||||
|
|
|
@ -5228,29 +5228,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// determine whether we have a template or a template specialization.
|
||||
TemplateParams = MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateParamLists,
|
||||
D.getCXXScopeSpec(),
|
||||
D.getName().getKind() == UnqualifiedId::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: 0,
|
||||
TemplateParamLists,
|
||||
/*never a friend*/ false, IsExplicitSpecialization, Invalid);
|
||||
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
|
||||
!TemplateParams) {
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
|
||||
// We have encountered something that the user meant to be a
|
||||
// specialization (because it has explicitly-specified template
|
||||
// arguments) but that was not introduced with a "template<>" (or had
|
||||
// too few of them).
|
||||
// FIXME: Differentiate between attempts for explicit instantiations
|
||||
// (starting with "template") and the rest.
|
||||
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
|
||||
<< FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
|
||||
"template<> ");
|
||||
IsExplicitSpecialization = true;
|
||||
TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),
|
||||
SourceLocation(), 0, 0,
|
||||
SourceLocation());
|
||||
}
|
||||
|
||||
if (TemplateParams) {
|
||||
if (!TemplateParams->size() &&
|
||||
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
|
@ -5283,6 +5267,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
: diag::ext_variable_template);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
|
||||
"should have a 'template<>' for this decl");
|
||||
}
|
||||
|
||||
if (IsVariableTemplateSpecialization) {
|
||||
|
@ -6709,8 +6696,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
if (TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateParamLists, isFriend,
|
||||
isExplicitSpecialization, Invalid)) {
|
||||
D.getCXXScopeSpec(),
|
||||
D.getName().getKind() == UnqualifiedId::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: 0,
|
||||
TemplateParamLists, isFriend, isExplicitSpecialization,
|
||||
Invalid)) {
|
||||
if (TemplateParams->size() > 0) {
|
||||
// This is a function template
|
||||
|
||||
|
@ -6751,9 +6742,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// This is a function template specialization.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
// For source fidelity, store all the template param lists.
|
||||
NewFD->setTemplateParameterListsInfo(Context,
|
||||
TemplateParamLists.size(),
|
||||
TemplateParamLists.data());
|
||||
if (TemplateParamLists.size() > 0)
|
||||
NewFD->setTemplateParameterListsInfo(Context,
|
||||
TemplateParamLists.size(),
|
||||
TemplateParamLists.data());
|
||||
|
||||
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
|
||||
if (isFriend) {
|
||||
|
@ -7152,21 +7144,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
|
||||
|
||||
HasExplicitTemplateArgs = false;
|
||||
} else if (!isFunctionTemplateSpecialization &&
|
||||
!D.getDeclSpec().isFriendSpecified()) {
|
||||
// We have encountered something that the user meant to be a
|
||||
// specialization (because it has explicitly-specified template
|
||||
// arguments) but that was not introduced with a "template<>" (or had
|
||||
// too few of them).
|
||||
// FIXME: Differentiate between attempts for explicit instantiations
|
||||
// (starting with "template") and the rest.
|
||||
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
|
||||
<< FixItHint::CreateInsertion(
|
||||
D.getDeclSpec().getLocStart(),
|
||||
"template<> ");
|
||||
isFunctionTemplateSpecialization = true;
|
||||
} else {
|
||||
assert((isFunctionTemplateSpecialization ||
|
||||
D.getDeclSpec().isFriendSpecified()) &&
|
||||
"should have a 'template<>' for this decl");
|
||||
// "friend void foo<>(int);" is an implicit specialization decl.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
}
|
||||
|
@ -7178,7 +7159,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// friend void foo<>(int);
|
||||
// Go ahead and fake up a template id.
|
||||
HasExplicitTemplateArgs = true;
|
||||
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
|
||||
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
|
||||
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
|
||||
}
|
||||
|
||||
|
@ -10569,8 +10550,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
(SS.isNotEmpty() && TUK != TUK_Reference)) {
|
||||
if (TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
|
||||
isExplicitSpecialization, Invalid)) {
|
||||
KWLoc, NameLoc, SS, 0, TemplateParameterLists,
|
||||
TUK == TUK_Friend, isExplicitSpecialization, Invalid)) {
|
||||
if (Kind == TTK_Enum) {
|
||||
Diag(KWLoc, diag::err_enum_template);
|
||||
return 0;
|
||||
|
|
|
@ -11370,7 +11370,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
|
|||
|
||||
if (TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
|
||||
TagLoc, NameLoc, SS, 0, TempParamLists, /*friend*/ true,
|
||||
isExplicitSpecialization, Invalid)) {
|
||||
if (TemplateParams->size() > 0) {
|
||||
// This is a declaration of a class template.
|
||||
|
|
|
@ -1593,6 +1593,9 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
|
|||
/// parameter lists. This scope specifier precedes a qualified name that is
|
||||
/// being declared.
|
||||
///
|
||||
/// \param TemplateId The template-id following the scope specifier, if there
|
||||
/// is one. Used to check for a missing 'template<>'.
|
||||
///
|
||||
/// \param ParamLists the template parameter lists, from the outermost to the
|
||||
/// innermost template parameter lists.
|
||||
///
|
||||
|
@ -1611,6 +1614,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
|
|||
/// itself a template).
|
||||
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
||||
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation *TemplateId,
|
||||
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
|
||||
bool &IsExplicitSpecialization, bool &Invalid) {
|
||||
IsExplicitSpecialization = false;
|
||||
|
@ -1830,6 +1834,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
|||
else
|
||||
ExpectedTemplateLoc = DeclStartLoc;
|
||||
|
||||
// FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
|
||||
Diag(DeclLoc, diag::err_template_spec_needs_header)
|
||||
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
|
||||
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
|
||||
|
@ -1875,12 +1880,33 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If there were at least as many template-ids as there were template
|
||||
// parameter lists, then there are no template parameter lists remaining for
|
||||
// the declaration itself.
|
||||
if (ParamIdx >= ParamLists.size())
|
||||
if (ParamIdx >= ParamLists.size()) {
|
||||
if (TemplateId && !IsFriend) {
|
||||
// FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
|
||||
// We don't have a template header for the declaration itself, but we
|
||||
// should.
|
||||
SourceLocation ExpectedTemplateLoc;
|
||||
if (!ParamLists.empty())
|
||||
ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
|
||||
else
|
||||
ExpectedTemplateLoc = DeclStartLoc;
|
||||
Diag(DeclLoc, diag::err_template_spec_needs_header)
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
|
||||
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
|
||||
IsExplicitSpecialization = true;
|
||||
|
||||
// Fabricate an empty template parameter list for the invented header.
|
||||
return TemplateParameterList::Create(Context, SourceLocation(),
|
||||
SourceLocation(), 0, 0,
|
||||
SourceLocation());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there were too many template parameter lists, complain about that now.
|
||||
if (ParamIdx < ParamLists.size() - 1) {
|
||||
|
@ -2355,6 +2381,17 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Convert the parser's template argument list representation into our form.
|
||||
static TemplateArgumentListInfo
|
||||
makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
|
||||
TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
|
||||
TemplateId.RAngleLoc);
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
|
||||
TemplateId.NumArgs);
|
||||
S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
|
||||
return TemplateArgs;
|
||||
}
|
||||
|
||||
DeclResult Sema::ActOnVarTemplateSpecialization(
|
||||
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
|
||||
TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
|
||||
|
@ -2364,13 +2401,12 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
|
|||
"Variable template specialization is declared with a template it.");
|
||||
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
TemplateArgumentListInfo TemplateArgs =
|
||||
makeTemplateArgumentListInfo(*this, *TemplateId);
|
||||
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
|
||||
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
|
||||
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
|
||||
TemplateId->NumArgs);
|
||||
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
|
||||
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
|
||||
|
||||
TemplateName Name = TemplateId->Template.get();
|
||||
|
||||
// The template-id must name a variable template.
|
||||
|
@ -5840,23 +5876,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
TagUseKind TUK,
|
||||
SourceLocation KWLoc,
|
||||
SourceLocation ModulePrivateLoc,
|
||||
CXXScopeSpec &SS,
|
||||
TemplateTy TemplateD,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgsIn,
|
||||
SourceLocation RAngleLoc,
|
||||
TemplateIdAnnotation &TemplateId,
|
||||
AttributeList *Attr,
|
||||
MultiTemplateParamsArg TemplateParameterLists) {
|
||||
assert(TUK != TUK_Reference && "References are not specializations");
|
||||
|
||||
CXXScopeSpec &SS = TemplateId.SS;
|
||||
|
||||
// NOTE: KWLoc is the location of the tag keyword. This will instead
|
||||
// store the location of the outermost template keyword in the declaration.
|
||||
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
|
||||
? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();
|
||||
? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
|
||||
SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
|
||||
SourceLocation LAngleLoc = TemplateId.LAngleLoc;
|
||||
SourceLocation RAngleLoc = TemplateId.RAngleLoc;
|
||||
|
||||
// Find the class template we're specializing
|
||||
TemplateName Name = TemplateD.get();
|
||||
TemplateName Name = TemplateId.Template.get();
|
||||
ClassTemplateDecl *ClassTemplate
|
||||
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
|
||||
|
||||
|
@ -5877,8 +5913,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
bool Invalid = false;
|
||||
TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,
|
||||
TUK == TUK_Friend, isExplicitSpecialization, Invalid);
|
||||
KWLoc, TemplateNameLoc, SS, &TemplateId,
|
||||
TemplateParameterLists, TUK == TUK_Friend, isExplicitSpecialization,
|
||||
Invalid);
|
||||
if (Invalid)
|
||||
return true;
|
||||
|
||||
|
@ -5929,11 +5966,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
<< SourceRange(LAngleLoc, RAngleLoc);
|
||||
else
|
||||
isExplicitSpecialization = true;
|
||||
} else if (TUK != TUK_Friend) {
|
||||
Diag(KWLoc, diag::err_template_spec_needs_header)
|
||||
<< FixItHint::CreateInsertion(KWLoc, "template<> ");
|
||||
TemplateKWLoc = KWLoc;
|
||||
isExplicitSpecialization = true;
|
||||
} else {
|
||||
assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");
|
||||
}
|
||||
|
||||
// Check that the specialization uses the same tag kind as the
|
||||
|
@ -5953,10 +5987,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
}
|
||||
|
||||
// Translate the parser's template argument list in our AST format.
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
TemplateArgs.setLAngleLoc(LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(RAngleLoc);
|
||||
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
|
||||
TemplateArgumentListInfo TemplateArgs =
|
||||
makeTemplateArgumentListInfo(*this, TemplateId);
|
||||
|
||||
// Check for unexpanded parameter packs in any of the template arguments.
|
||||
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
|
||||
|
@ -7416,13 +7448,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
}
|
||||
|
||||
// Translate the parser's template argument list into our AST format.
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
|
||||
TemplateId->NumArgs);
|
||||
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
|
||||
TemplateArgumentListInfo TemplateArgs =
|
||||
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
|
||||
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
|
||||
D.getIdentifierLoc(), TemplateArgs);
|
||||
|
@ -7492,12 +7519,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
|
||||
TemplateId->NumArgs);
|
||||
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
|
||||
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
HasExplicitTemplateArgs = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ virtual void C1::f() { } // expected-error{{'virtual' can only be specified insi
|
|||
|
||||
static void C1::g() { } // expected-error{{'static' can only be specified inside the class definition}}
|
||||
|
||||
template<int Value> struct CT { }; // expected-note{{previous use is here}}
|
||||
template<int Value> struct CT { template<typename> struct Inner; }; // expected-note{{previous use is here}}
|
||||
|
||||
CT<10 >> 2> ct; // expected-warning{{require parentheses}}
|
||||
|
||||
|
@ -32,6 +32,8 @@ struct CT<0> { }; // expected-error{{'template<>'}}
|
|||
|
||||
template<> union CT<1> { }; // expected-error{{tag type}}
|
||||
|
||||
struct CT<2>::Inner<int> { }; // expected-error 2{{'template<>'}}
|
||||
|
||||
// Access declarations
|
||||
class A {
|
||||
protected:
|
||||
|
|
Loading…
Reference in New Issue