https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171
mark <markrubn at yahoo dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |markrubn at yahoo dot com --- Comment #18 from mark <markrubn at yahoo dot com> --- I'd also like to request a GCC extension to allow reinterpret_cast in a constexpr. Following are a question, a comment, and a use-case illustrating why the extension is needed. Question: I understand that using reinterpret_cast in a constexpr is disallowed by the C++ standard. *Why* is it disallowed? The only reason I've seen stated is that "reinterpret_cast may require runtime (hardware) support". That seems plausible, but a constexpr static_cast from int to double, which requires a far deeper understanding of the target architecture, is supported. I understand that int-to-pointer conversion may involve widening, narrowing, or even more complex and possibly inexpressible semantics (segmented/non-linear memory architectures), but reinterpret_cast by definition is non-portable and error prone. Its "use these bits as they are" semantics, with possible truncation or zero-padding, seems to allow it to be used unambiguously in most normal cases. Comment: GCC has never been "shy" about adding extensions. Some of them, like __attribute__((fallthrough) becoming [[fallthrough]], have even eventually made it into the standards. Use-case: It is common practice in embedded microcontrollers to access hardware resources via reads and writes to specific, fixed memory addresses. I believe this is generally understood but can provide much more detail if requested. In addition, microcontrollers are usually very limited in terms of memory and CPU speed. By using constexpr constructors, extern/static objects are compiled pre-initialized in the .data segment, eliminating the memory needed for pre-main() constructor code and the time to execute it. In GCC 4.8.3, prior to the changes to make GCC standards-compliant as described in this bug report, the following code would compile the object into .data segment: ``` class C { public: constexpr C( unsigned* const u) : _u(u) {} void set() const { *_u = 0x87654321; } protected: unsigned* const _u; }; unsigned* const addr = reinterpret_cast<unsigned*>(0x40000000); C c(addr); int main() { c.set(); } ``` Later versions compile the object into .bss, and also include C::C constructor code. Attempts to force constexpr construction by changing the above to: ``` constexpr unsigned* const addr = reinterpret_cast<unsigned*>(0x40000000); ``` causes no change with 4.8.3 but results in a fatal "error: value ‘1073741824’ of type ‘unsigned int*’ is not a constant expression" in later versions. The only workaround I know is to introduce an extra conversion method, which will then again compile the object into .data with no runtime construction required: ``` class Addr { public: constexpr Addr( unsigned const u_addr) : _u_addr(u_addr) {} void set() const { *_u() = 0x87654321; } protected: volatile unsigned* _u() const { return reinterpret_cast<unsigned*>(_u_addr);} unsigned const _u_addr; }; Addr addr(0x40000000); int main() { addr.set(); } ``` And of course none of this is needed when coding in C instead of C++. The following struct is placed in .data without any workarounds being required: ``` struct Addr { unsigned* const u; }; void set( struct Addr *a) { *(a->u) = 0x87654321; } struct Addr addr = { (unsigned*)0x40000000 }; int main() { set(&addr); } ``` I firmly believe that C++ offers important improvements over C, with few if any disadvantages. Many in the embedded programming community feel otherwise ("C++ is obfuscated") and in this example the objection is valid. Any comments, corrections, or responses -- much less a change so that -fpermissive allows the reinterpret_cast -- would be welcome. Thank you.