Since r233183, we ICE with: class S { bool b; char a[] = "foo"; S () {} }; $ ./cc1plus -quiet q.cc q.cc: In constructor ‘S::S()’: q.cc:4:8: internal compiler error: in finish_expr_stmt, at cp/semantics.c:677 S () {} ^ 0x9b904c finish_expr_stmt(tree_node*) /home/marek/src/gcc/gcc/cp/semantics.c:677 0x98ed5a perform_member_init /home/marek/src/gcc/gcc/cp/init.c:803 0x990727 emit_mem_initializers(tree_node*) /home/marek/src/gcc/gcc/cp/init.c:1179 0x9bc39a finish_mem_initializers(tree_node*) /home/marek/src/gcc/gcc/cp/semantics.c:1627 0x90c782 cp_parser_ctor_initializer_opt /home/marek/src/gcc/gcc/cp/parser.c:13491 0x919f06 cp_parser_ctor_initializer_opt_and_function_body /home/marek/src/gcc/gcc/cp/parser.c:20764 0x922f70 cp_parser_function_definition_after_declarator /home/marek/src/gcc/gcc/cp/parser.c:25475 0x92556b cp_parser_late_parsing_for_member /home/marek/src/gcc/gcc/cp/parser.c:26354 0x91bf8d cp_parser_class_specifier_1 /home/marek/src/gcc/gcc/cp/parser.c:21630 0x91c06a cp_parser_class_specifier /home/marek/src/gcc/gcc/cp/parser.c:21656 0x9108e2 cp_parser_type_specifier /home/marek/src/gcc/gcc/cp/parser.c:15883 0x90b753 cp_parser_decl_specifier_seq /home/marek/src/gcc/gcc/cp/parser.c:12802 0x90ac9e cp_parser_simple_declaration /home/marek/src/gcc/gcc/cp/parser.c:12336 0x90ac26 cp_parser_block_declaration /home/marek/src/gcc/gcc/cp/parser.c:12283 0x90a9a8 cp_parser_declaration /home/marek/src/gcc/gcc/cp/parser.c:12180 0x90a501 cp_parser_declaration_seq_opt /home/marek/src/gcc/gcc/cp/parser.c:12059 0x8fa316 cp_parser_translation_unit /home/marek/src/gcc/gcc/cp/parser.c:4350 0x948552 c_parse_file() /home/marek/src/gcc/gcc/cp/parser.c:37581 0xafbce0 c_common_parse_file() /home/marek/src/gcc/gcc/c-family/c-opts.c:1070 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.
GCC 5 rejects the code: q.cc:3:14: error: initializer-string for array of chars is too long [-fpermissive] char a[] = "foo"; ^ q.cc: In constructor ‘S::S()’: q.cc:4:8: error: initializer-string for array of chars is too long [-fpermissive] S () {} ^ GCC 6 and trunk ICE. But before r233183 this code compiled fine.
Confirmed.
(In reply to Marek Polacek from comment #1) > But before r233183 this code compiled fine. It didn't do what one would expect at runtime, though, and neither did a program that used the aggregate initialization (i.e., struct S { bool b; char a[]; } s = { 1, "foo" };) because it treated the flexible array member as a zero-length array. With the flexible array member improvements committed in 6.0, GCC accepts the latter, so it seems that the original test case should be accepted as well, as an extension. I.e., I suggest to treat this as ice-on-valid code. $ cat y.C && ~/bin/gcc-5.1.0/bin/g++ -fpermissive -std=c++11 y.C && ./a.out struct S { bool b; char a[] = "foo"; S () {} } s; int main () { if (__builtin_strcmp (s.a, "foo")) __builtin_abort (); } y.C:3:14: warning: initializer-string for array of chars is too long [-fpermissive] char a[] = "foo"; ^ y.C: In constructor ‘S::S()’: y.C:4:8: warning: initializer-string for array of chars is too long [-fpermissive] S () {} ^ Aborted (core dumped)
(In reply to Martin Sebor from comment #3) > (In reply to Marek Polacek from comment #1) > > But before r233183 this code compiled fine. > > It didn't do what one would expect at runtime, though, and neither did a > program that used the aggregate initialization (i.e., struct S { bool b; > char a[]; } s = { 1, "foo" };) because it treated the flexible array member > as a zero-length array. With the flexible array member improvements > committed in 6.0, GCC accepts the latter, so it seems that the original test > case should be accepted as well, as an extension. I.e., I suggest to treat > this as ice-on-valid code. But the initialization happens in the default constructor, whereas allocating space for the object happens before the constructor. I don't think we should try to support initialization of a flexible array member in a constructor.
Would it be possible to take the size of the in-class initialized flexible array member into account when computing the size of the object to allocate? That way the example in comment #0 could be accepted and handled correctly but one where the flexible array member were initialized in a ctor-initializer list could be rejected.
GCC 6.2 is being released, adjusting target milestone.
Just had the same internal compiler error on a different piece of code, using GCC 6.1.1 on Fedora 24. Might be useful to investigate the cause. #include <thread> void func(int i); int main(int argc, char* argv[]) { int val = 0; auto thread = std::thread([&, =val]() { func(val); }); } $ gcc main.cpp main.cpp: In lambda function: main.cpp:8:51: internal compiler error: in finish_expr_stmt, at cp/semantics.c:677 auto thread = std::thread([&, =val]() { func(val); }); ^
This patch seems to disable initialization of a flexible array member in a constructor, and, curiously, doesn't regress anything in C++ dg.exp. --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -800,6 +800,11 @@ perform_member_init (tree member, tree init) in that case. */ init = build_x_compound_expr_from_list (init, ELK_MEM_INIT, tf_warning_or_error); + else if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == NULL_TREE + && DECL_CONSTRUCTOR_P (current_function_decl)) + error_at (DECL_SOURCE_LOCATION (member), + "initialization of a flexible array member in a constructor"); if (init) finish_expr_stmt (cp_build_modify_expr (input_location, decl,
(In reply to Matteo Bertello from comment #10) > Just had the same internal compiler error on a different piece of code, > using GCC 6.1.1 on Fedora 24. > Might be useful to investigate the cause. This code doesn't compile for me at all: r3.cc: In function ‘int main(int, char**)’: r3.cc:8:27: error: expected primary-expression before ‘(’ token auto thread = std::thread([&, =val]() { func(val); }); ^ r3.cc:8:32: error: expected identifier before ‘=’ token auto thread = std::thread([&, =val]() { func(val); }); ^ clang++ rejects it, too.
Marek, why the DECL_CONSTRUCTOR_P check? Isn't it enough that we've reached that location to know one's in a constructor? (and if it isn't, why are the other locations permitted to init the array?)
I think you're right. I dropped the check and am regtesting this again. Thanks!
Author: mpolacek Date: Wed Dec 14 20:41:43 2016 New Revision: 243669 URL: https://gcc.gnu.org/viewcvs?rev=243669&root=gcc&view=rev Log: PR c++/72775 * init.c (perform_member_init): Diagnose member initializer for flexible array member. * g++.dg/ext/flexary12.C: Adjust dg-error. * g++.dg/ext/flexary20.C: New. * g++.dg/ext/flexary21.C: New. Added: trunk/gcc/testsuite/g++.dg/ext/flexary20.C trunk/gcc/testsuite/g++.dg/ext/flexary21.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/init.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/ext/flexary12.C
Fixed.
Reopening, as this is still a GCC 6 regression.
I'll backport this to 6 too, testing looks good.
Author: mpolacek Date: Wed Mar 15 10:22:19 2017 New Revision: 246155 URL: https://gcc.gnu.org/viewcvs?rev=246155&root=gcc&view=rev Log: PR c++/72775 * init.c (perform_member_init): Diagnose member initializer for flexible array member. * g++.dg/ext/flexary12.C: Adjust dg-error. * g++.dg/ext/flexary20.C: New. * g++.dg/ext/flexary21.C: New. Added: branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary20.C branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary21.C Modified: branches/gcc-6-branch/gcc/cp/ChangeLog branches/gcc-6-branch/gcc/cp/init.c branches/gcc-6-branch/gcc/testsuite/ChangeLog branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary12.C
Done.