diff mbox

C++ PATCH to reject initializating flexible array members in constructors (PR c++/72775)

Message ID 20161207202622.GJ2337@redhat.com
State New
Headers show

Commit Message

Marek Polacek Dec. 7, 2016, 8:26 p.m. UTC
We were crashing in finish_expr_stmt here:
 676       /* If we ran into a problem, make sure we complained.  */
 677       gcc_assert (expr != error_mark_node || seen_error ());
Well, we ran into a problem, but never raised an error.  The problem was that
we couldn't determine the max index of the array when default-initizalizing the
members (at the beginning of cp_parser_ctor_initializer_opt).  Jason's
preference seems to be to disable initialization of a flexible array member in
a constructor and that is what this patch attempts to do.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2016-12-07  Marek Polacek  <polacek@redhat.com>

	PR c++/72775
	* init.c (perform_member_init): Diagnose initialization of a flexible
	array member in a constructor.

	* g++.dg/ext/flexary20.C: New.


	Marek

Comments

Jason Merrill Dec. 8, 2016, 6:05 p.m. UTC | #1
If the problem is the member initializer, we can diagnose that
directly rather than wait until we're in a constructor.

On Wed, Dec 7, 2016 at 3:26 PM, Marek Polacek <polacek@redhat.com> wrote:
> We were crashing in finish_expr_stmt here:
>  676       /* If we ran into a problem, make sure we complained.  */
>  677       gcc_assert (expr != error_mark_node || seen_error ());
> Well, we ran into a problem, but never raised an error.  The problem was that
> we couldn't determine the max index of the array when default-initizalizing the
> members (at the beginning of cp_parser_ctor_initializer_opt).  Jason's
> preference seems to be to disable initialization of a flexible array member in
> a constructor and that is what this patch attempts to do.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2016-12-07  Marek Polacek  <polacek@redhat.com>
>
>         PR c++/72775
>         * init.c (perform_member_init): Diagnose initialization of a flexible
>         array member in a constructor.
>
>         * g++.dg/ext/flexary20.C: New.
>
> diff --git gcc/cp/init.c gcc/cp/init.c
> index b4b6cdb..01009c9 100644
> --- gcc/cp/init.c
> +++ gcc/cp/init.c
> @@ -800,6 +800,10 @@ 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)
> +       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,
> diff --git gcc/testsuite/g++.dg/ext/flexary20.C gcc/testsuite/g++.dg/ext/flexary20.C
> index e69de29..ff97b06 100644
> --- gcc/testsuite/g++.dg/ext/flexary20.C
> +++ gcc/testsuite/g++.dg/ext/flexary20.C
> @@ -0,0 +1,49 @@
> +// PR c++/72775
> +// { dg-do compile { target c++11 } }
> +// { dg-options -Wno-pedantic }
> +
> +struct S {
> +  int i;
> +  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
> +  S () {}
> +};
> +
> +struct T {
> +  int i;
> +  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
> +};
> +
> +struct U {
> +  int i;
> +  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
> +  U ();
> +};
> +
> +U::U() {}
> +
> +int
> +main ()
> +{
> +  struct T t;
> +}
> +
> +struct V {
> +  int i;
> +  struct W {
> +    int j;
> +    char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
> +  } w;
> +  V () {}
> +};
> +
> +template <class T>
> +struct X {
> +  int i;
> +  T a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
> +};
> +
> +void
> +fn ()
> +{
> +  struct X<char> x;
> +}
>
>         Marek
Nathan Sidwell Dec. 8, 2016, 7:56 p.m. UTC | #2
On 12/08/2016 01:05 PM, Jason Merrill wrote:
> If the problem is the member initializer, we can diagnose that
> directly rather than wait until we're in a constructor.

What about:
struct Foo {
int a;
char ary[];
Foo () : ary ("bob"){}
};

?  That ICEs in the same way.

nathan
diff mbox

Patch

diff --git gcc/cp/init.c gcc/cp/init.c
index b4b6cdb..01009c9 100644
--- gcc/cp/init.c
+++ gcc/cp/init.c
@@ -800,6 +800,10 @@  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)
+	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,
diff --git gcc/testsuite/g++.dg/ext/flexary20.C gcc/testsuite/g++.dg/ext/flexary20.C
index e69de29..ff97b06 100644
--- gcc/testsuite/g++.dg/ext/flexary20.C
+++ gcc/testsuite/g++.dg/ext/flexary20.C
@@ -0,0 +1,49 @@ 
+// PR c++/72775
+// { dg-do compile { target c++11 } }
+// { dg-options -Wno-pedantic }
+
+struct S {
+  int i;
+  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
+  S () {}
+};
+
+struct T {
+  int i;
+  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
+};
+
+struct U {
+  int i;
+  char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
+  U ();
+};
+
+U::U() {}
+
+int
+main ()
+{
+  struct T t;
+}
+
+struct V {
+  int i;
+  struct W {
+    int j;
+    char a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
+  } w;
+  V () {}
+};
+
+template <class T>
+struct X {
+  int i;
+  T a[] = "foo"; // { dg-error "initialization of a flexible array member in a constructor" }
+};
+
+void
+fn ()
+{
+  struct X<char> x;
+}