[clang] afd800f - [clang] Require parameter pack to be last argument in concepts.
Luke Nihlen via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 28 10:41:31 PST 2022
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 at -1{{use of undeclared identifier 'invalid'}}
+ // expected-error at -2{{expected ';' after expression}}
+ // expected-error at -3{{use of undeclared identifier 'just'}}
+ // expected-error at -4{{unknown type name 'in'}}
+ return b;
+}
+} // namespace GH48182
More information about the cfe-commits
mailing list