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


2123. Omitted constant initialization of local static variables

Section: 8.8  [stmt.dcl]     Status: open     Submitter: Hubert Tong     Date: 2015-02-02

According to 8.8 [stmt.dcl] paragraph 4,

The zero-initialization (9.4 [dcl.init]) of all block-scope variables with static storage duration (6.7.5.2 [basic.stc.static]) or thread storage duration (6.7.5.3 [basic.stc.thread]) is performed before any other initialization takes place. Constant initialization (6.9.3.2 [basic.start.static]) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered.

The fact that a variable need not be constant-initialized if its block is not entered appears to allow inspection of the variable after zero-initialization but before constant initialization:

  constexpr int x = 0;

  auto foo() {
    constexpr static const int *p = &x;
    struct A {
      const int *const &getPtr() { return p; }
    } a;
    return a;
  }

  int xcpy = *decltype(foo()){ }.getPtr();

  int main(void) {
    return xcpy;
  }

For a related example, consider:

  // tu1.cpp
  extern const int a = 1;
  inline auto f() {
    static const int b = a;
    struct A { auto operator()() { return &b; } } a;
    return a;
  }

  // tu2.cpp
  extern const int a;
  inline auto f() {
    static const int b = a;
    struct A { auto operator()() { return &b; } } a;
    return a;
  }
  int main() {
    return *decltype(f())()();
  }

Here, b may or may not have constant initialization, but we don't have an ODR violation.

If we want to support such code, the nicest option would be to say that the ODR requires us to act as if we pick one of the definitions of the inline function, which requires us to make a consistent choice for all static storage duration variables within a given function. Alternatively, we could say that if multiple definitions of a variable disagree over whether it has constant initialization, then it does not, allowing more implementation simplicity and no functional change outside of pathological cases.

Notes from the February, 2016 meeting:

The second example will be dealt with separately under issue 2242. For the first example, the Standard should require that local types can be used outside their function only via a returned object. It was still to be decided whether this should be undefined behavior or an error on use of such a type. It was also noted that the same issue can arise with static member functions.