Created on 2026-02-13.00:00:00 last changed 2 days ago
Suggested resolution:
This also resolves issue 3127.
Change in 7.7 [expr.const] paragraph 30 as follows:
During an evaluation V (6.10.1 [intro.execution]) of an expression, conversion, or initialization E as a core constant expression, the point of evaluation of E during V is the program point P determined as follows:
- If E is a potentially-evaluated subexpression of a default member initializer I, and V is the evaluation of E in the evaluation of I as an immediate subexpression of a (possibly aggregate) initialization, then P is the point of evaluation of that initialization.
- Otherwise, if E is a potentially-evaluated subexpression of a default argument A (9.3.4.7 [dcl.fct.default]), and V is the evaluation of E in the evaluation of A as an immediate subexpression of a function call (7.6.1.3 [expr.call]), then P is the point of evaluation of that function call.
- Otherwise, P is the point at which E appears.
Theevaluation contextevaluation context is a set of program points that determines the behavior of certain functions used for reflection (21.4 [meta.reflection]). During the evaluation V of an expression E as a core constant expression, theevaluation contextevaluation context of an evaluation X(6.10.1 [intro.execution]) consists of the following pointsduring V is the set C of program points determined as follows:
- The program point EVAL-PT(L), where L is the point at which E appears, and where EVAL-PT(P), for a point P, is a point R determined as follows:
- If a potentially-evaluated subexpression (6.10.1 [intro.execution]) of a default member initializer I appears at P , and a (possibly aggregate) initialization during V is using I, then R is EVAL-PT(Q) where Q is the point at which that initialization appears.
- Otherwise, if a potentially-evaluated subexpression of a default argument (9.3.4.7 [dcl.fct.default]) appears at P, and an invocation of a function (7.6.1.3 [expr.call]) during V is using that default argument, then R is EVAL-PT(Q) where Q is the point at which that invocation appears.
- Otherwise, R is P.
- If the execution of X occurs during the evaluation Y of a manifestly constant-evaluated expression, then C is the evaluation context of X during Y.
- Otherwise, C contains
- the point of evaluation of E during V and each synthesized point in the instantiation context thereof and
Eacheach synthesized point corresponding to an injected declaration produced by any evaluation executed during V that is sequenced before X (6.10.1 [intro.execution]).
(From submission #848.)
Consider:
struct S;
consteval size_t f() {
constexpr bool b = is_complete_type(^^S);
return b ? 1 : 2;
}
struct T;
consteval {
define_aggregate(^^S, {});
define_aggregate(^^T, {
data_member_spec(^^int, {.name="m", .bit_width=f()}),
});
}
int main() {
return bit_size_of(^^T::m);
}
The Working Draft arguably says that this program should exit with status 1: During the evaluation of the expression corresponding to the consteval-block, the evaluation of is_complete_type(^^S) contains the synthesized point associated with the injected declaration of S; therefore, the type is complete.
But this was never the intention of P2996; the intention was to evaluate manifestly constant-evaluated expressions at the point where they appear. The problem is that we didn't consider manifestly constant-evaluated expressions that might be executed (formally, per the abstract machine) during the evaluation of other manifestly constant-evaluated expressions.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2026-03-05 08:23:53 | admin | set | messages: + msg8497 |
| 2026-02-13 00:00:00 | admin | create | |