Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 8b7a1c5

Browse files
committed
Refactor all the checking for missing 'template<>'s when a declaration has a
template-id after its scope specifier into a single place. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206442 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d997419 commit 8b7a1c5

File tree

6 files changed

+96
-102
lines changed

6 files changed

+96
-102
lines changed

include/clang/Sema/Sema.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -5197,7 +5197,8 @@ class Sema {
51975197
TemplateParamListContext TPC);
51985198
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
51995199
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
5200-
const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists,
5200+
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
5201+
ArrayRef<TemplateParameterList *> ParamLists,
52015202
bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid);
52025203

52035204
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
@@ -5279,12 +5280,7 @@ class Sema {
52795280
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
52805281
SourceLocation KWLoc,
52815282
SourceLocation ModulePrivateLoc,
5282-
CXXScopeSpec &SS,
5283-
TemplateTy Template,
5284-
SourceLocation TemplateNameLoc,
5285-
SourceLocation LAngleLoc,
5286-
ASTTemplateArgsPtr TemplateArgs,
5287-
SourceLocation RAngleLoc,
5283+
TemplateIdAnnotation &TemplateId,
52885284
AttributeList *Attr,
52895285
MultiTemplateParamsArg TemplateParameterLists);
52905286

lib/Parse/ParseDeclCXX.cpp

+5-12
Original file line numberDiff line numberDiff line change
@@ -1541,18 +1541,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
15411541
}
15421542

15431543
// Build the class template specialization.
1544-
TagOrTempResult
1545-
= Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
1546-
StartLoc, DS.getModulePrivateSpecLoc(), SS,
1547-
TemplateId->Template,
1548-
TemplateId->TemplateNameLoc,
1549-
TemplateId->LAngleLoc,
1550-
TemplateArgsPtr,
1551-
TemplateId->RAngleLoc,
1552-
attrs.getList(),
1553-
MultiTemplateParamsArg(
1554-
TemplateParams? &(*TemplateParams)[0] : 0,
1555-
TemplateParams? TemplateParams->size() : 0));
1544+
TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
1545+
getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
1546+
*TemplateId, attrs.getList(),
1547+
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : 0,
1548+
TemplateParams ? TemplateParams->size() : 0));
15561549
}
15571550
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
15581551
TUK == Sema::TUK_Declaration) {

lib/Sema/SemaDecl.cpp

+24-43
Original file line numberDiff line numberDiff line change
@@ -5228,29 +5228,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
52285228
// determine whether we have a template or a template specialization.
52295229
TemplateParams = MatchTemplateParametersToScopeSpecifier(
52305230
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
5231-
D.getCXXScopeSpec(), TemplateParamLists,
5231+
D.getCXXScopeSpec(),
5232+
D.getName().getKind() == UnqualifiedId::IK_TemplateId
5233+
? D.getName().TemplateId
5234+
: 0,
5235+
TemplateParamLists,
52325236
/*never a friend*/ false, IsExplicitSpecialization, Invalid);
52335237

5234-
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
5235-
!TemplateParams) {
5236-
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
5237-
5238-
// We have encountered something that the user meant to be a
5239-
// specialization (because it has explicitly-specified template
5240-
// arguments) but that was not introduced with a "template<>" (or had
5241-
// too few of them).
5242-
// FIXME: Differentiate between attempts for explicit instantiations
5243-
// (starting with "template") and the rest.
5244-
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
5245-
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
5246-
<< FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
5247-
"template<> ");
5248-
IsExplicitSpecialization = true;
5249-
TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),
5250-
SourceLocation(), 0, 0,
5251-
SourceLocation());
5252-
}
5253-
52545238
if (TemplateParams) {
52555239
if (!TemplateParams->size() &&
52565240
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
@@ -5283,6 +5267,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
52835267
: diag::ext_variable_template);
52845268
}
52855269
}
5270+
} else {
5271+
assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
5272+
"should have a 'template<>' for this decl");
52865273
}
52875274

