Author: Imad Aldij Date: 2025-06-07T11:31:04+02:00 New Revision: bc931318a2880360f3970e1e6906adc9c90eb698
URL: https://github.com/llvm/llvm-project/commit/bc931318a2880360f3970e1e6906adc9c90eb698 DIFF: https://github.com/llvm/llvm-project/commit/bc931318a2880360f3970e1e6906adc9c90eb698.diff LOG: [Clang] Implement CWG2517 Useless restriction on use of parameter in constraint-expression (#132919) Remove `[expr.prim.req.nested]` check which restrict that local parameters in constraint-expressions can only appear as unevaluated operands. This change makes the treatment of examples like `requires` expressions and other constant expression contexts uniform, consistent with the adoption of P2280. References: https://cplusplus.github.io/CWG/issues/2517.html Fixes #132825 --------- Co-authored-by: cor3ntin <corentinja...@gmail.com> Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaExpr.cpp clang/test/CXX/drs/cwg25xx.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9ab69320f0368..74a205a85da5c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -153,6 +153,8 @@ Resolutions to C++ Defect Reports - Bumped the ``__cpp_constexpr`` feature-test macro to ``202002L`` in C++20 mode as indicated in `P2493R0 <https://wg21.link/P2493R0>`_. +- Implemented `CWG2517 Useless restriction on use of parameter in ` + `constraint-expression <https://cplusplus.github.io/CWG/issues/2517.html>`_. - Implemented `CWG3005 Function parameters should never be name-independent <https://wg21.link/CWG3005>`_. C Language Changes diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e963612f387ef..5f44d503580b9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3108,8 +3108,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 9c322deb55e00..c7abbbd6993de 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -397,17 +397,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, targetDiag(*Locs.begin(), diag::err_thread_unsupported); } - if (isa<ParmVarDecl>(D) && isa<RequiresExprBodyDecl>(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<E2>::I { e }; #endif } // namespace cwg2516 +namespace cwg2517 { // cwg2517: 21 +#if __cplusplus >= 202002L +template<typename ArrayType> +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<Big>); +static_assert(!LargeArray<Small>); +#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 19145f68b2f75..033ae349a02e5 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<typename T> 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<int>); // expected-note{{because 'int' does not satisfy 'C2'}} expected-error{{static assertion failed}} + static_assert(C2<int>); // expected-error{{static assertion failed}} + // expected-note@-1{{while checking the satisfaction of concept 'C2<int>' requested here}} + // expected-note@-2{{because 'int' does not satisfy 'C2'}} } template<typename T> 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<int(*)[(typeid(x), 0)]>(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 58286db165077..d06eb4a0ed23e 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -14937,7 +14937,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/2517.html">2517</a></td> <td>C++23</td> <td>Useless restriction on use of parameter in <I>constraint-expression</I></td> - <td class="unknown" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 21</td> </tr> <tr id="2518"> <td><a href="https://cplusplus.github.io/CWG/issues/2518.html">2518</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits