diff mbox series

C++ PATCH for c++/84578, ICE when initializing flexarr

Message ID 20180302173644.GK16833@redhat.com
State New
Headers show
Series C++ PATCH for c++/84578, ICE when initializing flexarr | expand

Commit Message

Marek Polacek March 2, 2018, 5:36 p.m. UTC
We ICE in cxx_eval_vec_init_1 whereby we try to initialize a flexible array
member, because the code computing the number of elements of ATYPE wasn't
prepared to handle arrays with no bounds.  Fixed by using
get_array_or_vector_nelts, broken out of existing code.

Martin suggested to reject this code, but I decided to leave this as-is for
now; we already reject code that actually tries to initialize the flexible
array member with some data, e.g.:

struct A {
  constexpr A() : i(), x("foo") {}
  int i;
  char x[];
};
A a;

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

2018-03-02  Marek Polacek  <polacek@redhat.com>

	PR c++/84578
	* constexpr.c (get_array_or_vector_nelts): New.
	(cxx_eval_array_reference): Use it.
	(cxx_eval_vec_init_1): Likewise.
	(cxx_eval_store_expression): Likewise.

	* g++.dg/ext/flexary29.C: New test.


	Marek

Comments

Jason Merrill March 2, 2018, 8:22 p.m. UTC | #1
OK.

On Fri, Mar 2, 2018 at 12:36 PM, Marek Polacek <polacek@redhat.com> wrote:
> We ICE in cxx_eval_vec_init_1 whereby we try to initialize a flexible array
> member, because the code computing the number of elements of ATYPE wasn't
> prepared to handle arrays with no bounds.  Fixed by using
> get_array_or_vector_nelts, broken out of existing code.
>
> Martin suggested to reject this code, but I decided to leave this as-is for
> now; we already reject code that actually tries to initialize the flexible
> array member with some data, e.g.:
>
> struct A {
>   constexpr A() : i(), x("foo") {}
>   int i;
>   char x[];
> };
> A a;
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2018-03-02  Marek Polacek  <polacek@redhat.com>
>
>         PR c++/84578
>         * constexpr.c (get_array_or_vector_nelts): New.
>         (cxx_eval_array_reference): Use it.
>         (cxx_eval_vec_init_1): Likewise.
>         (cxx_eval_store_expression): Likewise.
>
>         * g++.dg/ext/flexary29.C: New test.
>
> diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
> index 39e6cdfb33d..27f841db38f 100644
> --- gcc/cp/constexpr.c
> +++ gcc/cp/constexpr.c
> @@ -2300,6 +2300,32 @@ diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
>      }
>  }
>
> +/* Return the number of elements for TYPE (which is an ARRAY_TYPE or
> +   a VECTOR_TYPE).  */
> +
> +static tree
> +get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
> +                          bool *non_constant_p, bool *overflow_p)
> +{
> +  tree nelts;
> +  if (TREE_CODE (type) == ARRAY_TYPE)
> +    {
> +      if (TYPE_DOMAIN (type))
> +       nelts = array_type_nelts_top (type);
> +      else
> +       nelts = size_zero_node;
> +    }
> +  else if (VECTOR_TYPE_P (type))
> +    nelts = size_int (TYPE_VECTOR_SUBPARTS (type));
> +  else
> +    gcc_unreachable ();
> +
> +  /* For VLAs, the number of elements won't be an integer constant.  */
> +  nelts = cxx_eval_constant_expression (ctx, nelts, false,
> +                                       non_constant_p, overflow_p);
> +  return nelts;
> +}
> +
>  /* Extract element INDEX consisting of CHARS_PER_ELT chars from
>     STRING_CST STRING.  */
>
> @@ -2379,22 +2405,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
>         }
>      }
>
> -  tree nelts;
> -  if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
> -    {
> -      if (TYPE_DOMAIN (TREE_TYPE (ary)))
> -       nelts = array_type_nelts_top (TREE_TYPE (ary));
> -      else
> -       nelts = size_zero_node;
> -    }
> -  else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
> -    nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
> -  else
> -    gcc_unreachable ();
> -
> -  /* For VLAs, the number of elements won't be an integer constant.  */
> -  nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
> -                                       overflow_p);
> +  tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
> +                                         overflow_p);
>    VERIFY_CONSTANT (nelts);
>    if ((lval
>         ? !tree_int_cst_le (index, nelts)
> @@ -2895,7 +2907,6 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
>                      bool *non_constant_p, bool *overflow_p)
>  {
>    tree elttype = TREE_TYPE (atype);
> -  unsigned HOST_WIDE_INT max = tree_to_uhwi (array_type_nelts_top (atype));
>    verify_ctor_sanity (ctx, atype);
>    vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
>    bool pre_init = false;
> @@ -2924,6 +2935,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
>        pre_init = true;
>      }
>
> +  tree nelts = get_array_or_vector_nelts (ctx, atype, non_constant_p,
> +                                         overflow_p);
> +  unsigned HOST_WIDE_INT max = tree_to_uhwi (nelts);
>    for (i = 0; i < max; ++i)
>      {
>        tree idx = build_int_cst (size_type_node, i);
> @@ -3480,19 +3494,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
>         case ARRAY_REF:
>           tree nelts, ary;
>           ary = TREE_OPERAND (probe, 0);
> -         if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
> -           {
> -             if (TYPE_DOMAIN (TREE_TYPE (ary)))
> -               nelts = array_type_nelts_top (TREE_TYPE (ary));
> -             else
> -               nelts = size_zero_node;
> -           }
> -         else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
> -           nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
> -         else
> -           gcc_unreachable ();
> -         nelts = cxx_eval_constant_expression (ctx, nelts, false,
> -                                               non_constant_p, overflow_p);
> +         nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary),
> +                                            non_constant_p, overflow_p);
>           VERIFY_CONSTANT (nelts);
>           gcc_assert (TREE_CODE (nelts) == INTEGER_CST
>                       && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
> diff --git gcc/testsuite/g++.dg/ext/flexary29.C gcc/testsuite/g++.dg/ext/flexary29.C
> index e69de29bb2d..a696fd9804f 100644
> --- gcc/testsuite/g++.dg/ext/flexary29.C
> +++ gcc/testsuite/g++.dg/ext/flexary29.C
> @@ -0,0 +1,12 @@
> +// PR c++/84578
> +// { dg-do compile { target c++11 } }
> +// { dg-options -Wno-pedantic }
> +
> +struct A
> +{
> +  constexpr A() : i(), x() {}
> +  int i;
> +  char x[];
> +};
> +
> +A a;
>
>         Marek
diff mbox series

Patch

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 39e6cdfb33d..27f841db38f 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -2300,6 +2300,32 @@  diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
     }
 }
 
+/* Return the number of elements for TYPE (which is an ARRAY_TYPE or
+   a VECTOR_TYPE).  */
+
+static tree
+get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
+			   bool *non_constant_p, bool *overflow_p)
+{
+  tree nelts;
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (type))
+	nelts = array_type_nelts_top (type);
+      else
+	nelts = size_zero_node;
+    }
+  else if (VECTOR_TYPE_P (type))
+    nelts = size_int (TYPE_VECTOR_SUBPARTS (type));
+  else
+    gcc_unreachable ();
+
+  /* For VLAs, the number of elements won't be an integer constant.  */
+  nelts = cxx_eval_constant_expression (ctx, nelts, false,
+					non_constant_p, overflow_p);
+  return nelts;
+}
+
 /* Extract element INDEX consisting of CHARS_PER_ELT chars from
    STRING_CST STRING.  */
 
@@ -2379,22 +2405,8 @@  cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
 	}
     }
 
-  tree nelts;
-  if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-    {
-      if (TYPE_DOMAIN (TREE_TYPE (ary)))
-	nelts = array_type_nelts_top (TREE_TYPE (ary));
-      else
-	nelts = size_zero_node;
-    }
-  else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
-    nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
-  else
-    gcc_unreachable ();
-
-  /* For VLAs, the number of elements won't be an integer constant.  */
-  nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
-					overflow_p);
+  tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
+					  overflow_p);
   VERIFY_CONSTANT (nelts);
   if ((lval
        ? !tree_int_cst_le (index, nelts)
@@ -2895,7 +2907,6 @@  cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
 		     bool *non_constant_p, bool *overflow_p)
 {
   tree elttype = TREE_TYPE (atype);
-  unsigned HOST_WIDE_INT max = tree_to_uhwi (array_type_nelts_top (atype));
   verify_ctor_sanity (ctx, atype);
   vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
   bool pre_init = false;
@@ -2924,6 +2935,9 @@  cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
       pre_init = true;
     }
 
+  tree nelts = get_array_or_vector_nelts (ctx, atype, non_constant_p,
+					  overflow_p);
+  unsigned HOST_WIDE_INT max = tree_to_uhwi (nelts);
   for (i = 0; i < max; ++i)
     {
       tree idx = build_int_cst (size_type_node, i);
@@ -3480,19 +3494,8 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
 	case ARRAY_REF:
 	  tree nelts, ary;
 	  ary = TREE_OPERAND (probe, 0);
-	  if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-	    {
-	      if (TYPE_DOMAIN (TREE_TYPE (ary)))
-		nelts = array_type_nelts_top (TREE_TYPE (ary));
-	      else
-		nelts = size_zero_node;
-	    }
-	  else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
-	    nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
-	  else
-	    gcc_unreachable ();
-	  nelts = cxx_eval_constant_expression (ctx, nelts, false,
-						non_constant_p, overflow_p);
+	  nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary),
+					     non_constant_p, overflow_p);
 	  VERIFY_CONSTANT (nelts);
 	  gcc_assert (TREE_CODE (nelts) == INTEGER_CST
 		      && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
diff --git gcc/testsuite/g++.dg/ext/flexary29.C gcc/testsuite/g++.dg/ext/flexary29.C
index e69de29bb2d..a696fd9804f 100644
--- gcc/testsuite/g++.dg/ext/flexary29.C
+++ gcc/testsuite/g++.dg/ext/flexary29.C
@@ -0,0 +1,12 @@ 
+// PR c++/84578
+// { dg-do compile { target c++11 } }
+// { dg-options -Wno-pedantic }
+
+struct A
+{
+  constexpr A() : i(), x() {}
+  int i;
+  char x[];
+};
+
+A a;