This error appears to be caused though the static_assert on a constexpr containing a union. prog.cpp: In function ‘int main()’: prog.cpp:29:48: in constexpr expansion of ‘BitsOrderCheck().BitsOrderCheck::IsLsbBottom()’ prog.cpp:29:58: internal compiler error: in cxx_eval_bit_field_ref, at cp/semantics.c:6977 Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions. Preprocessed source stored into /home/nUBliJ/ccd38zvW.out file, please attach this to your bugreport. #include <stdint.h> #include <iostream> struct BitsOrderCheck { union Data { struct Bitfield { const unsigned char clear:7; const unsigned char set:1; }; const unsigned char byte; const Bitfield bits; constexpr Data() : byte(1) {} }; constexpr BitsOrderCheck() {} constexpr bool IsLsbBottom() const { return 1 == data_.bits.set; } const Data data_; }; int main() { static_assert(BitsOrderCheck().IsLsbBottom(), "blah"); std::cout << "LSB: " << BitsOrderCheck().IsLsbBottom() << std::endl; return 0; }
Note: all the other compilers I have at hand reject the snippet with an error message about the static_assert expression not being constant (which behavior, in case the analysis shows it's correct, would be easy to obtain with GCC too)
(In reply to Paolo Carlini from comment #1) I agree that the code should be rejected, because the created BitsOrderCheck object initializes the member 'byte' of the union and later attempts to read the member 'bits', thus causing the exclusion case of core constant expressions: "an lvalue-to-rvalue conversion (4.1) or modification (5.17, 5.2.6, 5.3.2) that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;"
... but we ICE with the testcase adjusted too.
The code in cxx_eval_bit_field_ref needs some work, doesn't handle CONSTRUCTORs inside CONSTRUCTORs. This is a reduced testcase: struct BitsOrderCheck { struct Data { const unsigned char set:1; constexpr Data() : set{1} {} }; constexpr bool IsLsbBottom() const { return 1 == data_.set; } const Data data_; }; static_assert(BitsOrderCheck().IsLsbBottom(), "blah");
Kai's delayed folding work ought to fix this by avoiding creating BIT_FIELD_REFs so soon.
Yes, delayed folding fixes wrong-code/valid-code samples. For invalid-code I see with delayed folding the following error-messages: t_pr57335.C: In function 'int main()': t_pr57335.C:29:5: error: non-constant condition for static assertion static_assert(BitsOrderCheck().IsLsbBottom(), "blah"); ^ t_pr57335.C:29:47: in constexpr expansion of 'BitsOrderCheck().BitsOrderCheck::IsLsbBottom()' t_pr57335.C:29:5: error: accessing 'BitsOrderCheck::Data::bits' member instead of initialized 'BitsOrderCheck::Data::byte' member in constant expression Not sure if this is desired.
(In reply to Kai Tietz from comment #6) > t_pr57335.C:29:5: error: accessing 'BitsOrderCheck::Data::bits' member > instead of initialized 'BitsOrderCheck::Data::byte' member in constant > expression Yes, that's the desired behavior for this testcase.
Good. What about the snippet in Comment #4, though? That one seems Ok to me and meaning that cxx_eval_bit_field_ref needs some work.
Yes, that works without any warnings with delayed-folding patch. (I mentioned it in comment #6 as *valid-code* sample)
Ah, excellent.
Mine.
Surprisingly, no progress on this!? Any quick idea? Otherwise, I'm going to look into it a bit (again)...
Reconfirming as still failing with today's top of trunk (6.0), plus 5.x and 4.9.3. I get the following stack trace on the small test case from comment #4: z.c:18:43: in constexpr expansion of ‘BitsOrderCheck().BitsOrderCheck::IsLsbBottom()’ z.c:18:54: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2095 static_assert(BitsOrderCheck().IsLsbBottom(), "blah"); ^ 0xa49fd0 cxx_eval_bit_field_ref /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:2095 0xa4fe83 cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3657 0xa48278 cxx_eval_binary_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:1617 0xa4fcde cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3614 0xa48278 cxx_eval_binary_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:1617 0xa4fcde cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3614 0xa4d68e cxx_eval_store_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:2938 0xa4f5bb cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3441 0xa4f6b0 cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3454 0xa477b2 cxx_eval_call_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:1393 0xa4ee03 cxx_eval_constant_expression /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3364 0xa50f6f cxx_eval_outermost_constant_expr /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:3929 0xa51970 maybe_constant_value_1 /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:4117 0xa51a6d maybe_constant_value(tree_node*, tree_node*) /home/msebor/scm/fsf/gcc-svn/gcc/cp/constexpr.c:4138 0x9ba7a2 finish_static_assert(tree_node*, tree_node*, unsigned int, bool) /home/msebor/scm/fsf/gcc-svn/gcc/cp/semantics.c:8673 0x8ec892 cp_parser_static_assert /home/msebor/scm/fsf/gcc-svn/gcc/cp/parser.c:13034 0x8eb80b cp_parser_block_declaration /home/msebor/scm/fsf/gcc-svn/gcc/cp/parser.c:12228 0x8eb5ad cp_parser_declaration /home/msebor/scm/fsf/gcc-svn/gcc/cp/parser.c:12129 0x8eb0ff cp_parser_declaration_seq_opt /home/msebor/scm/fsf/gcc-svn/gcc/cp/parser.c:12008 0x8db2aa cp_parser_translation_unit /home/msebor/scm/fsf/gcc-svn/gcc/cp/parser.c:4321 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions.
With 6.1, this doesn't only fail for static_assert. Even a simple function call fails: struct Bits { unsigned char a : 7; unsigned char b : 1; constexpr Bits() : a(0), b(0) {} }; struct Foo { constexpr Foo(int) { } constexpr bool b() const { return bits.b; } private: Bits bits; }; void func(bool) {} void foo() { constexpr Foo foo(42); func(foo.b()); } ../test/foo.cpp: In function ‘void foo()’: ../test/foo.cpp:21:14: in constexpr expansion of ‘foo.Foo::b()’ ../test/foo.cpp:21:16: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2226 func(foo.b()); ^ 0x6fbb43 cxx_eval_bit_field_ref ../../src/gcc/cp/constexpr.c:2226 0x6fbb43 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3849 0x6fed08 cxx_eval_binary_expression ../../src/gcc/cp/constexpr.c:1725 0x6f9c52 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3806 0x6fed08 cxx_eval_binary_expression ../../src/gcc/cp/constexpr.c:1725 0x6f9c52 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3806 0x6fc651 cxx_eval_store_expression ../../src/gcc/cp/constexpr.c:3123 0x6fa39c cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3633 0x6f9f88 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3645 0x6f92d2 cxx_eval_call_expression ../../src/gcc/cp/constexpr.c:1494 0x6fab6f cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3556 0x6f9f08 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3901 0x6fd1f6 cxx_eval_outermost_constant_expr ../../src/gcc/cp/constexpr.c:4121 0x6feabc maybe_constant_value_1 ../../src/gcc/cp/constexpr.c:4316 0x6feabc maybe_constant_value(tree_node*, tree_node*) ../../src/gcc/cp/constexpr.c:4340 0x5d6b11 build_over_call ../../src/gcc/cp/call.c:7561 0x5d879f build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, int) ../../src/gcc/cp/call.c:4152 0x6acaca finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int) ../../src/gcc/cp/semantics.c:2461 0x65eaf2 cp_parser_postfix_expression ../../src/gcc/cp/parser.c:6904 0x65cee2 cp_parser_unary_expression ../../src/gcc/cp/parser.c:7988
This was fixed in GCC 6.4.0, possibly by the fix for PR79681. *** This bug has been marked as a duplicate of bug 79681 ***