r206442 - Refactor all the checking for missing 'template<>'s when a declaration has a

Nico Weber thakis at chromium.org
Thu Jan 29 18:35:49 PST 2015


On Thu, Jan 29, 2015 at 5:51 PM, Nico Weber <thakis at chromium.org> wrote:

> r227540, thanks. I'll look
> through MatchTemplateParametersToScopeSpecifier() for places that need to
> set Invalid.
>

I think it's all good. All but one of the `return nullptr`s
call CheckExplicitSpecialization() (maybe
through DiagnoseMissingExplicitSpecialization()), and that sets Invalid to
true. The one place that doesn't is the `if (ParamIdx >=
ParamLists.size())` branch, and that branch is taken for valid code (e.g.
`class C {} C;`), so setting Invalid there is incorrect.


>
> On Thu, Jan 29, 2015 at 4:24 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
>
>> 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.
>>
>> On Wed, Jan 28, 2015 at 8:14 PM, Nico Weber <thakis at chromium.org> wrote:
>>
>>> On Wed, Apr 16, 2014 at 8:29 PM, Richard Smith <
>>> richard-llvm at metafoo.co.uk> wrote:
>>>
>>>> Author: rsmith
>>>> Date: Wed Apr 16 22:29:33 2014
>>>> New Revision: 206442
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=206442&view=rev
>>>> Log:
>>>> Refactor all the checking for missing 'template<>'s when a declaration
>>>> has a
>>>> template-id after its scope specifier into a single place.
>>>>
>>>> Modified:
>>>>     cfe/trunk/include/clang/Sema/Sema.h
>>>>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>>>>     cfe/trunk/lib/Sema/SemaDecl.cpp
>>>>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>>>     cfe/trunk/lib/Sema/SemaTemplate.cpp
>>>>     cfe/trunk/test/FixIt/fixit.cpp
>>>>
>>>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>>>> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 16 22:29:33 2014
>>>> @@ -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);
>>>>
>>>>
>>>> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
>>>> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Apr 16 22:29:33 2014
>>>> @@ -1541,18 +1541,11 @@ void Parser::ParseClassSpecifier(tok::To
>>>>        }
>>>>
>>>>        // 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) {
>>>>
>>>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>>>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr 16 22:29:33 2014
>>>> @@ -5228,29 +5228,13 @@ Sema::ActOnVariableDeclarator(Scope *S,
>>>>      // 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,
>>>>                     : diag::ext_variable_template);
>>>>          }
>>>>        }
>>>> +    } else {
>>>> +      assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
>>>> +             "should have a 'template<>' for this decl");
>>>>
>>>
>>> This assert fires on some invalid inputs, for example
>>>
>>>   template <typename> struct CT2 {
>>>     template <class U> struct X;
>>>   };
>>>   template <typename T> int CT2<int>::X<>;
>>>
>>> Is the right fix just to change this to assert(Invalid || D.getNameā€¦)?
>>> (Also attached in patch form.)
>>>
>>>
>>>>      }
>>>>
>>>>      if (IsVariableTemplateSpecialization) {
>>>> @@ -6709,8 +6696,12 @@ Sema::ActOnFunctionDeclarator(Scope *S,
>>>>      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,
>>>>          // 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,
>>>>            << 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,
>>>>        //   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
>>>>        (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;
>>>>
>>>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>>>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr 16 22:29:33 2014
>>>> @@ -11370,7 +11370,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scop
>>>>
>>>>    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.
>>>>
>>>> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
>>>> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr 16 22:29:33 2014
>>>> @@ -1593,6 +1593,9 @@ static SourceRange getRangeOfTypeInNeste
>>>>  /// 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 getRangeOfTypeInNeste
>>>>  /// 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::MatchTempla
>>>>          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::MatchTempla
>>>>        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(Temp
>>>>    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::ActOnVarTemplateSpecial
>>>>           "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(S
>>>>                                         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(S
>>>>    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(S
>>>>          << 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(S
>>>>    }
>>>>
>>>>    // 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::ActOnExplicitInstantiat
>>>>        }
>>>>
>>>>        // 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::ActOnExplicitInstantiat
>>>>    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;
>>>>    }
>>>>
>>>>
>>>> Modified: cfe/trunk/test/FixIt/fixit.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=206442&r1=206441&r2=206442&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/test/FixIt/fixit.cpp (original)
>>>> +++ cfe/trunk/test/FixIt/fixit.cpp Wed Apr 16 22:29:33 2014
>>>> @@ -19,7 +19,7 @@ virtual void C1::f() { } // expected-err
>>>>
>>>>  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{{'te
>>>>
>>>>  template<> union CT<1> { }; // expected-error{{tag type}}
>>>>
>>>> +struct CT<2>::Inner<int> { }; // expected-error 2{{'template<>'}}
>>>> +
>>>>  // Access declarations
>>>>  class A {
>>>>  protected:
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-commits mailing list
>>>> cfe-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>>
>>>
>>>
>>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150129/86c17dd4/attachment.html>


More information about the cfe-commits mailing list