diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index d77036ff362c..962f0ce35f41 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2005,6 +2005,10 @@ public: SourceLocation RAngleLoc, TemplateArgumentListBuilder &Converted); + bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, + const TemplateArgument &Arg, + TemplateArgumentListBuilder &Converted); + bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg, SourceLocation ArgLoc); bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 78c1a9a97afb..f20bcd95ca14 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -975,6 +975,33 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name)); } +bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, + const TemplateArgument &Arg, + TemplateArgumentListBuilder &Converted) { + // Check template type parameter. + if (Arg.getKind() != TemplateArgument::Type) { + // C++ [temp.arg.type]p1: + // A template-argument for a template-parameter which is a + // type shall be a type-id. + + // We have a template type parameter but the template argument + // is not a type. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_type); + Diag(Param->getLocation(), diag::note_template_param_here); + + return true; + } + + if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation())) + return true; + + // Add the converted template type argument. + Converted.push_back( + TemplateArgument(Arg.getLocation(), + Context.getCanonicalType(Arg.getAsType()))); + return false; +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -1085,27 +1112,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { - // Check template type parameters. - if (Arg.getKind() == TemplateArgument::Type) { - if (CheckTemplateArgument(TTP, Arg.getAsType(), Arg.getLocation())) - Invalid = true; - - // Add the converted template type argument. - Converted.push_back( - TemplateArgument(Arg.getLocation(), - Context.getCanonicalType(Arg.getAsType()))); - continue; - } - - // C++ [temp.arg.type]p1: - // A template-argument for a template-parameter which is a - // type shall be a type-id. - - // We have a template type parameter but the template argument - // is not a type. - Diag(Arg.getLocation(), diag::err_template_arg_must_be_type); - Diag((*Param)->getLocation(), diag::note_template_param_here); - Invalid = true; + if (CheckTemplateTypeArgument(TTP, Arg, Converted)) + Invalid = true; } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*Param)) { // Check non-type template parameters.