diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-17 03:29:33 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-17 03:29:33 +0000 |
commit | 8b7a1c51e488639a3fe3854cc03955e9c5b21876 (patch) | |
tree | 9ed8f6fd50bd0ab76c27e1b2427f7246c8e37ae1 /lib/Sema/SemaTemplate.cpp | |
parent | d9974190c26c0ee9d8e1a8e6b569b2c89e9885b3 (diff) |
Refactor all the checking for missing 'template<>'s when a declaration has a
template-id after its scope specifier into a single place.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206442 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 9be7189ba9..58742fc055 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1593,6 +1593,9 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, /// 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 getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, /// 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::MatchTemplateParametersToScopeSpecifier( 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::MatchTemplateParametersToScopeSpecifier( 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(TemplateParameterList *Params, 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::ActOnVarTemplateSpecialization( "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(Scope *S, unsigned TagSpec, 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(Scope *S, unsigned TagSpec, 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(Scope *S, unsigned TagSpec, << 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(Scope *S, unsigned TagSpec, } // 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::ActOnExplicitInstantiation(Scope *S, } // 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::ActOnExplicitInstantiation(Scope *S, 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; } |