52885275
if (IsVariableTemplateSpecialization) {
@@ -6709,8 +6696,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
67096696
if (TemplateParameterList *TemplateParams =
67106697
MatchTemplateParametersToScopeSpecifier(
67116698
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
6712-
D.getCXXScopeSpec(), TemplateParamLists, isFriend,
6713-
isExplicitSpecialization, Invalid)) {
6699+
D.getCXXScopeSpec(),
6700+
D.getName().getKind() == UnqualifiedId::IK_TemplateId
6701+
? D.getName().TemplateId
6702+
: 0,
6703+
TemplateParamLists, isFriend, isExplicitSpecialization,
6704+
Invalid)) {
67146705
if (TemplateParams->size() > 0) {
67156706
// This is a function template
67166707

@@ -6751,9 +6742,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
67516742
// This is a function template specialization.
67526743
isFunctionTemplateSpecialization = true;
67536744
// For source fidelity, store all the template param lists.
6754-
NewFD->setTemplateParameterListsInfo(Context,
6755-
TemplateParamLists.size(),
6756-
TemplateParamLists.data());
6745+
if (TemplateParamLists.size() > 0)
6746+
NewFD->setTemplateParameterListsInfo(Context,
6747+
TemplateParamLists.size(),
6748+
TemplateParamLists.data());
67576749

67586750
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
67596751
if (isFriend) {
@@ -7152,21 +7144,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
71527144
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
71537145

71547146
HasExplicitTemplateArgs = false;
7155-
} else if (!isFunctionTemplateSpecialization &&
7156-
!D.getDeclSpec().isFriendSpecified()) {
7157-
// We have encountered something that the user meant to be a
7158-
// specialization (because it has explicitly-specified template
7159-
// arguments) but that was not introduced with a "template<>" (or had
7160-
// too few of them).
7161-
// FIXME: Differentiate between attempts for explicit instantiations
7162-
// (starting with "template") and the rest.
7163-
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
7164-
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
7165-
<< FixItHint::CreateInsertion(
7166-
D.getDeclSpec().getLocStart(),
7167-
"template<> ");
7168-
isFunctionTemplateSpecialization = true;
71697147
} else {
7148+
assert((isFunctionTemplateSpecialization ||
7149+
D.getDeclSpec().isFriendSpecified()) &&
7150+
"should have a 'template<>' for this decl");
71707151
// "friend void foo<>(int);" is an implicit specialization decl.
71717152
isFunctionTemplateSpecialization = true;
71727153
}
@@ -7178,7 +7159,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
71787159
// friend void foo<>(int);
71797160
// Go ahead and fake up a template id.
71807161
HasExplicitTemplateArgs = true;
7181-
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
7162+
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
71827163
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
71837164
}
71847165

@@ -10569,8 +10550,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
1056910550
(SS.isNotEmpty() && TUK != TUK_Reference)) {
1057010551
if (TemplateParameterList *TemplateParams =
1057110552
MatchTemplateParametersToScopeSpecifier(
10572-
KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
10573-
isExplicitSpecialization, Invalid)) {
10553+
KWLoc, NameLoc, SS, 0, TemplateParameterLists,
10554+
TUK == TUK_Friend, isExplicitSpecialization, Invalid)) {
1057410555
if (Kind == TTK_Enum) {
1057510556
Diag(KWLoc, diag::err_enum_template);
1057610557
return 0;

lib/Sema/SemaDeclCXX.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -11370,7 +11370,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
1137011370

1137111371
if (TemplateParameterList *TemplateParams =
1137211372
MatchTemplateParametersToScopeSpecifier(
11373-
TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
11373+
TagLoc, NameLoc, SS, 0, TempParamLists, /*friend*/ true,
1137411374
isExplicitSpecialization, Invalid)) {
1137511375
if (TemplateParams->size() > 0) {
1137611376
// This is a declaration of a class template.

lib/Sema/SemaTemplate.cpp

+60-38
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,9 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
15931593
/// parameter lists. This scope specifier precedes a qualified name that is
15941594
/// being declared.
15951595
///
1596+
/// \param TemplateId The template-id following the scope specifier, if there
1597+
/// is one. Used to check for a missing 'template<>'.
1598+
///
15961599
/// \param ParamLists the template parameter lists, from the outermost to the
15971600
/// innermost template parameter lists.
15981601
///
@@ -1611,6 +1614,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
16111614
/// itself a template).
16121615
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
16131616
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
1617+
TemplateIdAnnotation *TemplateId,
16141618
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
16151619
bool &IsExplicitSpecialization, bool &Invalid) {
16161620
IsExplicitSpecialization = false;
@@ -1830,6 +1834,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
18301834
else
18311835
ExpectedTemplateLoc = DeclStartLoc;
18321836

1837+
// FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
18331838
Diag(DeclLoc, diag::err_template_spec_needs_header)
18341839
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
18351840
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
@@ -1875,12 +1880,33 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
18751880
continue;
18761881
}
18771882
}
1878-
1883+
18791884
// If there were at least as many template-ids as there were template
18801885
// parameter lists, then there are no template parameter lists remaining for
18811886
// the declaration itself.
1882-
if (ParamIdx >= ParamLists.size())
1887+
if (ParamIdx >= ParamLists.size()) {
1888+
if (TemplateId && !IsFriend) {
1889+
// FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
1890+
// We don't have a template header for the declaration itself, but we
1891+
// should.
1892+
SourceLocation ExpectedTemplateLoc;
1893+
if (!ParamLists.empty())
1894+
ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
1895+
else
1896+
ExpectedTemplateLoc = DeclStartLoc;
1897+
Diag(DeclLoc, diag::err_template_spec_needs_header)
1898+
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
1899+
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
1900+
IsExplicitSpecialization = true;
1901+
1902+
// Fabricate an empty template parameter list for the invented header.
1903+
return TemplateParameterList::Create(Context, SourceLocation(),
1904+
SourceLocation(), 0, 0,
1905+
SourceLocation());
1906+
}
1907+
18831908
return 0;
1909+
}
18841910

18851911
// If there were too many template parameter lists, complain about that now.
18861912
if (ParamIdx < ParamLists.size() - 1) {
@@ -2355,6 +2381,17 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
23552381
return true;
23562382
}
23572383

2384+
/// Convert the parser's template argument list representation into our form.
2385+
static TemplateArgumentListInfo
2386+
makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
2387+
TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
2388+
TemplateId.RAngleLoc);
2389+
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
2390+
TemplateId.NumArgs);
2391+
S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
2392+
return TemplateArgs;
2393+
}
2394+
23582395
DeclResult Sema::ActOnVarTemplateSpecialization(
23592396
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
23602397
TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
@@ -2364,13 +2401,12 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
23642401
"Variable template specialization is declared with a template it.");
23652402

