Title
constinit and optimized dynamic initialization
Status
c++23
Section
9.2.7 [dcl.constinit]
Submitter
Zhihao Yuan

Created on 2022-03-01.00:00:00 last changed 9 months ago

Messages

Date: 2023-02-07.05:42:41

Proposed resolution (approved by CWG 2023-02-06):

Change in 9.2.7 [dcl.constinit] paragraph 2 as follows:

If a variable declared with the constinit specifier has dynamic initialization (6.9.3.3 [basic.start.dynamic]), the program is ill-formed, even if the implementation would perform that initialization as a static initialization (6.9.3.2 [basic.start.static]). [Note 1: The constinit specifier ensures that the variable is initialized during static initialization (6.9.3.2 [basic.start.static]). —end note]
Date: 2022-11-15.00:00:00

Notes from the November, 2022 meeting

CWG seeks the advice of EWG how to proceed with this issue, via cplusplus/papers#1379.

EWG 2023-01-19

EWG resolved to desire portable, guaranteed semantics for constinit. That means, constinit should produce a diagnostic if de-jure dynamic initialization is turned into de-facto static initialization as permitted by 6.9.3.2 [basic.start.static] paragraph 3.

Date: 2023-02-15.00:00:00

[Accepted as a DR at the February, 2023 meeting.]

Subclause 9.2.7 [dcl.constinit] paragraph 2 states:

If a variable declared with the constinit specifier has dynamic initialization (6.9.3.3 [basic.start.dynamic]), the program is ill-formed. [ Note: The constinit specifier ensures that the variable is initialized during static initialization (6.9.3.2 [basic.start.static]). —end note]

Subclause 6.9.3.2 [basic.start.static] paragraph 3 gives permission for an implementation to perform static initialization in lieu of dynamic initialization:

An implementation is permitted to perform the initialization of a variable with static or thread storage duration as a static initialization even if such initialization is not required to be done statically, provided that ...

constinit will assuredly not give a diagnostic for variables that are constant initialized (7.7 [expr.const] paragraph 2), because those are required to be statically initialized and thus will never be dynamically initialized. Conversely, constinit is guaranteed to give a diagnostic for variables that cannot be statically initialized, for example those with an initializer whose value depends on runtime conditions.

Between those boundaries, it is unclear whether constinit ought to give a diagnostic for variables whose initializer does not satisfy the constraints of constant-initialized, yet the implementation takes advantage of the permission to turn dynamic initialization into static initialization. For example,

  float f;
  constinit int * pi = (int*) &f;    // reinterpret_cast, not constant-initialized

The current wording seems to imply that constinit accurately reflects whether dynamic initialization was turned into static initialization by the implementation. However, that is impossible to implement, because such decisions are often made by the optimizer, which runs later than the compiler front-end interpreting the program text containing constinit.

There is value in permitting constinit not to diagnose some of the dynamic initializations that are turned into static initializations.

There is also value in having portable semantics of constinit.

See also issue 2536.

History
Date User Action Args
2023-07-16 13:00:43adminsetstatus: open -> c++23
2023-07-16 13:00:43adminsetstatus: dr -> open
2023-02-18 18:43:04adminsetstatus: ready -> dr
2023-02-10 23:01:52adminsetstatus: tentatively ready -> ready
2023-02-07 05:42:41adminsetmessages: + msg7162
2023-02-07 05:42:41adminsetstatus: review -> tentatively ready
2023-01-19 18:50:45adminsetstatus: open -> review
2022-12-01 21:34:09adminsetmessages: + msg7072
2022-12-01 21:34:09adminsetstatus: drafting -> open
2022-11-20 07:54:16adminsetstatus: open -> drafting
2022-03-01 00:00:00admincreate