Modifying a global variable in a constexpr function in C++17

  • A+

In C++17, are you allowed to modify global variables in a constexpr function?

#include <iostream>  int global = 0;  constexpr int Foo(bool arg) {     if (arg) {         return 1;     }     return global++; }  int main() {     std::cout << global;     Foo(true);     std::cout << global;     Foo(false);     std::cout << global; } 

I wouldn't expect you to be able to, but clang 6 allows it:

GCC, however, doesn't:

Which compiler is correct?


Which compiler is correct?

Clang is right.

The definition of a constexpr function as per dcl.constexpr/3

The definition of a constexpr function shall satisfy the following requirements:

(3.1) its return type shall be a literal type;
(3.2) each of its parameter types shall be a literal type;
(3.3) its function-body shall be = delete, = default, or a compound-statement that does not contain:

(3.3.1) an asm-definition,
(3.3.2) a goto statement,
(3.3.3) an identifier label,
(3.3.4) a try-block, or
(3.3.5) a definition of a variable of non-literal type or of static or thread storage duration or for which no initialization is performed.

Also as per dcl.constexpr/5:

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression,

Foo(true) could be evaluated to a core constant expression (i.e 1).

Also, Foo(false) could be but is not required to be constant evaluated.


Thus, a bug in GCC.

Many thanks to @Barry, @aschepler and @BenVoigt for helping me with this answer.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: