diff options
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 55 | ||||
-rw-r--r-- | gcc/cp/init.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/constexpr-vla2.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/constexpr-vla3.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/vla-1.C | 1 |
7 files changed, 81 insertions, 31 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2c2cdfb..6c66cc4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 57595a4..b076991 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9f7b614..976ada8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3c27184..c20ea73 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..6cb1f70 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C @@ -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 index 0000000..ba4eb50 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/ubsan/vla-1.C b/gcc/testsuite/g++.dg/ubsan/vla-1.C index e7f2494..311cdb1 100644 --- a/gcc/testsuite/g++.dg/ubsan/vla-1.C +++ b/gcc/testsuite/g++.dg/ubsan/vla-1.C @@ -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) { |