This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


2924. Undefined behavior during constant evaluation

Section: 3.63  [defns.undefined]     Status: tentatively ready     Submitter: Jan Schultke     Date: 2024-06-04

(From editorial issue #7042 and submission #595.)

Subclause 3.63 [defns.undefined] states:

[Note 1 to entry: ... Evaluation of a constant expression (7.7 [expr.const]) never exhibits behavior explicitly specified as undefined in Clause 4 [intro] through Clause 15 [cpp]. —end note]

However, 7.7 [expr.const] bullet 5.8 excludes [[noreturn]] and [[assume]]; see also 7.7 [expr.const] paragraph 6.

Suggested resolution [SUPERSEDED]:

Change in 3.63 [defns.undefined] as follows:

[Note 1 to entry: ... Evaluation of a constant expression (7.7 [expr.const]) never exhibits behavior explicitly specified as undefined in Clause 4 [intro] through Clause 15 [cpp], excluding 9.12 [dcl.attr]. —end note]

CWG 2024-09-13

Admitting unbounded core-language undefined behavior in constant expressions is to be avoided. The quoted note is correct; the semantics of [[noreturn]] and [[assume]] need to be clarified.

Possible resolution [SUPERSEDED]:

  1. Change in 9.12.3 [dcl.attr.assume] paragraph 1 as follows:

    ... The expression is not evaluated. If the converted expression would evaluate to true at the point where the assumption appears or if the assumption is evaluated in a context that is manifestly constant-evaluated, the assumption has no effect. Otherwise, the behavior is undefined.
  2. Change in 9.12.11 [dcl.attr.noreturn] paragraph 2 as follows:

    If a function f is called where f was previously declared with the noreturn attribute, the function call is evaluated in a context that is not manifestly constant-evaluated (7.7 [expr.const]), and f eventually returns, the behavior is undefined.

CWG 2024-09-27

The suggested resolution is circular with the rules in 7.7 [expr.const] paragraph 6.

Possible resolution [SUPERSEDED]:

  1. Change in 9.12.3 [dcl.attr.assume] paragraph 1 as follows:

    ... The expression is not evaluated. If the converted expression would evaluate to true at the point where the assumption appears, the assumption has no effect. Otherwise, outside of an evaluation to determine whether an expression is a core constant expression (7.7 [expr.const]), the behavior is undefined.
  2. Change in 9.12.11 [dcl.attr.noreturn] paragraph 2 as follows:

    If a function f is called where f was previously declared with the noreturn attribute, the function call is evaluated outside of an evaluation to determine whether an expression is a core constant expression (7.7 [expr.const]), and f eventually returns, the behavior is undefined.

CWG 2024-10-11

Implementations have two options: Either a violation of an attribute causes an expressions not to be a constant expression, leading to runtime undefined behavior, or the attribute has no effect during constant evaluation.

Possible resolution [SUPERSEDED]:

  1. Change in 7.7 [expr.const] paragraph 6:

    It is implementation-defined whether E is a core constant expression in the situations specified in 9.12.3 [dcl.attr.assume] and 9.12.11 [dcl.attr.noreturn].

    It is unspecified whether E is a core constant expression if E satisfies the constraints of a core constant expression, but evaluation of E would evaluate

    • an operation that has undefined behavior as specified in Clause 16 [library] through Clause 34 [exec], or
    • an invocation of the va_start macro (17.13.2 [cstdarg.syn]),.
    • a call to a function that was previously declared with the noreturn attribute (9.12.11 [dcl.attr.noreturn]) and that call returns to its caller, or
    • a statement with an assumption (9.12.3 [dcl.attr.assume]) whose converted conditional-expression, if evaluated where the assumption appears, would not disqualify E from being a core constant expression and would not evaluate to true. [Note 5: E is not disqualified from being a core constant expression if the hypothetical evaluation of the converted conditional-expression would disqualify E from being a core constant expression. —end note]
  2. Change in 9.12.3 [dcl.attr.assume] paragraph 1 as follows:

    ... The expression is not evaluated.
    • If the converted expression would evaluate to true at the point where the assumption appears, the assumption has no effect.
    • Otherwise, if the statement with the assumption would be evaluated as part of an evaluation of an expression E that satisfies the constraints of a core constant expression (7.7 [expr.const]):
      • If the converted expression, evaluated at the point where the assumption appears, would disqualify E from being a core constant expression, the assumption is ignored.
      • Otherwise, it is implementation-defined whether E is a core constant expression; if E is evaluated as a core constant expression, the assumption has no effect.
    • Otherwise, the behavior is undefined.
  3. Change in 9.12.11 [dcl.attr.noreturn] paragraph 2 as follows:

    If a function f is called where f was previously declared with the noreturn attribute and f eventually returns:
    • If the function call would be part of an evaluation of an expression E that satisfies the constraints of a core constant expression (7.7 [expr.const]), it is implementation-defined whether E is a core constant expression; if E is evaluated as a core constant expression, the attribute has no effect.
    • Otherwise, the behavior is undefined.

CWG 2024-10-25

CWG prefers an approach suggested by Richard Smith that defines a new term "runtime undefined behavior".

Proposed resolution (approved by CWG 2024-11-08):

  1. Add to Clause 3 [intro.defs]:

    constant evaluation [defns.const.eval]

    evaluation that is performed as part of evaluating an expression as a core constant expression (7.7 [expr.const])

    runtime-undefined behavior [defns.undefined.runtime]

    behavior that is undefined except when it occurs during constant evaluation

    [Note 1 to entry: During constant evaluation,

    • it is implementation-defined whether runtime-undefined behavior results in the expression being deemed non-constant (as specified in 7.7 [expr.const]) and
    • runtime-undefined behavior has no other effect.]

  2. Change in 7.7 [expr.const] bullet 5.8 as follows:

  3. Add a paragraph after 7.7 [expr.const] paragraph 5 as follows:

    It is implementation-defined whether E is a core constant expression if E satisfies the constraints of a core constant expression, but evaluation of E has runtime-undefined behavior.
  4. Change in 7.7 [expr.const] paragraph 6:

    It is unspecified whether E is a core constant expression if E satisfies the constraints of a core constant expression, but evaluation of E would evaluate

    • an operation that has undefined behavior as specified in Clause 16 [library] through Clause 34 [exec], or
    • an invocation of the va_start macro (17.13.2 [cstdarg.syn]),.
    • a call to a function that was previously declared with the noreturn attribute (9.12.11 [dcl.attr.noreturn]) and that call returns to its caller, or
    • a statement with an assumption (9.12.3 [dcl.attr.assume]) whose converted conditional-expression, if evaluated where the assumption appears, would not disqualify E from being a core constant expression and would not evaluate to true. [Note 5: E is not disqualified from being a core constant expression if the hypothetical evaluation of the converted conditional-expression would disqualify E from being a core constant expression. —end note]
  5. Change in 9.12.3 [dcl.attr.assume] paragraph 1 as follows:

    ... If the converted expression would evaluate to true at the point where the assumption appears, the assumption has no effect. Otherwise, the behavior is undefined evaluation of the assumption has runtime-undefined behavior.
  6. Change in 9.12.11 [dcl.attr.noreturn] paragraph 2 as follows:

    If a function f is called invoked where f was previously declared with the noreturn attribute and f that invocation eventually returns, the behavior is runtime-undefined.