[clang] Fix the local parameter of void type inside the Requires expression. (#109831)

Fixes #109538.

In this patch, we introduce diagnostic for required expression
parameters in the same way as function parameters, fix the issue of
handling void type parameters, and align the behavior with GCC and other
compilers.
This commit is contained in:
c8ef 2024-10-01 21:39:10 +08:00 committed by GitHub
parent be6b4f6979
commit bb78a0b334
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 1 deletions

View File

@ -362,6 +362,8 @@ Improvements to Clang's diagnostics
- Clang now diagnoses cases where a dangling ``GSLOwner<GSLPointer>`` object is constructed, e.g. ``std::vector<string_view> 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
----------------------------------

View File

@ -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

View File

@ -65,4 +65,18 @@ template<typename T> requires requires { T::value; S<T>::s; }
struct r4 { };
using r4i = r4<int>;
// expected-error@-1 {{constraints not satisfied for class template 'r4' [with T = int]}}
// 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