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