On Thu, Sep 10, 2026 at 04:45:45PM +0200, Jakub Jelinek wrote: > Hi! > > The paper claims that GCC already implements it, which is only partially > the case. Non-dependent splice expression of a variable (of function > parameter or real variable) inside of contract conditions goes through > finish_id_expression -> finish_id_expression_1 which calls > constify_contract_access when needed. > We don't call it during tsubst_splice_expr though (and the paper requires > us to constify in that case), and on the other side, for splice expression > of a reflection of an object we weren't distinguishing it from splice > expression of a reflection of a variable. > > So, the following patch > 1) for splice wraps decls from REFLECT_OBJECT into a VCE, so that they > still act as lvalues, but aren't considered the variables themselves, > just an lvalue referencing them > 2) calls constify_contract_access during tsubst_splice_expr > > I've added all testcases from the paper (after fixing numerous bugs in > those), plus related stuff I could come up with. > > So far lightly tested (on > GXX_TESTSUITE_STDS=98,11,14,17,20,23,26,29 make check-g++ -j32 -k > RUNTESTFLAGS="dg.exp='reflect/*'" > ), ok for trunk if it passes full bootstrap/regtest? > > 2026-09-10 Jakub Jelinek <[email protected]> > > P3598R0 > PR c++/125840 > * reflect.cc: Implement C++26 CWG 3158 - const-ification of Splice > Expressions. > (splice): Remember REFLECT_EXPR_KIND of REFLECT_EXPR. Set refl to > REFLECT_EXPR_HANDLE earlier. For REFLECT_OBJECT wrap decls into > a VCE to differentiate it from corresponding variables. > * pt.cc (tsubst_splice_expr): Call constify_contract_access if > needed. > > * g++.dg/reflect/contract1.C: New test. > * g++.dg/reflect/contract2.C: New test. > * g++.dg/reflect/contract3.C: New test. > * g++.dg/reflect/contract4.C: New test. > * g++.dg/reflect/contract5.C: New test. > * g++.dg/reflect/reflect_object2.C (g): Add test for setting of > splice expr of an object reflection. > > --- a/gcc/cp/reflect.cc 2026-08-20 08:39:02.400320178 +0200 > +++ b/gcc/cp/reflect.cc 2026-09-10 15:54:22.535416674 +0200 > @@ -8782,12 +8782,14 @@ splice (tree refl) > return error_mark_node; > } > > + reflect_kind kind = REFLECT_EXPR_KIND (refl); > + refl = REFLECT_EXPR_HANDLE (refl); > + > /* We are bringing some entity from the unevaluated expressions world > to possibly outside of that, mark it used. */ > - if (!mark_used (REFLECT_EXPR_HANDLE (refl))) > + if (!mark_used (refl)) > return error_mark_node; > > - refl = REFLECT_EXPR_HANDLE (refl); > /* Function templates are wrapped in OVERLOAD from name lookup > and a lot of places assume that. Furthermore, if reflection comes > from ^^fntmpl, it is wrapped with OVERLOAD already, only when > @@ -8799,6 +8801,10 @@ splice (tree refl) > class for the access path. */ > if (is_overloaded_fn (refl)) > refl = baselink_for_fns (refl, /*ignore_current_class_p=*/true); > + /* For [:reflect_object(var):] wrap var into a VCE, so that it is an > lvalue, > + but not the var itself. */ > + if (kind == REFLECT_OBJECT && DECL_P (refl)) > + refl = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (refl), refl);
Should we give this VCE the location loc? I have no other comments. Marek
