c++cgccreinterpret-caststatic-assert

GCC: _Static_assert "non-constant condition for static assertion"


I have larger C code base, where I want to integrate some C++ code. The C++ code needs some declarations from the C code base.

Compiler is currently GCC 6.3.1, but we might be able to update the compiler.

Basically, the included C headers contain code like this:

#define NRF_GPIO  ((int*)          0x0000112233)
static_assert(NRF_GPIO == NRF_GPIO, "asd");

This compiles fine, if the compiler compiles C files, but fails, if the code is written in C++, as the reinterpret cast will not yield in a constant expression and the compiler correctly complains about it:

error: non-constant condition for static assertion
 static_assert(NRF_GPIO == NRF_GPIO, "asd");
                        ^
t.cpp:2:20: error: reinterpret_cast from integer to pointer
 #define NRF_GPIO  ((int*)          0x0000112233)
                   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.cpp:3:15: note: in expansion of macro 'NRF_GPIO'
 static_assert(NRF_GPIO == NRF_GPIO, "asd");

Is there a way to let the GCC compile the C++ a little bit more relaxed and thus to except the code above?


Solution

  • It is not guaranteed to work in C either. In C the static assertion requires an integer constant expression, which may contain casts to non-integer types only as part of sizeof or _Alignof operands.

    C does permit an implementation to allow other forms of constant expressions, but at least with the current C23 working draft it has been clarified that this does not affect the validity as integer constant expression. See N2713.

    GCC also warns about that with -pedantic.

    You generally can't invent out-of-thin-air pointer values and use them at compile time in C++ (except for null pointer values). C allows slightly more, but not in contexts requiring integer constant expressions. See below.

    The only way to work with this is to keep the address as a numeric value at compile-time and convert it to a pointer only at runtime when it is needed as such.

    There is one exception in C, but not C++: An integer constant can be cast to a pointer and be used as an address constant to constant-initialize a variable. However even then the address constant cannot be an operand to == (or most other operators) in the initializer expression, nor is it allowed in an integer constant expression.