cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[expr.const] p20 constant evaluation is not specified what requirement should be obeyed #370

Open xmh0511 opened 1 year ago

xmh0511 commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[expr.const] p20 says:

A function or variable is needed for constant evaluation if it is:

  • [...]

So, what requirements do we want to impose on these constructs?

Suggested Resolution

We may want to say:

The constant evaluation requires the full-expression within it to be a constant expression.

However, it is not clear what "is needed for constant evaluation" intend to mean. Consider this example:

constexpr int fun(int c){
    return c
}
int main(){
   int a = 0;
   int b = fun(a+1);
}

[expr.const] p20.2 says fun(a+1) is potentially constant evaluated, and [expr.const] p20.6 says it is needed for constant evaluation because fun is a constexpr function. However, the expression is not required to be constant expression.

frederick-vs-ja commented 1 year ago

I think the intent is specifying when are certain defaulted functions, function template specializations, and variable template specializations instantiated in unevaluated operands (see P0859R0).

There should be no requirements in addition to those for instantiation, or implicit definition for defaulted functions.

xmh0511 commented 1 year ago

So, where's the rule in the document that specifies the following code is ill-formed?

consteval int bar (int x) { return x; }
int i = 5;
bar (i);  // ill-formed

After all, the following sentence in n4861 expr.const p13 standard is removed now:

An immediate invocation shall be a constant expression.

jensmaurer commented 1 year ago

Note the italics. This is (simply) a definition of "needed for constant evaluation" for later use by [dcl.fct.def.default] and [temp.inst]. That definition has no local purpose in [expr.const].

jensmaurer commented 1 year ago

Regarding the example, we have

"An invocation is an immediate invocation if it is a potentially-evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context"

So, bar(i) is an immediate invocation. Thus, this function call expression is manifestly constant evaluated (p19.3).

Hm... But we seem to say nowhere that manifestly constant evaluated expressions need to be constant expressions.

xmh0511 commented 1 year ago

Hm... But we seem to say nowhere that manifestly constant evaluated expressions need to be constant expressions.

I cited the intended rule that could cover this issue in https://github.com/cplusplus/CWG/issues/371, however, as specified in that issue, the rule has some issues too.

frederick-vs-ja commented 1 year ago

After all, the following sentence in n4861 expr.const p13 standard is removed now:

An immediate invocation shall be a constant expression.

I think the requirement is moved to [expr.const] p17:

An immediate-escalating expression shall appear only in an immediate-escalating function.

frederick-vs-ja commented 1 year ago

Hm... But we seem to say nowhere that manifestly constant evaluated expressions need to be constant expressions.

I guess we've almost already separately specified when they need to be constant expressions.

  1. All occurrences of constant-expression are required to be constant expressions in certain forms.
  2. The condition of a constexpr if statement is same as above,
  3. An immediate invocation is not always required to be a constant expression. However, when it is not a constant expression (or a subexpression of another immediate invocation), it is additionally required to satisfy the additional requirements for an immediate-escalating expression.
  4. The result of substitution into an atomic constraint expression to determine whether it is satisfied is currently problematic (CWG2739).
  5. The initializer of a variable that is usable in constant expressions or has constant initialization, is already constant expression by definition. The related contexts (except for initializers of constexpr variables) accept both constant and non-constant initializers. For initializers of constant variables, we've already required the initialization and destruction to be constant expressions.
xmh0511 commented 1 year ago

After all, the following sentence in n4861 expr.const p13 standard is removed now:

An immediate invocation shall be a constant expression.

I think the requirement is moved to [expr.const] p17:

An immediate-escalating expression shall appear only in an immediate-escalating function.

see https://github.com/cplusplus/CWG/issues/371