Author: Luke Nihlen Date: 2022-11-28T18:40:19Z New Revision: afd800fc5679ccfe6f32b097586c658628500867
URL: https://github.com/llvm/llvm-project/commit/afd800fc5679ccfe6f32b097586c658628500867 DIFF: https://github.com/llvm/llvm-project/commit/afd800fc5679ccfe6f32b097586c658628500867.diff LOG: [clang] Require parameter pack to be last argument in concepts. Fixes GH48182. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/concepts.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ab7334e483282..3dcd65e3b25e1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -650,6 +650,8 @@ C++20 Feature Support ([temp.func.order]p6.2.1 is not implemented, matching GCC). - Implemented `P0857R0 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0857r0.html>`_, which specifies constrained lambdas and constrained template *template-parameter*\s. +- Required parameter pack to be provided at the end of the concept parameter list. This + fixes `Issue 48182 <https://github.com/llvm/llvm-project/issues/48182>`_. - Do not hide templated base members introduced via using-decl in derived class (useful specially for constrained members). Fixes `GH50886 <https://github.com/llvm/llvm-project/issues/50886>`_. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bb419e79a347a..a6abf556d2d7c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5981,8 +5981,12 @@ bool Sema::CheckTemplateArgumentList( // A non-expanded parameter pack before the end of the parameter list // only occurs for an ill-formed template parameter list, unless we've // got a partial argument list for a function template, so just bail out. - if (Param + 1 != ParamEnd) + if (Param + 1 != ParamEnd) { + assert( + (Template->getMostRecentDecl()->getKind() != Decl::Kind::Concept) && + "Concept templates must have parameter packs at the end."); return true; + } SugaredConverted.push_back( TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); @@ -8922,17 +8926,33 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, return nullptr; } - if (TemplateParameterLists.front()->size() == 0) { + TemplateParameterList *Params = TemplateParameterLists.front(); + + if (Params->size() == 0) { Diag(NameLoc, diag::err_concept_no_parameters); return nullptr; } + // Ensure that the parameter pack, if present, is the last parameter in the + // template. + for (TemplateParameterList::const_iterator ParamIt = Params->begin(), + ParamEnd = Params->end(); + ParamIt != ParamEnd; ++ParamIt) { + Decl const *Param = *ParamIt; + if (Param->isParameterPack()) { + if (++ParamIt == ParamEnd) + break; + Diag(Param->getLocation(), + diag::err_template_param_pack_must_be_last_template_parameter); + return nullptr; + } + } + if (DiagnoseUnexpandedParameterPack(ConstraintExpr)) return nullptr; - ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, - TemplateParameterLists.front(), - ConstraintExpr); + ConceptDecl *NewDecl = + ConceptDecl::Create(Context, DC, NameLoc, Name, Params, ConstraintExpr); if (NewDecl->hasAssociatedConstraints()) { // C++2a [temp.concept]p4: diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 8544635696331..df4db9b8d4457 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -766,3 +766,24 @@ void use2() { __iterator_traits_member_pointer_or_arrow_or_void<counted_iterator<int>> f; } }// namespace InheritedFromPartialSpec + +namespace GH48182 { +template<typename, typename..., typename = int> // expected-error{{template parameter pack must be the last template parameter}} +concept invalid = true; + +template<typename> requires invalid<int> // expected-error{{use of undeclared identifier 'invalid'}} +no errors are printed +; + +static_assert(invalid<int> also here ; // expected-error{{use of undeclared identifier 'invalid'}} + +int foo() { + bool b; + b = invalid<int> not just in declarations; // expected-error{{expected ';' after expression}} + // expected-error@-1{{use of undeclared identifier 'invalid'}} + // expected-error@-2{{expected ';' after expression}} + // expected-error@-3{{use of undeclared identifier 'just'}} + // expected-error@-4{{unknown type name 'in'}} + return b; +} +} // namespace GH48182 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits