Home > database >  Can one volatile constexpr variable initialize another one in C ?
Can one volatile constexpr variable initialize another one in C ?

Time:11-21

C standard allows constexpr volatile variables per defect report 1688, which was resolved in September 2013:

The combination is intentionally permitted and could be used in some circumstances to force constant initialization.

It looks though that the intention was to allow only constinit volatile, which was not available before C 20.

Still the current compilers diverge in treatment of constexpr volatile in certain circumstances. For example, this program initializes one such variable by the other one:

int main() {
    constexpr volatile int i = 0;
    constexpr volatile int j = i;
    return j;
}

It is accepted in GCC and MSVC, but Clang complains:

error: constexpr variable 'j' must be initialized by a constant expression
    constexpr volatile int j = i;
                           ^   ~
note: read of volatile-qualified type 'const volatile int' is not allowed in a constant expression
    constexpr volatile int j = i;

Online demo: https://gcc.godbolt.org/z/43ee65Peq

Which compiler is right here and why?

CodePudding user response:

The defect report you linked shows it should not work, so Clang is correct.

(...) “a non-volatile object defined with constexpr” (...) is permitted but that such a variable cannot appear in a constant expression. What is the intent?

But more interesting is: why Clang cares while other compilers not?

In my opinion, this happened because of JF Bastien, a very influential figure in the world of Clang / LLVM, that personally dislikes volatile :)

He is proposing to remove it from a language for a long time. So if it was allowed to ban volatile somewhere, he probably spared no effort to make it so. If for no other reason, then simply to prevent people from writing code that will have to be rewritten if his proposal is eventually accepted.

He also made a presentation on CppCon about his this depreciation proposal, if you want tho know his reasoning.

CodePudding user response:

Clang is correct. The initialization of j from i requires that an lvalue-to-rvalue conversion be performed on i, but according to [expr.const]/5.9, an lvalue-to-rvalue conversion on a volatile glvalue is never permitted inside a constant expression. Since i is a constexpr variable, it must be initialized by a constant expression.

I have no idea why GCC and MSVC choose not to enforce this rule, other than that all C compilers are perpetually short-staffed and can't implement everything they're expected to.

  • Related