[clang] bc93131 - [Clang] Implement CWG2517 Useless restriction on use of parameter in constraint-expression (#132919)

via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 7 02:31:07 PDT 2025


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 <corentinjabot at 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 at -1{{while checking the satisfaction of nested requirement requested here}}
+      // expected-note at -2{{in instantiation of requirement here}}
+      // expected-note at -3{{while checking the satisfaction of nested requirement requested here}}
+      // expected-note at -6{{while substituting template arguments into constraint expression here}}
+      // expected-note at -5{{function parameter 'a' with unknown value cannot be used in a constant expression}}
+      // expected-note at -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 at -1{{while checking the satisfaction of concept 'C2<int>' requested here}}
+    // expected-note at -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 at -1{{constraint variable 'x' cannot be used in an evaluated context}}
-// expected-note at -2{{'x' declared here}}
+// expected-warning at -1 {{left operand of comma operator has no effect}}
+// expected-warning at -2 {{variable length arrays in C++ are a Clang extension}}
+// expected-note at -3{{function parameter 'x' with unknown value cannot be used in a constant expression}}
+// expected-note at -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>


        


More information about the cfe-commits mailing list