diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-03 21:13:47 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-03 21:13:47 +0000 |
commit | 875b6fe364372e9021012fb32eccc49e39c7b0fb (patch) | |
tree | 893946babec77bdefb0ec4f35778c09a5f19cb59 /clang | |
parent | 4423070356e64d36d1772e2ef89b6acfabed1fb2 (diff) | |
download | bcm5719-llvm-875b6fe364372e9021012fb32eccc49e39c7b0fb.tar.gz bcm5719-llvm-875b6fe364372e9021012fb32eccc49e39c7b0fb.zip |
Unwrap template argument packs when checking the template arguments of
a class template partial specialiation, and look through pack
expansions when checking the conditions of C++0x [temp.class.spec]p8.
llvm-svn: 122774
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 82 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp | 8 |
3 files changed, 62 insertions, 32 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2d349bc34c2..b5dfe0a480c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2910,10 +2910,6 @@ public: bool EnteringContext, TemplateTy &Template); - bool CheckClassTemplatePartialSpecializationArgs( - TemplateParameterList *TemplateParams, - llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs); - DeclResult ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6384e53e80b..c3cfbb8c258 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3915,34 +3915,31 @@ static bool CheckTemplateSpecializationScope(Sema &S, return false; } - -/// \brief Check the non-type template arguments of a class template -/// partial specialization according to C++ [temp.class.spec]p9. -/// -/// \param TemplateParams the template parameters of the primary class -/// template. -/// -/// \param TemplateArg the template arguments of the class template -/// partial specialization. -/// -/// \returns true if there was an error, false otherwise. -bool Sema::CheckClassTemplatePartialSpecializationArgs( - TemplateParameterList *TemplateParams, - llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) { - const TemplateArgument *ArgList = TemplateArgs.data(); - - for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { - NonTypeTemplateParmDecl *Param - = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I)); - if (!Param) + +/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs +/// that checks non-type template partial specialization arguments. +static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I].getKind() == TemplateArgument::Pack) { + if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, + Args[I].pack_begin(), + Args[I].pack_size())) + return true; + continue; - - Expr *ArgExpr = ArgList[I].getAsExpr(); + } + + Expr *ArgExpr = Args[I].getAsExpr(); if (!ArgExpr) { continue; } - // FIXME: Variadic templates. Unwrap argument packs. + // We can have a pack expansion of any of the above. + if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr)) + ArgExpr = Expansion->getPattern(); // C++ [temp.class.spec]p8: // A non-type argument is non-specialized if it is the name of a @@ -3964,24 +3961,53 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // specialization except when the argument expression is a // simple identifier. if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) { - Diag(ArgExpr->getLocStart(), + S.Diag(ArgExpr->getLocStart(), diag::err_dependent_non_type_arg_in_partial_spec) << ArgExpr->getSourceRange(); return true; } - + // -- The type of a template parameter corresponding to a // specialized non-type argument shall not be dependent on a // parameter of the specialization. if (Param->getType()->isDependentType()) { - Diag(ArgExpr->getLocStart(), + S.Diag(ArgExpr->getLocStart(), diag::err_dependent_typed_non_type_arg_in_partial_spec) << Param->getType() << ArgExpr->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } } + + return false; +} + +/// \brief Check the non-type template arguments of a class template +/// partial specialization according to C++ [temp.class.spec]p9. +/// +/// \param TemplateParams the template parameters of the primary class +/// template. +/// +/// \param TemplateArg the template arguments of the class template +/// partial specialization. +/// +/// \returns true if there was an error, false otherwise. +static bool CheckClassTemplatePartialSpecializationArgs(Sema &S, + TemplateParameterList *TemplateParams, + llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) { + const TemplateArgument *ArgList = TemplateArgs.data(); + + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + NonTypeTemplateParmDecl *Param + = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I)); + if (!Param) + continue; + + if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, + &ArgList[I], 1)) + return true; + } return false; } @@ -4145,7 +4171,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Find the class template (partial) specialization declaration that // corresponds to these arguments. if (isPartialSpecialization) { - if (CheckClassTemplatePartialSpecializationArgs( + if (CheckClassTemplatePartialSpecializationArgs(*this, ClassTemplate->getTemplateParameters(), Converted)) return true; diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp new file mode 100644 index 00000000000..14152cf339a --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<int ...Values> struct X1; + +template<int ...Values> +struct X1<0, Values+1 ...>; // expected-error{{non-type template argument depends on a template parameter of the partial specialization}} + + |