diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5748339015906..2cce502234f42 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -141,6 +141,8 @@ Resolutions to C++ Defect Reports - Bumped the ``__cpp_constexpr`` feature-test macro to ``202002L`` in C++20 mode as indicated in `P2493R0 `_. +- Implemented `CWG2517 Useless restriction on use of parameter in ` + `constraint-expression `_. - Implemented `CWG3005 Function parameters should never be name-independent `_. C Language Changes diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6e940a318b61d..b16368027ab1d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3082,8 +3082,6 @@ def err_reference_to_function_with_unsatisfied_constraints : Error< "invalid reference to function %0: constraints not satisfied">; def err_requires_expr_local_parameter_default_argument : Error< "default arguments not allowed for parameters of a requires expression">; -def err_requires_expr_parameter_referenced_in_evaluated_context : Error< - "constraint variable %0 cannot be used in an evaluated context">; def note_expr_requirement_expr_substitution_error : Note< "%select{and|because}0 '%1' would be invalid: %2">; def note_expr_requirement_expr_unknown_substitution_error : Note< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2c81f7c583eb6..8e428d04be8a5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -397,17 +397,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, targetDiag(*Locs.begin(), diag::err_thread_unsupported); } - if (isa(D) && isa(D->getDeclContext()) && - !isUnevaluatedContext()) { - // C++ [expr.prim.req.nested] p3 - // A local parameter shall only appear as an unevaluated operand - // (Clause 8) within the constraint-expression. - Diag(Loc, diag::err_requires_expr_parameter_referenced_in_evaluated_context) - << D; - Diag(D->getLocation(), diag::note_entity_declared_at) << D; - return true; - } - return false; } diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp index d9a7d2bbb2671..5c2948f67d0ee 100644 --- a/clang/test/CXX/drs/cwg25xx.cpp +++ b/clang/test/CXX/drs/cwg25xx.cpp @@ -32,6 +32,26 @@ enum E2 : S::I { e }; #endif } // namespace cwg2516 +namespace cwg2517 { // cwg2517: 21 +#if __cplusplus >= 202002L +template +concept LargeArray = requires (ArrayType my_array) { + requires my_array.size() > 5; +}; + +struct Big { + constexpr int size() const { return 100; } +}; + +struct Small { + constexpr int size() const { return 3; } +}; + +static_assert(LargeArray); +static_assert(!LargeArray); +#endif +} // namespace cwg2517 + namespace cwg2518 { // cwg2518: 17 #if __cplusplus >= 201103L diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp index 651cca927d513..f621cff00128a 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp @@ -41,9 +41,17 @@ namespace std_example { template concept C2 = requires (T a) { requires sizeof(a) == 4; // OK - requires a == 0; // expected-note{{because 'a == 0' would be invalid: constraint variable 'a' cannot be used in an evaluated context}} + requires a == 0; // expected-error{{substitution into constraint expression resulted in a non-constant expression}} + // expected-note@-1{{while checking the satisfaction of nested requirement requested here}} + // expected-note@-2{{in instantiation of requirement here}} + // expected-note@-3{{while checking the satisfaction of nested requirement requested here}} + // expected-note@-6{{while substituting template arguments into constraint expression here}} + // expected-note@-5{{function parameter 'a' with unknown value cannot be used in a constant expression}} + // expected-note@-8{{declared here}} }; - static_assert(C2); // expected-note{{because 'int' does not satisfy 'C2'}} expected-error{{static assertion failed}} + static_assert(C2); // expected-error{{static assertion failed}} + // expected-note@-1{{while checking the satisfaction of concept 'C2' requested here}} + // expected-note@-2{{because 'int' does not satisfy 'C2'}} } template diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp index 7515f5c62d5ea..5199708cd8166 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp @@ -102,8 +102,10 @@ namespace std_example { // of a polymorphic type. class X { virtual ~X(); }; constexpr bool b = requires (X &x) { static_cast(nullptr); }; -// expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}} -// expected-note@-2{{'x' declared here}} +// expected-warning@-1 {{left operand of comma operator has no effect}} +// expected-warning@-2 {{variable length arrays in C++ are a Clang extension}} +// expected-note@-3{{function parameter 'x' with unknown value cannot be used in a constant expression}} +// expected-note@-4{{declared here}} namespace access_checks { namespace in_requires_expression { diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 52c9cb7d37c23..6e8ecc7913f9a 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -14937,7 +14937,7 @@

C++ defect report implementation status

2517 C++23 Useless restriction on use of parameter in constraint-expression - Unknown + Clang 21 2518