]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/69509 (infinite loop compiling a VLA in a recursive constexpr function)
authorMarek Polacek <polacek@redhat.com>
Fri, 29 Jan 2016 09:25:14 +0000 (09:25 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 29 Jan 2016 09:25:14 +0000 (09:25 +0000)
PR c++/69509
PR c++/69516
* constexpr.c (cxx_eval_array_reference): Give the "array subscript
out of bound" error earlier.
* init.c (build_vec_init): Change NE_EXPR into GT_EXPR.  Update the
commentary.

* g++.dg/ext/constexpr-vla2.C: New test.
* g++.dg/ext/constexpr-vla3.C: New test.
* g++.dg/ubsan/vla-1.C: Remove dg-shouldfail.

From-SVN: r232969

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/constexpr-vla2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/constexpr-vla3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/vla-1.C

index 2c2cdfb0d0cf7466a9287f455231aba1dc455337..6c66cc4747ac4a832c9905aff4b1a29526ea698d 100644 (file)
@@ -1,3 +1,12 @@
+2016-01-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/69509
+       PR c++/69516
+       * constexpr.c (cxx_eval_array_reference): Give the "array subscript
+       out of bound" error earlier.
+       * init.c (build_vec_init): Change NE_EXPR into GT_EXPR.  Update the
+       commentary.
+
 2016-01-29  Patrick Palka  <ppalka@gcc.gnu.org>
 
        * name-lookup.c (begin_scope): After reusing a cp_binding_level
index 57595a4002627ec31132f997430452eeb3b87328..b0769914d452feef4e586dce552c793b7a67cd29 100644 (file)
@@ -1833,6 +1833,19 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
       return t;
     }
 
+  tree nelts = array_type_nelts_top (TREE_TYPE (ary));
+  /* 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);
+  VERIFY_CONSTANT (nelts);
+  if (!tree_int_cst_lt (index, nelts))
+    {
+      if (!ctx->quiet)
+       error ("array subscript out of bound");
+      *non_constant_p = true;
+      return t;
+    }
+
   bool found;
   if (TREE_CODE (ary) == CONSTRUCTOR)
     {
@@ -1846,37 +1859,23 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
 
   if (!found)
     {
-      tree nelts = array_type_nelts_top (TREE_TYPE (ary));
-      /* 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);
-      VERIFY_CONSTANT (nelts);
-      if (tree_int_cst_lt (index, nelts))
+      if (TREE_CODE (ary) == CONSTRUCTOR
+         && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary))
        {
-         if (TREE_CODE (ary) == CONSTRUCTOR
-             && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary))
-           {
-             /* 'ary' is part of the aggregate initializer we're currently
-                building; if there's no initializer for this element yet,
-                that's an error. */
-             if (!ctx->quiet)
-               error ("accessing uninitialized array element");
-             *non_constant_p = true;
-             return t;
-           }
-
-         /* If it's within the array bounds but doesn't have an explicit
-            initializer, it's value-initialized.  */
-         tree val = build_value_init (elem_type, tf_warning_or_error);
-         return cxx_eval_constant_expression (ctx, val,
-                                              lval,
-                                              non_constant_p, overflow_p);
+         /* 'ary' is part of the aggregate initializer we're currently
+            building; if there's no initializer for this element yet,
+            that's an error.  */
+         if (!ctx->quiet)
+           error ("accessing uninitialized array element");
+         *non_constant_p = true;
+         return t;
        }
 
-      if (!ctx->quiet)
-       error ("array subscript out of bound");
-      *non_constant_p = true;
-      return t;
+      /* If it's within the array bounds but doesn't have an explicit
+        initializer, it's value-initialized.  */
+      tree val = build_value_init (elem_type, tf_warning_or_error);
+      return cxx_eval_constant_expression (ctx, val, lval, non_constant_p,
+                                          overflow_p);
     }
 
   if (TREE_CODE (ary) == CONSTRUCTOR)
index 9f7b614a2938e207e25bf7853268f02930077df7..976ada84587752585ec84b1064733832c6cfac7f 100644 (file)
@@ -4008,7 +4008,7 @@ build_vec_init (tree base, tree maxindex, tree init,
                && (num_initialized_elts
                    == tree_to_shwi (maxindex) + 1))))
     {
-      /* If the ITERATOR is equal to -1, then we don't have to loop;
+      /* If the ITERATOR is lesser or equal to -1, then we don't have to loop;
         we've already initialized all the elements.  */
       tree for_stmt;
       tree elt_init;
@@ -4016,7 +4016,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 
       for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
       finish_for_init_stmt (for_stmt);
-      finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
+      finish_for_cond (build2 (GT_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
                       for_stmt, false);
       elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
index 3c271847f7c7b2162bef10f2b12b5acd172b6a62..c20ea73f52ff314009fd99a56c8536147d500ca8 100644 (file)
@@ -1,3 +1,11 @@
+2016-01-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/69509
+       PR c++/69516
+       * g++.dg/ext/constexpr-vla2.C: New test.
+       * g++.dg/ext/constexpr-vla3.C: New test.
+       * g++.dg/ubsan/vla-1.C: Remove dg-shouldfail.
+
 2016-01-29  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/69537
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C
new file mode 100644 (file)
index 0000000..6cb1f70
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/69509
+// { dg-do compile { target c++14 } }
+
+constexpr int
+fn_bad (int n)
+{
+  __extension__ int a [n] = { 0 };
+  int z = a [0] + (n ? fn_bad (n - 1) : 0);
+  return z;
+}
+
+constexpr int
+fn_ok (int n)
+{
+  __extension__ int a [n] = { 0 };
+  int z = a [0] + (n > 1 ? fn_ok (n - 1) : 0);
+  return z;
+}
+
+constexpr int i1 = fn_ok (3);
+constexpr int i2 = fn_bad (3); // { dg-error "array subscript out of bound" }
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C
new file mode 100644 (file)
index 0000000..ba4eb50
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/69516
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo (int n)
+{
+  __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 };
+  int z = 0;
+  for (int i = 0; i <= n; ++i)
+    z += a[i];
+  return z;
+}
+
+constexpr int n = foo (3); // { dg-error "array subscript out of bound" }
index e7f24945f7ae1ccdec2abe7209596b3d9e2cb4b0..311cdb1d77a740e81ff245adb809437052603eca 100644 (file)
@@ -1,6 +1,5 @@
 // { dg-do run }
 // { dg-options "-Wno-vla -fsanitize=undefined" }
-// { dg-shouldfail "ubsan" }
 // { dg-output "index 1 out of bounds" }
 
 void f(int i) {