aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-04-03 17:15:36 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-04-03 17:15:36 -0400
commit5a68fae797b88216b40eb6af8c75dec6e98b983c (patch)
tree28f3a1d200fa86ca4057f09c132ba79749c015a7 /gcc/cp
parentb0dfb235e837330a5f91ff14092aa76684fee24d (diff)
downloadgcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.zip
gcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.tar.gz
gcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.tar.bz2
PR sanitizer/79993 - ICE with VLA initialization from string
PR c++/69487 - wrong VLA initialization from string * init.c (finish_length_check): Split out from build_vec_init. (build_vec_init): Handle STRING_CST. * typeck2.c (split_nonconstant_init): Handle STRING_CST. (digest_init_r): Don't give a STRING_CST VLA type. From-SVN: r246662
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/init.c92
-rw-r--r--gcc/cp/typeck2.c7
3 files changed, 80 insertions, 28 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7438479..f3c668b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2017-04-03 Jason Merrill <jason@redhat.com>
+
+ PR sanitizer/79993 - ICE with VLA initialization from string
+ PR c++/69487 - wrong VLA initialization from string
+ * init.c (finish_length_check): Split out from build_vec_init.
+ (build_vec_init): Handle STRING_CST.
+ * typeck2.c (split_nonconstant_init): Handle STRING_CST.
+ (digest_init_r): Don't give a STRING_CST VLA type.
+
2017-03-31 Jakub Jelinek <jakub@redhat.com>
PR c++/79572
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 7732795..2015205 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3884,6 +3884,35 @@ vec_copy_assign_is_trivial (tree inner_elt_type, tree init)
return is_trivially_xible (MODIFY_EXPR, inner_elt_type, fromtype);
}
+/* Subroutine of build_vec_init: Check that the array has at least N
+ elements. Other parameters are local variables in build_vec_init. */
+
+void
+finish_length_check (tree atype, tree iterator, tree obase, unsigned n)
+{
+ tree nelts = build_int_cst (ptrdiff_type_node, n - 1);
+ if (TREE_CODE (atype) != ARRAY_TYPE)
+ {
+ if (flag_exceptions)
+ {
+ tree c = fold_build2 (LT_EXPR, boolean_type_node, iterator,
+ nelts);
+ c = build3 (COND_EXPR, void_type_node, c,
+ throw_bad_array_new_length (), void_node);
+ finish_expr_stmt (c);
+ }
+ /* Don't check an array new when -fno-exceptions. */
+ }
+ else if (flag_sanitize & SANITIZE_BOUNDS
+ && do_ubsan_in_current_function ())
+ {
+ /* Make sure the last element of the initializer is in bounds. */
+ finish_expr_stmt
+ (ubsan_instrument_bounds
+ (input_location, obase, &nelts, /*ignore_off_by_one*/false));
+ }
+}
+
/* `build_vec_init' returns tree structure that performs
initialization of a vector of aggregate types.
@@ -3932,6 +3961,8 @@ build_vec_init (tree base, tree maxindex, tree init,
tree obase = base;
bool xvalue = false;
bool errors = false;
+ location_t loc = (init ? EXPR_LOC_OR_LOC (init, input_location)
+ : location_of (base));
if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
maxindex = array_type_nelts (atype);
@@ -3963,10 +3994,12 @@ build_vec_init (tree base, tree maxindex, tree init,
}
}
- /* If we have a braced-init-list, make sure that the array
+ /* If we have a braced-init-list or string constant, make sure that the array
is big enough for all the initializers. */
- bool length_check = (init && TREE_CODE (init) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (init) > 0
+ bool length_check = (init
+ && (TREE_CODE (init) == STRING_CST
+ || (TREE_CODE (init) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (init) > 0))
&& !TREE_CONSTANT (maxindex));
if (init
@@ -4105,30 +4138,7 @@ build_vec_init (tree base, tree maxindex, tree init,
from_array = 0;
if (length_check)
- {
- tree nelts = build_int_cst (ptrdiff_type_node,
- CONSTRUCTOR_NELTS (init) - 1);
- if (TREE_CODE (atype) != ARRAY_TYPE)
- {
- if (flag_exceptions)
- {
- tree c = fold_build2 (LT_EXPR, boolean_type_node, iterator,
- nelts);
- c = build3 (COND_EXPR, void_type_node, c,
- throw_bad_array_new_length (), void_node);
- finish_expr_stmt (c);
- }
- /* Don't check an array new when -fno-exceptions. */
- }
- else if (flag_sanitize & SANITIZE_BOUNDS
- && do_ubsan_in_current_function ())
- {
- /* Make sure the last element of the initializer is in bounds. */
- finish_expr_stmt
- (ubsan_instrument_bounds
- (input_location, obase, &nelts, /*ignore_off_by_one*/false));
- }
- }
+ finish_length_check (atype, iterator, obase, CONSTRUCTOR_NELTS (init));
if (try_const)
vec_alloc (const_vec, CONSTRUCTOR_NELTS (init));
@@ -4196,6 +4206,34 @@ build_vec_init (tree base, tree maxindex, tree init,
/* Any elements without explicit initializers get T{}. */
empty_list = true;
}
+ else if (init && TREE_CODE (init) == STRING_CST)
+ {
+ /* Check that the array is at least as long as the string. */
+ if (length_check)
+ finish_length_check (atype, iterator, obase,
+ TREE_STRING_LENGTH (init));
+ tree length = build_int_cst (ptrdiff_type_node,
+ TREE_STRING_LENGTH (init));
+
+ /* Copy the string to the first part of the array. */
+ tree alias_set = build_int_cst (build_pointer_type (type), 0);
+ tree lhs = build2 (MEM_REF, TREE_TYPE (init), base, alias_set);
+ tree stmt = build2 (MODIFY_EXPR, void_type_node, lhs, init);
+ finish_expr_stmt (stmt);
+
+ /* Adjust the counter and pointer. */
+ stmt = cp_build_binary_op (loc, MINUS_EXPR, iterator, length, complain);
+ stmt = build2 (MODIFY_EXPR, void_type_node, iterator, stmt);
+ finish_expr_stmt (stmt);
+
+ stmt = cp_build_binary_op (loc, PLUS_EXPR, base, length, complain);
+ stmt = build2 (MODIFY_EXPR, void_type_node, base, stmt);
+ finish_expr_stmt (stmt);
+
+ /* And set the rest of the array to NUL. */
+ from_array = 0;
+ explicit_value_init_p = true;
+ }
else if (from_array)
{
if (init)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 58a01c9..d1a3930 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -749,6 +749,10 @@ split_nonconstant_init (tree dest, tree init)
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
}
+ else if (TREE_CODE (init) == STRING_CST
+ && array_of_runtime_bound_p (TREE_TYPE (dest)))
+ code = build_vec_init (dest, NULL_TREE, init, /*value-init*/false,
+ /*from array*/1, tf_warning_or_error);
else
code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init);
@@ -1066,7 +1070,8 @@ digest_init_r (tree type, tree init, bool nested, int flags,
}
}
- if (type != TREE_TYPE (init))
+ if (type != TREE_TYPE (init)
+ && !variably_modified_type_p (type, NULL_TREE))
{
init = copy_node (init);
TREE_TYPE (init) = type;