Skip to content

Commit bc93131

Browse files
imdjcor3ntin
andauthored
[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@gmail.com>
1 parent 432c5f2 commit bc93131

File tree

7 files changed

+37
-18
lines changed

7 files changed

+37
-18
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ Resolutions to C++ Defect Reports
153153
- Bumped the ``__cpp_constexpr`` feature-test macro to ``202002L`` in C++20 mode as indicated in
154154
`P2493R0 <https://wg21.link/P2493R0>`_.
155155

156+
- Implemented `CWG2517 Useless restriction on use of parameter in `
157+
`constraint-expression <https://cplusplus.github.io/CWG/issues/2517.html>`_.
156158
- Implemented `CWG3005 Function parameters should never be name-independent <https://wg21.link/CWG3005>`_.
157159

158160
C Language Changes

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,8 +3108,6 @@ def err_reference_to_function_with_unsatisfied_constraints : Error<
31083108
"invalid reference to function %0: constraints not satisfied">;
31093109
def err_requires_expr_local_parameter_default_argument : Error<
31103110
"default arguments not allowed for parameters of a requires expression">;
3111-
def err_requires_expr_parameter_referenced_in_evaluated_context : Error<
3112-
"constraint variable %0 cannot be used in an evaluated context">;
31133111
def note_expr_requirement_expr_substitution_error : Note<
31143112
"%select{and|because}0 '%1' would be invalid: %2">;
31153113
def note_expr_requirement_expr_unknown_substitution_error : Note<

clang/lib/Sema/SemaExpr.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
397397
targetDiag(*Locs.begin(), diag::err_thread_unsupported);
398398
}
399399

400-
if (isa<ParmVarDecl>(D) && isa<RequiresExprBodyDecl>(D->getDeclContext()) &&
401-
!isUnevaluatedContext()) {
402-
// C++ [expr.prim.req.nested] p3
403-
// A local parameter shall only appear as an unevaluated operand
404-
// (Clause 8) within the constraint-expression.
405-
Diag(Loc, diag::err_requires_expr_parameter_referenced_in_evaluated_context)
406-
<< D;
407-
Diag(D->getLocation(), diag::note_entity_declared_at) << D;
408-
return true;
409-
}
410-
411400
return false;
412401
}
413402

clang/test/CXX/drs/cwg25xx.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ enum E2 : S<E2>::I { e };
3232
#endif
3333
} // namespace cwg2516
3434

35+
namespace cwg2517 { // cwg2517: 21
36+
#if __cplusplus >= 202002L
37+
template<typename ArrayType>
38+
concept LargeArray = requires (ArrayType my_array) {
39+
requires my_array.size() > 5;
40+
};
41+
42+
struct Big {
43+
constexpr int size() const { return 100; }
44+
};
45+
46+
struct Small {
47+
constexpr int size() const { return 3; }
48+
};
49+
50+
static_assert(LargeArray<Big>);
51+
static_assert(!LargeArray<Small>);
52+
#endif
53+
} // namespace cwg2517
54+
3555
namespace cwg2518 { // cwg2518: 17
3656

3757
#if __cplusplus >= 201103L

clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,17 @@ namespace std_example {
4141
template<typename T>
4242
concept C2 = requires (T a) {
4343
requires sizeof(a) == 4; // OK
44-
requires a == 0; // expected-note{{because 'a == 0' would be invalid: constraint variable 'a' cannot be used in an evaluated context}}
44+
requires a == 0; // expected-error{{substitution into constraint expression resulted in a non-constant expression}}
45+
// expected-note@-1{{while checking the satisfaction of nested requirement requested here}}
46+
// expected-note@-2{{in instantiation of requirement here}}
47+
// expected-note@-3{{while checking the satisfaction of nested requirement requested here}}
48+
// expected-note@-6{{while substituting template arguments into constraint expression here}}
49+
// expected-note@-5{{function parameter 'a' with unknown value cannot be used in a constant expression}}
50+
// expected-note@-8{{declared here}}
4551
};
46-
static_assert(C2<int>); // expected-note{{because 'int' does not satisfy 'C2'}} expected-error{{static assertion failed}}
52+
static_assert(C2<int>); // expected-error{{static assertion failed}}
53+
// expected-note@-1{{while checking the satisfaction of concept 'C2<int>' requested here}}
54+
// expected-note@-2{{because 'int' does not satisfy 'C2'}}
4755
}
4856

4957
template<typename T>

clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ namespace std_example {
102102
// of a polymorphic type.
103103
class X { virtual ~X(); };
104104
constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); };
105-
// expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}}
106-
// expected-note@-2{{'x' declared here}}
105+
// expected-warning@-1 {{left operand of comma operator has no effect}}
106+
// expected-warning@-2 {{variable length arrays in C++ are a Clang extension}}
107+
// expected-note@-3{{function parameter 'x' with unknown value cannot be used in a constant expression}}
108+
// expected-note@-4{{declared here}}
107109

108110
namespace access_checks {
109111
namespace in_requires_expression {

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14937,7 +14937,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1493714937
<td><a href="https://cplusplus.github.io/CWG/issues/2517.html">2517</a></td>
1493814938
<td>C++23</td>
1493914939
<td>Useless restriction on use of parameter in <I>constraint-expression</I></td>
14940-
<td class="unknown" align="center">Unknown</td>
14940+
<td class="unreleased" align="center">Clang 21</td>
1494114941
</tr>
1494214942
<tr id="2518">
1494314943
<td><a href="https://cplusplus.github.io/CWG/issues/2518.html">2518</a></td>

0 commit comments

Comments
 (0)