r206442 - Refactor all the checking for missing 'template<>'s when a declaration has a
Richard Smith
richard at metafoo.co.uk
Thu Jan 29 16:24:17 PST 2015
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
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150129/fcb3c6a9/attachment.html>
More information about the cfe-commits
mailing list