23662403
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
2404+
TemplateArgumentListInfo TemplateArgs =
2405+
makeTemplateArgumentListInfo(*this, *TemplateId);
23672406
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
23682407
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
23692408
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
2370-
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
2371-
TemplateId->NumArgs);
2372-
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
2373-
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
2409+
23742410
TemplateName Name = TemplateId->Template.get();
23752411

23762412
// The template-id must name a variable template.
@@ -5840,23 +5876,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
58405876
TagUseKind TUK,
58415877
SourceLocation KWLoc,
58425878
SourceLocation ModulePrivateLoc,
5843-
CXXScopeSpec &SS,
5844-
TemplateTy TemplateD,
5845-
SourceLocation TemplateNameLoc,
5846-
SourceLocation LAngleLoc,
5847-
ASTTemplateArgsPtr TemplateArgsIn,
5848-
SourceLocation RAngleLoc,
5879+
TemplateIdAnnotation &TemplateId,
58495880
AttributeList *Attr,
58505881
MultiTemplateParamsArg TemplateParameterLists) {
58515882
assert(TUK != TUK_Reference && "References are not specializations");
58525883

5884+
CXXScopeSpec &SS = TemplateId.SS;
5885+
58535886
// NOTE: KWLoc is the location of the tag keyword. This will instead
58545887
// store the location of the outermost template keyword in the declaration.
58555888
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
5856-
? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();
5889+
? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
5890+
SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
5891+
SourceLocation LAngleLoc = TemplateId.LAngleLoc;
5892+
SourceLocation RAngleLoc = TemplateId.RAngleLoc;
58575893

58585894
// Find the class template we're specializing
5859-
TemplateName Name = TemplateD.get();
5895+
TemplateName Name = TemplateId.Template.get();
58605896
ClassTemplateDecl *ClassTemplate
58615897
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
58625898

@@ -5877,8 +5913,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
58775913
bool Invalid = false;
58785914
TemplateParameterList *TemplateParams =
58795915
MatchTemplateParametersToScopeSpecifier(
5880-
TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,
5881-
TUK == TUK_Friend, isExplicitSpecialization, Invalid);
5916+
KWLoc, TemplateNameLoc, SS, &TemplateId,
5917+
TemplateParameterLists, TUK == TUK_Friend, isExplicitSpecialization,
5918+
Invalid);
58825919
if (Invalid)
58835920
return true;
58845921

