https://gcc.gnu.org/g:6e973e87e3fec6f33e97edf8fce2fcd121e53961
commit r15-9203-g6e973e87e3fec6f33e97edf8fce2fcd121e53961 Author: Patrick Palka <ppa...@redhat.com> Date: Fri Apr 4 14:03:58 2025 -0400 c++: constraint variable used in evaluated context [PR117849] Here we wrongly reject the type-requirement at parse time due to its use of the constraint variable 't' within a template argument (an evaluated context). Fix this simply by refining the "use of parameter outside function body" error path to exclude constraint variables. PR c++/104255 tracks the same issue for function parameters, but fixing that would be more involved, requiring changes to the PARM_DECL case of tsubst_expr. PR c++/117849 gcc/cp/ChangeLog: * semantics.cc (finish_id_expression_1): Allow use of constraint variable outside an unevaluated context. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-requires41.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/semantics.cc | 1 + gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C | 25 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 7d8beb8833d3..a10ef34383c2 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -4755,6 +4755,7 @@ finish_id_expression_1 (tree id_expression, body, except inside an unevaluated context (i.e. decltype). */ if (TREE_CODE (decl) == PARM_DECL && DECL_CONTEXT (decl) == NULL_TREE + && !CONSTRAINT_VAR_P (decl) && !cp_unevaluated_operand && !processing_contract_condition && !processing_omp_trait_property_expr) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C new file mode 100644 index 000000000000..28c976116cad --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C @@ -0,0 +1,25 @@ +// PR c++/117849 +// { dg-do compile { target c++20 } } + +template<int N> +struct array { + constexpr int size() const { return N; } +}; + +struct vector { + int _size = 3; + constexpr int size() const { return _size; } +}; + +template<int N> +struct integral_constant { + constexpr operator int() const { return N; } +}; + +template<class T> +concept StaticSize = requires (T& t) { + typename integral_constant<t.size()>; +}; + +static_assert(StaticSize<array<5>>); +static_assert(!StaticSize<vector>);