On Thu, 3 Apr 2025, Jason Merrill wrote: > On 4/2/25 2:28 PM, Patrick Palka wrote: > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look > > OK for trunk/14? > > OK for 14. > > For 15, what happens if we remove that error entirely? Do we still give other > errors in that case? That seems to be the expectation of > https://eel.is/c++draft/basic.scope.param#note-1 and I'd expect that in a > constant-evaluated (and therefore evaluated) context we would complain about > it not being constant.
Indeed, it seems we do reliably error elsewhere if we remove that error, e.g. for parse/parameter-declaration-2.C we instead emit give: error: size of array ‘p’ is not an integral constant-expression But regtesting revealed that error path is also used to disambiguate vexing parses -- removing it causes us to now reject parse/ambig7.C: parse/ambig7.C:16:36: error: no matching function for call to ‘Helper::Helper(int, <unresolved overloaded function type>)’ So I guess we can't remove it outright just yet. > > I think the current rule that corresponds to that error is > https://eel.is/c++draft/basic.def.odr#10 -- odr-using a variable that isn't > odr-usable. process_outer_var_ref/mark_use make that distinction for > variables from an enclosing function, but I think for references outside of > any function constant-evaluation should handle it. > > > -- >8 -- > > > > Here we wrongly reject the requires-expression requirement at parse time > > due to the 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" code 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 in an evaluated context. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp2a/concepts-requires41.C: New test. > > --- > > gcc/cp/semantics.cc | 1 + > > .../g++.dg/cpp2a/concepts-requires41.C | 23 +++++++++++++++++++ > > 2 files changed, 24 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C > > > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > > index 7d8beb8833d..a10ef34383c 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 00000000000..840ed86c4ac > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires41.C > > @@ -0,0 +1,23 @@ > > +// 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>); > >