diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 28c759538f7df..24f0d27923413 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -359,6 +359,8 @@ Improvements to Clang's diagnostics - Clang now diagnoses cases where a dangling ``GSLOwner`` object is constructed, e.g. ``std::vector v = {std::string()};`` (#GH100526). +- Clang now diagnoses when a ``requires`` expression has a local parameter of void type, aligning with the function parameter (#GH109831). + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ac3fe6ab8f9bd..b30414a8a8277 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -9509,6 +9509,18 @@ Sema::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, PushDeclContext(BodyScope, Body); for (ParmVarDecl *Param : LocalParameters) { + if (Param->getType()->isVoidType()) { + if (LocalParameters.size() > 1) { + Diag(Param->getBeginLoc(), diag::err_void_only_param); + Param->setType(Context.IntTy); + } else if (Param->getIdentifier()) { + Diag(Param->getBeginLoc(), diag::err_param_with_void_type); + Param->setType(Context.IntTy); + } else if (Param->getType().hasQualifiers()) { + Diag(Param->getBeginLoc(), diag::err_void_param_qualified); + } + } + if (Param->hasDefaultArg()) // C++2a [expr.prim.req] p4 // [...] A local parameter of a requires-expression shall not have a diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp index 90a38292d15d3..09f8f36d3c5ba 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp @@ -65,4 +65,18 @@ template requires requires { T::value; S::s; } struct r4 { }; using r4i = r4; -// expected-error@-1 {{constraints not satisfied for class template 'r4' [with T = int]}} \ No newline at end of file +// expected-error@-1 {{constraints not satisfied for class template 'r4' [with T = int]}} + +namespace GH109538 { +static_assert(requires(void *t) { t; }); +static_assert(requires(void) { 42; }); +static_assert(requires(void t) { // expected-error {{argument may not have 'void' type}} + t; +}); +static_assert(requires(void t, int a) { // expected-error {{'void' must be the first and only parameter if specified}} + t; +}); +static_assert(requires(const void) { // expected-error {{'void' as parameter must not have type qualifiers}} + 42; +}); +} // namespace GH109538