C26426 NO_GLOBAL_INIT_CALLS

"Global initializer calls a non-constexpr function."

C++ Core Guidelines: I.22: Avoid complex initialization of global objects

The order of execution of initializers for global objects may be inconsistent or undefined. This can lead to issues that are hard to reproduce and investigate. To avoid such problems, global initializers should not depend on external code that's executed at run time and can potentially depend on data that's not yet initialized. This rule flags cases where global objects call functions to obtain their initial values.

Remarks

  • The rule ignores calls to constexpr functions or intrinsic functions on assumption that these either will be calculated at compile time or guarantee predictable execution at run time.
  • Calls to inline functions are still flagged since the checker doesn’t attempt to analyze their implementation.
  • This rule can be noisy in many common scenarios where a variable of a user-defined type (or standard container) is initialized globally: this is often due to calls to constructors and destructors. This is still a valid warning since it points to places where unpredictable behavior may exist or future changes in external code may introduce instability.
  • Static class members are considered global, so their initializers are also checked.

Example

external version check

// api.cpp
int api_version = API_DEFAULT_VERSION; // Assume it can change at run time, hence non-const.
int get_api_version() noexcept {
    return api_version;
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode = get_api_version() <= API_LEGACY_VERSION; // C26426, also stale value

Example

external version check – made more reliable

// api.cpp
int& api_version() noexcept {
    static auto value = API_DEFAULT_VERSION;
    return value;
}
int get_api_version() noexcept {
    return api_version();
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode() noexcept {
    return get_api_version() <= API_LEGACY_VERSION;
}