Bug 72775 - [6 Regression] internal compiler error: in finish_expr_stmt, at cp/semantics.c:677
Summary: [6 Regression] internal compiler error: in finish_expr_stmt, at cp/semantics....
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0
: P2 normal
Target Milestone: 6.3
Assignee: Marek Polacek
URL:
Keywords: ice-on-invalid-code
Depends on:
Blocks:
 
Reported: 2016-08-02 13:26 UTC by Marek Polacek
Modified: 2018-02-28 07:10 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-08-02 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2016-08-02 13:26:47 UTC
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.
Comment 1 Marek Polacek 2016-08-02 13:29:36 UTC
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.
Comment 2 Martin Liška 2016-08-02 19:37:44 UTC
Confirmed.
Comment 3 Martin Sebor 2016-08-04 15:13:06 UTC
(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)
Comment 4 Jason Merrill 2016-08-15 17:25:47 UTC
(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.
Comment 5 Martin Sebor 2016-08-17 17:39:55 UTC
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.
Comment 6 Richard Biener 2016-08-22 08:23:56 UTC
GCC 6.2 is being released, adjusting target milestone.
Comment 7 Richard Biener 2016-08-22 08:25:11 UTC
GCC 6.2 is being released, adjusting target milestone.
Comment 8 Richard Biener 2016-08-22 08:45:06 UTC
GCC 6.2 is being released, adjusting target milestone.
Comment 9 Richard Biener 2016-08-22 08:46:35 UTC
GCC 6.2 is being released, adjusting target milestone.
Comment 10 Matteo Bertello 2016-08-23 16:08:25 UTC
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); });
                                                   ^
Comment 11 Marek Polacek 2016-12-07 14:10:21 UTC
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,
Comment 12 Marek Polacek 2016-12-07 14:11:30 UTC
(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.
Comment 13 Nathan Sidwell 2016-12-07 18:38:43 UTC
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?)
Comment 14 Marek Polacek 2016-12-07 18:57:04 UTC
I think you're right.  I dropped the check and am regtesting this again.  Thanks!
Comment 15 Marek Polacek 2016-12-14 20:42:15 UTC
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
Comment 16 Marek Polacek 2016-12-14 20:43:27 UTC
Fixed.
Comment 17 Jason Merrill 2017-02-03 22:45:50 UTC
Reopening, as this is still a GCC 6 regression.
Comment 18 Marek Polacek 2017-03-15 09:48:03 UTC
I'll backport this to 6 too, testing looks good.
Comment 19 Marek Polacek 2017-03-15 10:22:52 UTC
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
Comment 20 Marek Polacek 2017-03-15 10:23:14 UTC
Done.