On 9/23/26 5:07 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
In my P4101 patch I left the part that deals with taking the address of
a consteval function unresolved, leaving it as a follow-up.  Little did
I know that the follow-up wouldn't be just a small refinement, but a
relatively big change.

So, taking the address of a consteval function is no longer prohibited
outside an immediate function context, and a pointer or ptr-to-member
that points to an immediate function is a consteval-only value.  So
consteval_only_p has to be adjusted.  Since P4101 is a DR and consteval
functions are a C++20 thing, consteval_only_p & other spots cannot be
guarded with flag_reflection.  That might, unfortunately, penalize code
that doesn't use Reflection at all.

find_immediate_fndecl is now gone and instead, check_out_of_consteval_use
diagnoses invalid uses of the address of a consteval function.  The
diagnostic now looks like:

   error: consteval-only value outside an immediate function context
   note: taking address of an immediate function 'constexpr int f(auto:1) [with 
auto:1 = int]'

Problem #1: currently we detect out-of-consteval issues in
cp_genericize_r, but that runs too early, after parsing a function.  But
some functions will only be escalated at the end of the TU, so the
out-of-consteval detection needs to be done in cp_fold_immediate_r.  For
an example, see consteval-prop20.C and its "auto p = &f<int>;".
I think this matches the [expr.const.imm]/2 wording too.  But then
cp_fold_immediate_r has to be taught not to walk the initializer of
a constexpr variable, sort of like the if consteval code already
present.

Problem #2: PTRMEM_CST is a shared constant and carries PTRMEM_CST_LOCATION,
but that is the location of the & itself, not its use.  So I've added
a location wrapper around it in cp_fold_non_odr_use_1.  Without this,
the diagnostic would make no sense.  See e.g. value10.C.

Did you consider copying the PTRMEM_CST to give it the new location?

Problem #3: sometimes we fold things too early so we miss some
out-of-consteval diagnostics.  Due to this we accept some ill-formed code,
e.g. fp (), (o.*pm) (), or tbl[1].fp () where the operand is a constexpr
variable; see the comments in value9.C.  I've opened PR127478 though
that doesn't cover all of it.  I don't really have a good idea how to fix
this right now.  I suspect we might want to delay some folding, if possible.

Relatedly,

   consteval int f () { return 1; }
   consteval auto g () { return &f; }
   void fn () { int i; i = g () (); }

is still ill-formed, but would work were P3496 adopted.

This patch removes the !consteval_only_p assert in cp_finish_decl
because there the decl's DECL_INITIAL is still NULL_TREE (and so in the
value model it cannot be true).  In

   struct O { consteval int mf () const { return 1; } };
   constexpr auto pm = &O::mf;
   void
   fn (O o)
   {
     static constexpr auto spm = &O::mf;
   }

both spm and pm are handled by the consteval_only_p check in
make_rtl_for_nonlocal_decl.  The consequence is that pm and spm are no longer
emitted, even without -freflection.

Aside: I think Example 2 in [expr.const.const] is now wrong, the first
error is no longer expected after P4101.

Aside #2: I think [expr.const.const]/3.2 should say "subobject" instead
of "subject".  (I can open a pull request for both.)

Sounds good, I agree with both.
@@ -1480,7 +1526,23 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, 
void *data_)
            promote_function_to_consteval (current_function_decl);
          else if (complain & tf_error)
            {
-             if (call_p)
+             if (imm_const_p)
+               {
+                 if (!data->pset.add (*stmt_p)
+                     && !check_out_of_consteval_use (e, (data->decl
+                                                        ? data->decl
+                                                        : *stmt_p)))

Can you elaborate on why the ->decl handling is needed?

+      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))

This seems like an incomplete subset of scalarish_type_p that can't have consteval-only values. How about a new predicate function type_has_consteval_only_values?

Jason

Reply via email to