https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89481
Bug ID: 89481 Summary: constexpr function allows writing one active union member and reading another Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: mickey.veksler at gmail dot com Target Milestone: --- The following code should not compile, not when passed as a template argument to std::intergral_constant<bool, all_zeros()> : constexpr bool all_zeros() { union mix { double numeric; char bytes[sizeof(double)+1]; }; mix zero{-0.0}; // active is 'numeric' // setting a different active member(?): zero.bytes[sizeof(double)] = '\0'; for (unsigned i=0 ; i != sizeof(double) ; ++i) { // or this is illegal (since it was never initialized through 'bytes') if (zero.bytes[i]) return false; } return true; } The puzzling thing is that the following two give different results: int main() { // return all_zeros(); return std::integral_constant<bool, all_zeros()>::value; } Unlike gcc, clang-7.0.0 emits diagnostics: <source>:3:16: error: constexpr function never produces a constant expression [-Winvalid-constexpr] constexpr bool all_zeros() ^ <source>:10:32: note: assignment to member 'bytes' of union with active member 'numeric' is not allowed in a constant expression zero.bytes[sizeof(double)] = '\0'; ^