<div dir="ltr">r227540, thanks. I'll look through MatchTemplateParametersToScopeSpecifier() for places that need to set Invalid.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 29, 2015 at 4:24 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">It looks like there are paths through MatchTemplateParametersToScopeSpecifier that return nullptr on invalid inputs but don't set Invalid to true; I don't think this patch is sufficient, though it does seem correct as far as it goes.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 28, 2015 at 8:14 PM, Nico Weber <span dir="ltr"><<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div>On Wed, Apr 16, 2014 at 8:29 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: rsmith<br>
Date: Wed Apr 16 22:29:33 2014<br>
New Revision: 206442<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=206442&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=206442&view=rev</a><br>
Log:<br>
Refactor all the checking for missing 'template<>'s when a declaration has a<br>
template-id after its scope specifier into a single place.<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Sema/Sema.h<br>
cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaDecl.cpp<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
cfe/trunk/test/FixIt/fixit.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 16 22:29:33 2014<br>
@@ -5197,7 +5197,8 @@ public:<br>
TemplateParamListContext TPC);<br>
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(<br>
SourceLocation DeclStartLoc, SourceLocation DeclLoc,<br>
- const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists,<br>
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,<br>
+ ArrayRef<TemplateParameterList *> ParamLists,<br>
bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid);<br>
<br>
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,<br>
@@ -5279,12 +5280,7 @@ public:<br>
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,<br>
SourceLocation KWLoc,<br>
SourceLocation ModulePrivateLoc,<br>
- CXXScopeSpec &SS,<br>
- TemplateTy Template,<br>
- SourceLocation TemplateNameLoc,<br>
- SourceLocation LAngleLoc,<br>
- ASTTemplateArgsPtr TemplateArgs,<br>
- SourceLocation RAngleLoc,<br>
+ TemplateIdAnnotation &TemplateId,<br>
AttributeList *Attr,<br>
MultiTemplateParamsArg TemplateParameterLists);<br>
<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Apr 16 22:29:33 2014<br>
@@ -1541,18 +1541,11 @@ void Parser::ParseClassSpecifier(tok::To<br>
}<br>
<br>
// Build the class template specialization.<br>
- TagOrTempResult<br>
- = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,<br>
- StartLoc, DS.getModulePrivateSpecLoc(), SS,<br>
- TemplateId->Template,<br>
- TemplateId->TemplateNameLoc,<br>
- TemplateId->LAngleLoc,<br>
- TemplateArgsPtr,<br>
- TemplateId->RAngleLoc,<br>
- attrs.getList(),<br>
- MultiTemplateParamsArg(<br>
- TemplateParams? &(*TemplateParams)[0] : 0,<br>
- TemplateParams? TemplateParams->size() : 0));<br>
+ TagOrTempResult = Actions.ActOnClassTemplateSpecialization(<br>
+ getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),<br>
+ *TemplateId, attrs.getList(),<br>
+ MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : 0,<br>
+ TemplateParams ? TemplateParams->size() : 0));<br>
}<br>
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&<br>
TUK == Sema::TUK_Declaration) {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr 16 22:29:33 2014<br>
@@ -5228,29 +5228,13 @@ Sema::ActOnVariableDeclarator(Scope *S,<br>
// determine whether we have a template or a template specialization.<br>
TemplateParams = MatchTemplateParametersToScopeSpecifier(<br>
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),<br>
- D.getCXXScopeSpec(), TemplateParamLists,<br>
+ D.getCXXScopeSpec(),<br>
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId<br>
+ ? D.getName().TemplateId<br>
+ : 0,<br>
+ TemplateParamLists,<br>
/*never a friend*/ false, IsExplicitSpecialization, Invalid);<br>
<br>
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&<br>
- !TemplateParams) {<br>
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;<br>
-<br>
- // We have encountered something that the user meant to be a<br>
- // specialization (because it has explicitly-specified template<br>
- // arguments) but that was not introduced with a "template<>" (or had<br>
- // too few of them).<br>
- // FIXME: Differentiate between attempts for explicit instantiations<br>
- // (starting with "template") and the rest.<br>
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)<br>
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)<br>
- << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),<br>
- "template<> ");<br>
- IsExplicitSpecialization = true;<br>
- TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),<br>
- SourceLocation(), 0, 0,<br>
- SourceLocation());<br>
- }<br>
-<br>
if (TemplateParams) {<br>
if (!TemplateParams->size() &&<br>
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {<br>
@@ -5283,6 +5267,9 @@ Sema::ActOnVariableDeclarator(Scope *S,<br>
: diag::ext_variable_template);<br>
}<br>
}<br>
+ } else {<br>
+ assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&<br>
+ "should have a 'template<>' for this decl");<br></blockquote><div><br></div></div></div><div>This assert fires on some invalid inputs, for example</div><div><br></div><div><div> template <typename> struct CT2 {</div><div> template <class U> struct X;</div><div> };</div><div> template <typename T> int CT2<int>::X<>;</div></div><div><br></div><div>Is the right fix just to change this to assert(Invalid || D.getName…)? (Also attached in patch form.)</div><div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
}<br>
<br>
if (IsVariableTemplateSpecialization) {<br>
@@ -6709,8 +6696,12 @@ Sema::ActOnFunctionDeclarator(Scope *S,<br>
if (TemplateParameterList *TemplateParams =<br>
MatchTemplateParametersToScopeSpecifier(<br>
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),<br>
- D.getCXXScopeSpec(), TemplateParamLists, isFriend,<br>
- isExplicitSpecialization, Invalid)) {<br>
+ D.getCXXScopeSpec(),<br>
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId<br>
+ ? D.getName().TemplateId<br>
+ : 0,<br>
+ TemplateParamLists, isFriend, isExplicitSpecialization,<br>
+ Invalid)) {<br>
if (TemplateParams->size() > 0) {<br>
// This is a function template<br>
<br>
@@ -6751,9 +6742,10 @@ Sema::ActOnFunctionDeclarator(Scope *S,<br>
// This is a function template specialization.<br>
isFunctionTemplateSpecialization = true;<br>
// For source fidelity, store all the template param lists.<br>
- NewFD->setTemplateParameterListsInfo(Context,<br>
- TemplateParamLists.size(),<br>
- TemplateParamLists.data());<br>
+ if (TemplateParamLists.size() > 0)<br>
+ NewFD->setTemplateParameterListsInfo(Context,<br>
+ TemplateParamLists.size(),<br>
+ TemplateParamLists.data());<br>
<br>
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".<br>
if (isFriend) {<br>
@@ -7152,21 +7144,10 @@ Sema::ActOnFunctionDeclarator(Scope *S,<br>
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);<br>
<br>
HasExplicitTemplateArgs = false;<br>
- } else if (!isFunctionTemplateSpecialization &&<br>
- !D.getDeclSpec().isFriendSpecified()) {<br>
- // We have encountered something that the user meant to be a<br>
- // specialization (because it has explicitly-specified template<br>
- // arguments) but that was not introduced with a "template<>" (or had<br>
- // too few of them).<br>
- // FIXME: Differentiate between attempts for explicit instantiations<br>
- // (starting with "template") and the rest.<br>
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)<br>
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)<br>
- << FixItHint::CreateInsertion(<br>
- D.getDeclSpec().getLocStart(),<br>
- "template<> ");<br>
- isFunctionTemplateSpecialization = true;<br>
} else {<br>
+ assert((isFunctionTemplateSpecialization ||<br>
+ D.getDeclSpec().isFriendSpecified()) &&<br>
+ "should have a 'template<>' for this decl");<br>
// "friend void foo<>(int);" is an implicit specialization decl.<br>
isFunctionTemplateSpecialization = true;<br>
}<br>
@@ -7178,7 +7159,7 @@ Sema::ActOnFunctionDeclarator(Scope *S,<br>
// friend void foo<>(int);<br>
// Go ahead and fake up a template id.<br>
HasExplicitTemplateArgs = true;<br>
- TemplateArgs.setLAngleLoc(D.getIdentifierLoc());<br>
+ TemplateArgs.setLAngleLoc(D.getIdentifierLoc());<br>
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());<br>
}<br>
<br>
@@ -10569,8 +10550,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned<br>
(SS.isNotEmpty() && TUK != TUK_Reference)) {<br>
if (TemplateParameterList *TemplateParams =<br>
MatchTemplateParametersToScopeSpecifier(<br>
- KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,<br>
- isExplicitSpecialization, Invalid)) {<br>
+ KWLoc, NameLoc, SS, 0, TemplateParameterLists,<br>
+ TUK == TUK_Friend, isExplicitSpecialization, Invalid)) {<br>
if (Kind == TTK_Enum) {<br>
Diag(KWLoc, diag::err_enum_template);<br>
return 0;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr 16 22:29:33 2014<br>
@@ -11370,7 +11370,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scop<br>
<br>
if (TemplateParameterList *TemplateParams =<br>
MatchTemplateParametersToScopeSpecifier(<br>
- TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,<br>
+ TagLoc, NameLoc, SS, 0, TempParamLists, /*friend*/ true,<br>
isExplicitSpecialization, Invalid)) {<br>
if (TemplateParams->size() > 0) {<br>
// This is a declaration of a class template.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr 16 22:29:33 2014<br>
@@ -1593,6 +1593,9 @@ static SourceRange getRangeOfTypeInNeste<br>
/// parameter lists. This scope specifier precedes a qualified name that is<br>
/// being declared.<br>
///<br>
+/// \param TemplateId The template-id following the scope specifier, if there<br>
+/// is one. Used to check for a missing 'template<>'.<br>
+///<br>
/// \param ParamLists the template parameter lists, from the outermost to the<br>
/// innermost template parameter lists.<br>
///<br>
@@ -1611,6 +1614,7 @@ static SourceRange getRangeOfTypeInNeste<br>
/// itself a template).<br>
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(<br>
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,<br>
+ TemplateIdAnnotation *TemplateId,<br>
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,<br>
bool &IsExplicitSpecialization, bool &Invalid) {<br>
IsExplicitSpecialization = false;<br>
@@ -1830,6 +1834,7 @@ TemplateParameterList *Sema::MatchTempla<br>
else<br>
ExpectedTemplateLoc = DeclStartLoc;<br>
<br>
+ // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.<br>
Diag(DeclLoc, diag::err_template_spec_needs_header)<br>
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS)<br>
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");<br>
@@ -1875,12 +1880,33 @@ TemplateParameterList *Sema::MatchTempla<br>
continue;<br>
}<br>
}<br>
-<br>
+<br>
// If there were at least as many template-ids as there were template<br>
// parameter lists, then there are no template parameter lists remaining for<br>
// the declaration itself.<br>
- if (ParamIdx >= ParamLists.size())<br>
+ if (ParamIdx >= ParamLists.size()) {<br>
+ if (TemplateId && !IsFriend) {<br>
+ // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.<br>
+ // We don't have a template header for the declaration itself, but we<br>
+ // should.<br>
+ SourceLocation ExpectedTemplateLoc;<br>
+ if (!ParamLists.empty())<br>
+ ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();<br>
+ else<br>
+ ExpectedTemplateLoc = DeclStartLoc;<br>
+ Diag(DeclLoc, diag::err_template_spec_needs_header)<br>
+ << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)<br>
+ << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");<br>
+ IsExplicitSpecialization = true;<br>
+<br>
+ // Fabricate an empty template parameter list for the invented header.<br>
+ return TemplateParameterList::Create(Context, SourceLocation(),<br>
+ SourceLocation(), 0, 0,<br>
+ SourceLocation());<br>
+ }<br>
+<br>
return 0;<br>
+ }<br>
<br>
// If there were too many template parameter lists, complain about that now.<br>
if (ParamIdx < ParamLists.size() - 1) {<br>
@@ -2355,6 +2381,17 @@ static bool isSameAsPrimaryTemplate(Temp<br>
return true;<br>
}<br>
<br>
+/// Convert the parser's template argument list representation into our form.<br>
+static TemplateArgumentListInfo<br>
+makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {<br>
+ TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,<br>
+ TemplateId.RAngleLoc);<br>
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),<br>
+ TemplateId.NumArgs);<br>
+ S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);<br>
+ return TemplateArgs;<br>
+}<br>
+<br>
DeclResult Sema::ActOnVarTemplateSpecialization(<br>
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,<br>
TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,<br>
@@ -2364,13 +2401,12 @@ DeclResult Sema::ActOnVarTemplateSpecial<br>
"Variable template specialization is declared with a template it.");<br>
<br>
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;<br>
+ TemplateArgumentListInfo TemplateArgs =<br>
+ makeTemplateArgumentListInfo(*this, *TemplateId);<br>
SourceLocation TemplateNameLoc = D.getIdentifierLoc();<br>
SourceLocation LAngleLoc = TemplateId->LAngleLoc;<br>
SourceLocation RAngleLoc = TemplateId->RAngleLoc;<br>
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br>
- TemplateId->NumArgs);<br>
- TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);<br>
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);<br>
+<br>
TemplateName Name = TemplateId->Template.get();<br>
<br>
// The template-id must name a variable template.<br>
@@ -5840,23 +5876,23 @@ Sema::ActOnClassTemplateSpecialization(S<br>
TagUseKind TUK,<br>
SourceLocation KWLoc,<br>
SourceLocation ModulePrivateLoc,<br>
- CXXScopeSpec &SS,<br>
- TemplateTy TemplateD,<br>
- SourceLocation TemplateNameLoc,<br>
- SourceLocation LAngleLoc,<br>
- ASTTemplateArgsPtr TemplateArgsIn,<br>
- SourceLocation RAngleLoc,<br>
+ TemplateIdAnnotation &TemplateId,<br>
AttributeList *Attr,<br>
MultiTemplateParamsArg TemplateParameterLists) {<br>
assert(TUK != TUK_Reference && "References are not specializations");<br>
<br>
+ CXXScopeSpec &SS = TemplateId.SS;<br>
+<br>
// NOTE: KWLoc is the location of the tag keyword. This will instead<br>
// store the location of the outermost template keyword in the declaration.<br>
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0<br>
- ? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();<br>
+ ? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;<br>
+ SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;<br>
+ SourceLocation LAngleLoc = TemplateId.LAngleLoc;<br>
+ SourceLocation RAngleLoc = TemplateId.RAngleLoc;<br>
<br>
// Find the class template we're specializing<br>
- TemplateName Name = TemplateD.get();<br>
+ TemplateName Name = TemplateId.Template.get();<br>
ClassTemplateDecl *ClassTemplate<br>
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());<br>
<br>
@@ -5877,8 +5913,9 @@ Sema::ActOnClassTemplateSpecialization(S<br>
bool Invalid = false;<br>
TemplateParameterList *TemplateParams =<br>
MatchTemplateParametersToScopeSpecifier(<br>
- TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,<br>
- TUK == TUK_Friend, isExplicitSpecialization, Invalid);<br>
+ KWLoc, TemplateNameLoc, SS, &TemplateId,<br>
+ TemplateParameterLists, TUK == TUK_Friend, isExplicitSpecialization,<br>
+ Invalid);<br>
if (Invalid)<br>
return true;<br>
<br>
@@ -5929,11 +5966,8 @@ Sema::ActOnClassTemplateSpecialization(S<br>
<< SourceRange(LAngleLoc, RAngleLoc);<br>
else<br>
isExplicitSpecialization = true;<br>
- } else if (TUK != TUK_Friend) {<br>
- Diag(KWLoc, diag::err_template_spec_needs_header)<br>
- << FixItHint::CreateInsertion(KWLoc, "template<> ");<br>
- TemplateKWLoc = KWLoc;<br>
- isExplicitSpecialization = true;<br>
+ } else {<br>
+ assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");<br>
}<br>
<br>
// Check that the specialization uses the same tag kind as the<br>
@@ -5953,10 +5987,8 @@ Sema::ActOnClassTemplateSpecialization(S<br>
}<br>
<br>
// Translate the parser's template argument list in our AST format.<br>
- TemplateArgumentListInfo TemplateArgs;<br>
- TemplateArgs.setLAngleLoc(LAngleLoc);<br>
- TemplateArgs.setRAngleLoc(RAngleLoc);<br>
- translateTemplateArguments(TemplateArgsIn, TemplateArgs);<br>
+ TemplateArgumentListInfo TemplateArgs =<br>
+ makeTemplateArgumentListInfo(*this, TemplateId);<br>
<br>
// Check for unexpanded parameter packs in any of the template arguments.<br>
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)<br>
@@ -7416,13 +7448,8 @@ DeclResult Sema::ActOnExplicitInstantiat<br>
}<br>
<br>
// Translate the parser's template argument list into our AST format.<br>
- TemplateArgumentListInfo TemplateArgs;<br>
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;<br>
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);<br>
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);<br>
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br>
- TemplateId->NumArgs);<br>
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);<br>
+ TemplateArgumentListInfo TemplateArgs =<br>
+ makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);<br>
<br>
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,<br>
D.getIdentifierLoc(), TemplateArgs);<br>
@@ -7492,12 +7519,7 @@ DeclResult Sema::ActOnExplicitInstantiat<br>
bool HasExplicitTemplateArgs = false;<br>
TemplateArgumentListInfo TemplateArgs;<br>
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {<br>
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;<br>
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);<br>
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);<br>
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br>
- TemplateId->NumArgs);<br>
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);<br>
+ TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);<br>
HasExplicitTemplateArgs = true;<br>
}<br>
<br>
<br>
Modified: cfe/trunk/test/FixIt/fixit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=206442&r1=206441&r2=206442&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=206442&r1=206441&r2=206442&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/FixIt/fixit.cpp (original)<br>
+++ cfe/trunk/test/FixIt/fixit.cpp Wed Apr 16 22:29:33 2014<br>
@@ -19,7 +19,7 @@ virtual void C1::f() { } // expected-err<br>
<br>
static void C1::g() { } // expected-error{{'static' can only be specified inside the class definition}}<br>
<br>
-template<int Value> struct CT { }; // expected-note{{previous use is here}}<br>
+template<int Value> struct CT { template<typename> struct Inner; }; // expected-note{{previous use is here}}<br>
<br>
CT<10 >> 2> ct; // expected-warning{{require parentheses}}<br>
<br>
@@ -32,6 +32,8 @@ struct CT<0> { }; // expected-error{{'te<br>
<br>
template<> union CT<1> { }; // expected-error{{tag type}}<br>
<br>
+struct CT<2>::Inner<int> { }; // expected-error 2{{'template<>'}}<br>
+<br>
// Access declarations<br>
class A {<br>
protected:<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>