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

Reply via email to