@@ -5929,11 +5966,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
59295966
<< SourceRange(LAngleLoc, RAngleLoc);
59305967
else
59315968
isExplicitSpecialization = true;
5932-
} else if (TUK != TUK_Friend) {
5933-
Diag(KWLoc, diag::err_template_spec_needs_header)
5934-
<< FixItHint::CreateInsertion(KWLoc, "template<> ");
5935-
TemplateKWLoc = KWLoc;
5936-
isExplicitSpecialization = true;
5969+
} else {
5970+
assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");
59375971
}
59385972

59395973
// Check that the specialization uses the same tag kind as the
@@ -5953,10 +5987,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
59535987
}
59545988

59555989
// Translate the parser's template argument list in our AST format.
5956-
TemplateArgumentListInfo TemplateArgs;
5957-
TemplateArgs.setLAngleLoc(LAngleLoc);
5958-
TemplateArgs.setRAngleLoc(RAngleLoc);
5959-
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
5990+
TemplateArgumentListInfo TemplateArgs =
5991+
makeTemplateArgumentListInfo(*this, TemplateId);
59605992

59615993
// Check for unexpanded parameter packs in any of the template arguments.
59625994
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -7416,13 +7448,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
74167448
}
74177449

74187450
// Translate the parser's template argument list into our AST format.
7419-
TemplateArgumentListInfo TemplateArgs;
7420-
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
7421-
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
7422-
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
7423-
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
7424-
TemplateId->NumArgs);
7425-
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
7451+
TemplateArgumentListInfo TemplateArgs =
7452+
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
74267453

74277454
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
74287455
D.getIdentifierLoc(), TemplateArgs);
@@ -7492,12 +7519,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
74927519
bool HasExplicitTemplateArgs = false;
74937520
TemplateArgumentListInfo TemplateArgs;
74947521
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
7495-
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
7496-
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
7497-
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
7498-
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
7499-
TemplateId->NumArgs);
7500-
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
7522+
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
75017523
HasExplicitTemplateArgs = true;
75027524
}
75037525

test/FixIt/fixit.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ virtual void C1::f() { } // expected-error{{'virtual' can only be specified insi
1919

2020
static void C1::g() { } // expected-error{{'static' can only be specified inside the class definition}}
2121

22-
template<int Value> struct CT { }; // expected-note{{previous use is here}}
22+
template<int Value> struct CT { template<typename> struct Inner; }; // expected-note{{previous use is here}}
2323

2424
CT<10 >> 2> ct; // expected-warning{{require parentheses}}
2525

@@ -32,6 +32,8 @@ struct CT<0> { }; // expected-error{{'template<>'}}
3232

3333
template<> union CT<1> { }; // expected-error{{tag type}}
3434

35+
struct CT<2>::Inner<int> { }; // expected-error 2{{'template<>'}}
36+
3537
// Access declarations
3638
class A {
3739
protected:

0 commit comments

Comments
 (0)