<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>