diff options
author | Martin Sebor <msebor@redhat.com> | 2016-04-14 17:35:23 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2016-04-14 11:35:23 -0600 |
commit | d8747845fded660e09bab98470f77753a4216b6e (patch) | |
tree | 83cb3798bea28b1aa1cc72277814a9f1a15bffd0 /gcc | |
parent | 851285595028bdbb0eed29766e6eece1a884138e (diff) | |
download | gcc-d8747845fded660e09bab98470f77753a4216b6e.zip gcc-d8747845fded660e09bab98470f77753a4216b6e.tar.gz gcc-d8747845fded660e09bab98470f77753a4216b6e.tar.bz2 |
PR c++/70652 - [6 Regression] r234966 causes bootstrap to fail
PR c++/70652 - [6 Regression] r234966 causes bootstrap to fail
Revert patch for c++/69517, c++/70019, and c++/70588.
From-SVN: r234981
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 45 | ||||
-rw-r--r-- | gcc/cp/init.c | 315 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 4 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 38 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/ubsan/vla-1.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla12.C | 99 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla13.C | 260 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla14.C | 48 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla3.C | 43 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array24.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/vla-1.C | 5 |
15 files changed, 47 insertions, 872 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c4a0759..17de27f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-04-14 Martin Sebor <msebor@redhat.com> + + PR c++/69517 + PR c++/70019 + PR c++/70588 + * doc/extend.texi (Variable Length): Revert. + 2016-04-14 Marek Polacek <polacek@redhat.com> Jan Hubicka <hubicka@ucw.cz> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4267f65..feb38c2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2016-04-14 Martin Sebor <msebor@redhat.com> + + PR c++/69517 + PR c++/70019 + PR c++/70588 + * cp-tree.h, decl.c, init.c, typeck2.c: Revert. + 2016-04-14 Jason Merrill <jason@redhat.com> * call.c, decl.c, error.c, cp-tree.h, decl.c: Revert empty diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index baff674..a3cd834 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5944,7 +5944,6 @@ extern tree build_value_init_noctor (tree, tsubst_flags_t); extern tree get_nsdmi (tree, bool); extern tree build_offset_ref (tree, tree, bool, tsubst_flags_t); -extern tree throw_bad_array_length (void); extern tree throw_bad_array_new_length (void); extern tree build_new (vec<tree, va_gc> **, tree, tree, vec<tree, va_gc> **, int, @@ -5966,7 +5965,6 @@ extern tree scalar_constant_value (tree); extern tree decl_really_constant_value (tree); extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool); extern tree build_vtbl_address (tree); -extern tree build_vla_check (tree, tree = NULL_TREE); /* in lex.c */ extern void cxx_dup_lang_specific_decl (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 65b5733..380bc79 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5892,16 +5892,6 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p, } } - if (variably_modified_type_p (type, NULL_TREE)) - { - /* Require VLAs to have their initializers fully braced - to avoid initializing the wrong elements. */ - if (complain & tf_error) - error ("missing braces around initializer for a variable length " - "array %qT", type); - return error_mark_node; - } - warning (OPT_Wmissing_braces, "missing braces around initializer for %qT", type); } @@ -6054,10 +6044,6 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) /* There is no way to make a variable-sized class type in GNU C++. */ gcc_assert (TREE_CONSTANT (TYPE_SIZE (type))); - /* Initializer exression used to check invalid VLA bounds and excess - initializer elements. */ - tree saved_init_for_vla_check = NULL_TREE; - if (init && BRACE_ENCLOSED_INITIALIZER_P (init)) { int init_len = vec_safe_length (CONSTRUCTOR_ELTS (init)); @@ -6209,9 +6195,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl))) warning (0, "array %qD initialized by parenthesized string literal %qE", decl, DECL_INITIAL (decl)); - - saved_init_for_vla_check = init; - init = NULL_TREE; + init = NULL; } } else @@ -6225,33 +6209,6 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) check_for_uninitialized_const_var (decl); } - if (TREE_CODE (type) == ARRAY_TYPE - && variably_modified_type_p (type, NULL_TREE) - && !processing_template_decl) - { - /* Statically check for overflow in VLA bounds and build - an expression that checks at runtime whether the VLA - is erroneous due to invalid (runtime) bounds. - Another expression to check for excess initializers - is built in build_vec_init. */ - tree check = build_vla_check (TREE_TYPE (decl), saved_init_for_vla_check); - - if (flag_exceptions && current_function_decl - /* Avoid instrumenting constexpr functions for now. - Those must be checked statically, and the (non- - constexpr) dynamic instrumentation would cause - them to be rejected. See c++/70507. */ - && !DECL_DECLARED_CONSTEXPR_P (current_function_decl)) - { - /* Use the runtime check only when exceptions are enabled. - Otherwise let bad things happen... */ - check = build3 (COND_EXPR, void_type_node, check, - throw_bad_array_length (), void_node); - - finish_expr_stmt (check); - } - } - if (init && init != error_mark_node) init_code = build2 (INIT_EXPR, type, decl, init); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ec19d72..5997d53 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2262,20 +2262,6 @@ diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool compla return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain); } -/* Call __cxa_throw_bad_array_length to indicate that the size calculation - in the bounds of a variable length array overflowed. */ - -tree -throw_bad_array_length (void) -{ - tree fn = get_identifier ("__cxa_throw_bad_array_length"); - if (!get_global_value_if_present (fn, &fn)) - fn = push_throw_library_fn (fn, build_function_type_list (void_type_node, - NULL_TREE)); - - return build_cxx_call (fn, 0, NULL, tf_warning_or_error); -} - /* Call __cxa_bad_array_new_length to indicate that the size calculation overflowed. Pretend it returns sizetype so that it plays nicely in the COND_EXPR. */ @@ -4723,304 +4709,3 @@ build_vec_delete (tree base, tree maxindex, return rval; } - - -/* The implementation of build_vla_check() that recursively builds - an expression to determine whether the VLA TYPE is erroneous due - either to its bounds being invalid or to integer overflow in - the computation of its total size. - CHECK is the boolean expression being built, initialized to - boolean_false_node. - VLASIZE is used internally to pass the incrementally computed - size of the VLA object down to its recursive invocations. - MAX_VLASIZE is the maximum valid size of the VLA in bytes. - CST_SIZE is the product of the VLA's constant dimensions. */ - -static tree -build_vla_size_check (tree check, - tree type, - tree vlasize, - tree max_vlasize, - offset_int *cst_size) -{ - tree vmul = builtin_decl_explicit (BUILT_IN_MUL_OVERFLOW); - - tree vlasizeaddr = build_unary_op (input_location, ADDR_EXPR, vlasize, 0); - - bool overflow = false; - - if (TREE_CODE (type) == ARRAY_TYPE) - { - /* Compute the upper bound of this array type. */ - tree inner_nelts = array_type_nelts_top (type); - tree inner_nelts_cst = maybe_constant_value (inner_nelts); - - if (TREE_CODE (inner_nelts_cst) == INTEGER_CST) - { - /* The upper bound is a constant expression. Compute the product - of the constant upper bounds seen so far so that overflow can - be diagnosed. */ - offset_int result = wi::mul (wi::to_offset (inner_nelts_cst), - *cst_size, SIGNED, &overflow); - *cst_size = overflow ? 0 : result; - } - - /* Check for overflow in the VLAs (runtime) upper bounds. */ - tree vflowcheck = build_call_expr (vmul, 3, inner_nelts, - vlasize, vlasizeaddr); - - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, vflowcheck); - - /* Recursively check for overflow in the remaining major bounds. */ - check = build_vla_size_check (check, TREE_TYPE (type), - vlasize, max_vlasize, - cst_size); - } - else - { - /* Get the size of the VLA element type in bytes. */ - tree typesize = TYPE_SIZE_UNIT (type); - - /* See if the size, when multipled by the product of the VLA's - constant dimensions, is within range of size_t. If not, - the VLA is definitely erroneous amd must be diagnosed at - compile time. */ - offset_int result = wi::mul (wi::to_offset (typesize), *cst_size, - SIGNED, &overflow); - *cst_size = overflow ? 0 : result; - - /* Multiply the (non-constant) VLA size so far by the element size, - checking for overflow, and replacing the value of vlasize with - the product in the absence of overflow. This size is the total - runtime size of the VLA in bytes. */ - tree vflowcheck = build_call_expr (vmul, 3, typesize, - vlasize, vlasizeaddr); - - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, vflowcheck); - - /* Check to see if the final VLA size exceeds the maximum. */ - tree sizecheck = fold_build2 (LT_EXPR, boolean_type_node, - max_vlasize, vlasize); - - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, sizecheck); - - /* Also check to see if the final array size is zero (the size - is unsigned so the earlier overflow check detects negative - values as well. */ - tree zerocheck = fold_build2 (EQ_EXPR, boolean_type_node, - vlasize, size_zero_node); - - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, zerocheck); - } - - /* Diagnose overflow determined at compile time. */ - if (overflow) - { - error ("integer overflow in variable array size"); - /* Reset to suppress any further diagnostics. */ - *cst_size = 0; - } - - return check; -} - -/* The implementation of build_vla_check() that recursively builds - an expression to determine whether the VLA initializer-list for - TYPE is erroneous due to excess initializers. - CHECK is the boolean expression being built, initialized to - the result of build_vla_size_check(). - INIT is the VLA initializer expression to check against TYPE. - On the first (non-recursive) call, INIT_ELTS is set either to 1, - or to the number of elements in the initializer-list for VLAs - of unspecified (major) bound. On subsequent (recursive) calls. - it is set to NULL and computed from the number of elements in - the (nested) initializer-list. -*/ - -static tree -build_vla_init_check (tree check, tree type, tree init, tree init_elts) -{ - if (TREE_CODE (type) == ARRAY_TYPE) - { - /* Compute the upper bound of this array type unless it has - already been computed by the caller for an array of unspecified - bound, as in 'T a[];' */ - tree inner_nelts = init_elts ? init_elts : array_type_nelts_top (type); - - size_t len; - - if (TREE_CODE (init) == CONSTRUCTOR) - { - /* The initializer of this array is itself an array. Build - an expression to check if the number of elements in the - initializer array exceeds the upper bound of the type - of the object being initialized. */ - if (vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (init)) - { - len = v->length (); - tree initelts = build_int_cstu (size_type_node, len); - tree initcheck = fold_build2 (LT_EXPR, boolean_type_node, - inner_nelts, initelts); - - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, initcheck); - - constructor_elt *ce; - HOST_WIDE_INT i; - - /* Iterate over all non-empty initializers in this array, - recursively building expressions to see if the elements - of each are in excess of the corresponding (runtime) - bound of the array type. */ - FOR_EACH_VEC_SAFE_ELT (v, i, ce) - check = build_vla_init_check (check, TREE_TYPE (type), - ce->value, NULL_TREE); - } - } - else if (TREE_CODE (init) == STRING_CST - && (len = TREE_STRING_LENGTH (init))) - { - /* The initializer of this array is a string. */ - tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); - len /= TYPE_PRECISION (ctype) / BITS_PER_UNIT; - - /* A C++ string literal initializer must have at most as many - characters as there are elements in the array, including - the terminating NUL. */ - tree initelts = build_int_cstu (size_type_node, len); - tree initcheck = fold_build2 (LT_EXPR, boolean_type_node, - inner_nelts, initelts); - check = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, - check, initcheck); - } - else if (TREE_CODE (init) == ERROR_MARK) - { - // No checking is possible. - check = boolean_false_node; - } - else - { - /* What's this array initializer? */ - gcc_unreachable (); - } - } - - return check; -} - -/* Build an expression to determine whether the VLA TYPE is erroneous. - INIT is the VLA initializer expression or NULL_TREE when the VLA is - not initialized. */ - -tree -build_vla_check (tree type, tree init /* = NULL_TREE */) -{ - tree check = boolean_false_node; - - /* The product of all constant dimensions of the VLA, initialized - to either 1 in the common case or to the number of elements in - the VLA's initializer-list for VLAs of unspecified (major) - bound. */ - offset_int cst_size = 1; - - /* The initial size of the VLA to start the computation of the total - size with. Like CST_SIZE above, initialized to 1 or the number - of elements in the VLA's initializer-list for VLAs of unspecified - bound. */ - tree initial_size = size_one_node; - - /* For a VLA of unspecified (major) bound, the number of elements - it is initialized with determined from the initializer-list. */ - tree initial_elts = NULL_TREE; - - if (init) - { - /* Determine the upper bound of the VLA of unspecified bound, - as in 'T a[];' if this is such a VLA. Such a VLA can be - initialized with any number of elements but the number of - elements so determined must be used to check the total size - of the VLA. */ - gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - - if (tree dom = TYPE_DOMAIN (type)) - if (tree max = TYPE_MAX_VALUE (dom)) - if (integer_zerop (max)) - { - if (TREE_CODE (init) == CONSTRUCTOR) - { - vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (init); - - /* Since the upper bound of every array must be positive - a VLA with an unspecified major bound must be initized - by a non-empty initializer list. */ - gcc_assert (v != NULL); - - cst_size = v->length (); - } - else if (TREE_CODE (init) == STRING_CST) - { - /* The initializer is a (possibly empty) string consisting - at a minumum of one character, the terminating NUL. - This condition implies a definition like - char s [][N] = ""; - which is an error but even though it has been diagnosed - by this point the initializer still winds up here. */ - size_t nchars = TREE_STRING_LENGTH (init); - tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); - nchars /= TYPE_PRECISION (ctype) / BITS_PER_UNIT; - - cst_size = nchars + 1; - } - - initial_elts = wide_int_to_tree (size_type_node, cst_size); - initial_size = initial_elts; - } - } - - /* Build a variable storing the total runtime size of the VLA and - initialize it either to 1 (in the common case) or to the number - of topmost elements in the initializer-list when the VLA is - an array of unspecified (major) bound. */ - tree vlasize = build_decl (input_location, - VAR_DECL, NULL_TREE, sizetype); - DECL_ARTIFICIAL (vlasize) = 1; - DECL_IGNORED_P (vlasize) = 1; - DECL_CONTEXT (vlasize) = current_function_decl; - DECL_INITIAL (vlasize) = initial_size; - vlasize = pushdecl (vlasize); - add_decl_expr (vlasize); - - /* Impose a lenient limit on the size of the biggest VLA in bytes. - FIXME: Tighten up the limit to make it more useful and make it - configurable for users with unusual requirements. */ - tree max_vlasize - = fold_build2 (RSHIFT_EXPR, size_type_node, - build_all_ones_cst (size_type_node), - integer_one_node); - - /* Build an expression that checks the runtime bounds of the VLA - for invalid values and the total size of the VLA for overflow. */ - check = build_vla_size_check (check, type, vlasize, max_vlasize, &cst_size); - - if (wi::ltu_p (wi::to_offset (max_vlasize), cst_size)) - { - /* Issue the warning only in the "topmost" (non-recursive) call - to avoid duplicating diagnostics. This is only a warning to - allow programs to be portable to more permissive environments. */ - warning (OPT_Wvla, "size of variable length array exceeds maximum " - "of %qE bytes", max_vlasize); - } - - if (init) - { - /* Build an expression that checks the VLA initializer expression - against the type of the VLA for excess elements. */ - check = build_vla_init_check (check, type, init, initial_elts); - } - - return check; -} diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index eba19ca..b921689 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -603,7 +603,7 @@ split_nonconstant_init_1 (tree dest, tree init) array_type_p = true; if ((TREE_SIDE_EFFECTS (init) && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) - || variably_modified_type_p (type, NULL_TREE)) + || array_of_runtime_bound_p (type)) { /* For an array, we only need/want a single cleanup region rather than one per element. */ @@ -845,7 +845,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) will perform the dynamic initialization. */ if (value != error_mark_node && (TREE_SIDE_EFFECTS (value) - || variably_modified_type_p (type, NULL_TREE) + || array_of_runtime_bound_p (type) || ! reduced_constant_expression_p (value))) return split_nonconstant_init (decl, value); /* If the value is a constant, just put it in DECL_INITIAL. If DECL diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6687d59..a5a8b23 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1638,48 +1638,14 @@ foo (int n) You can use the function @code{alloca} to get an effect much like variable-length arrays. The function @code{alloca} is available in many other C implementations (but not in all). On the other hand, -variable-length arrays are available in GCC for all targets and -provide type safety. +variable-length arrays are more elegant. There are other differences between these two methods. Space allocated with @code{alloca} exists until the containing @emph{function} returns. The space for a variable-length array is deallocated as soon as the array name's scope ends, unless you also use @code{alloca} in this scope. -Unlike GCC, G++ instruments variable-length arrays (@xref{Variable Length}) -with checks for erroneous uses: when a variable-length array object is -created its runtime bounds are checked to detect non-positive values, -integer overflows, sizes in excess of SIZE_MAX / 2 bytes, and excess -initializers. When an erroneous variable-length array is detected -the runtime arranges for an exception to be thrown that matches a handler -of type @code{std::bad_array_length}. - -Also unlike GCC, G++ allows variable-length arrays to be initialized. -However, unlike initializer lists for ordinary multidimensional arrays, -those for multidimensional variable-length arrays must be enclosed in -pairs of curly braces delimiting each sequence of values to use to -initialize each subarray. Initializer lists that aren't unambiguously -enclosed in braces are rejected with an error. For example, in the -following function, the initializer list for the ordinary @code{array} -is accepted even though it isn't fully enclosed in braces. The same -initializer list, however, wouldn't be accepted for a multidimensional -variable-length array. To initialize the variable-length array @code{vla}, -the elements of the subarray @code{vla[m]} must be enclosed in braces -as shown. As with ordinary arrays, elements that aren't initialized -explicitly are default-initialized. - -@smallexample -void -foo (int m, int n) -@{ - int array[2][3] = @{ 1, 2, 4, 5, 6 @}; - int vla[m][n] = @{ @{ 1, 2 @}, @{ 4, 5, 6 @} @}; -@} -@end smallexample - - -In C programs (but not in C++) variable-length arrays can also be declared -as function arguments: +You can also use variable-length arrays as arguments to functions: @smallexample struct entry diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9cd0c6c..44f71b5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2016-04-14 Martin Sebor <msebor@redhat.com> + + PR c++/69517 + PR c++/70019 + PR c++/70588 + * c-c++-common/ubsan/vla-1.c: Revert. + * g++.dg/cpp1y/vla11.C: Same. + * g++.dg/cpp1y/vla12.C: Same. + * g++.dg/cpp1y/vla13.C: Same. + * g++.dg/cpp1y/vla14.C: Same. + * g++.dg/cpp1y/vla3.C: Same. + * gcc/testsuite/g++.dg/init/array24.C: Same. + * g++.dg/ubsan/vla-1.C: Same. + 2016-04-14 Marek Polacek <polacek@redhat.com> Jan Hubicka <hubicka@ucw.cz> diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-1.c b/gcc/testsuite/c-c++-common/ubsan/vla-1.c index 27ef110..52ade3a 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-1.c @@ -87,24 +87,18 @@ fn12 (void) int main (void) { -#if __cplusplus -# define TRY(stmt) do { try { stmt; } catch (...) { } } while (0) -#else -# define TRY(stmt) stmt -#endif - - TRY (fn1 ()); - TRY (fn2 ()); - TRY (fn3 ()); - TRY (fn4 ()); - TRY (fn5 ()); - TRY (fn6 ()); - TRY (fn7 ()); - TRY (fn8 ()); - TRY (fn9 ()); - TRY (fn10 ()); - TRY (fn11 ()); - TRY (fn12 ()); + fn1 (); + fn2 (); + fn3 (); + fn4 (); + fn5 (); + fn6 (); + fn7 (); + fn8 (); + fn9 (); + fn10 (); + fn11 (); + fn12 (); return 0; } diff --git a/gcc/testsuite/g++.dg/cpp1y/vla12.C b/gcc/testsuite/g++.dg/cpp1y/vla12.C deleted file mode 100644 index f938f3b..0000000 --- a/gcc/testsuite/g++.dg/cpp1y/vla12.C +++ /dev/null @@ -1,99 +0,0 @@ -// Test to verify that variable length arrays the product of whose constant -// bounds overflows or exceeds the implementation-defined limit are diagnosed. -// { dg-do compile { target c++11 } } -// { dg-additional-options "-Wno-error=vla" } - -#define INT_MAX __INT_MAX__ -#define LONG_MAX __LONG_MAX__ -#define SIZE_MAX __SIZE_MAX__ - -typedef __SIZE_TYPE__ size_t; - -#define MAX (SIZE_MAX / 2) - -void test (int x) -{ - const size_t amax = MAX; - - // The following are valid and shouldn't elicit a bounds overflow warning. - { - char a [x][amax]; // { dg-warning "forbids" } - (void)a; - } - - { - char a [amax][x]; // { dg-warning "forbids" } - (void)a; - } - - // The following is invalid and should be diagnosed. Unfortunately, - // when the VLA maximum size is (SIZE_MAX / 2), G++ also issues - // a (bogus) -Woverflow because it computes the array bound in - // a signed type (ssize_t) instead of size_t, in addition to - // rejecting the declaration with error: size of array ‘a’ is too - // large, before the VLA constant bound check has had a chance to - // see it. So the test is disabled. - // { - // char a [x][amax + 1]; - // (void)a; - // } - - { - char a [x][x][amax]; // { dg-warning "forbids" } - (void)a; - } - - { - char a [x][amax][x]; // { dg-warning "forbids" } - (void)a; - } - - { - char a [amax][x][x]; // { dg-warning "forbids" } - (void)a; - } - - { - char a [2][x][amax]; // { dg-warning "forbids|exceeds maximum" } - (void)a; - } - - { - // Unfortunately, the following is rejected with a different error - // earlier during parsing and before the VLA checking gets to see - // it: error: size of array ‘a’ is too large - // Ditto for other multidimensional VLAs where the overflow occurs - // in the computation of the product of adjacent constant bounds. - // char a [x][amax][amax]; - // char b [x][2][amax]; - // That error above also leads to the following error when using - // the variable below. - // error:’ was not declared in this scope - // (void)a; - } - - { - char a [amax][x][amax]; // { dg-warning "forbids|exceeds maximum" } - (void)a; - } - - { - char a [amax][amax][x]; // { dg-warning "forbids|exceeds maximum" } - (void)a; - } - - { - struct A256 { __attribute__ ((aligned (256))) char a; }; - - enum { - M = 1024, - N = MAX / (sizeof (A256) * M) - }; - - A256 a [x][M][x][N]; // { dg-warning "forbids" } - (void)a; - - A256 b [2][x][M][x][N]; // { dg-warning "forbids|exceeds maximum" } - (void)b; - } -} diff --git a/gcc/testsuite/g++.dg/cpp1y/vla13.C b/gcc/testsuite/g++.dg/cpp1y/vla13.C deleted file mode 100644 index d473a63..0000000 --- a/gcc/testsuite/g++.dg/cpp1y/vla13.C +++ /dev/null @@ -1,260 +0,0 @@ -// PR c++/70019 - VLA size overflow not detected -// Runtime test to verify that attempting to initialize a VLA with a string -// or character array that's longer than the non-constant (runtime) bound -// of the VLA causes an exception to be thrown. For a compile-time version -// of the test see vla14.C. - -// { dg-do run { target c++11 } } -// { dg-additional-options "-Wno-vla" } - -#pragma GCC diagnostic ignored "-Wvla" - -#define SIZE_MAX __SIZE_MAX__ - -// The size of the largest allowed VLA in bytes. Bigger objects -// cause an exception to be thrown. Unless the maximum size is -// obscenely large, smaller objects should be successfully created -// provided there's enough stack space. See TEST_NEAR_VLA_MAX_SIZE -// below. -#define MAX (__SIZE_MAX__ / 2) - -// Define to non-zero to exercise very large VLAs with size just -// below the implementation-defined maximum. -#define TEST_NEAR_VLA_MAX_SIZE 0 - -// Define to zero to enable tests that cause an ICE due to c++/58646. -#define BUG_58646 1 - -// Define to zero to enable tests that cause an ICE due to c++/69487. -#define BUG_69487 1 - -// Helper macro to make it possible to pass as one multpile arguments -// to another macro. -#define Init(...) __VA_ARGS__ - -typedef __SIZE_TYPE__ size_t; - -// Incremented for each test failure. -int fail; - -// Used to convert a constant array dimension to a non-constant one. -template <class T> -T d (T n) -{ - return n; -} - -// Verify either that an expected exception has been thrown or that -// one hasn't been thrown if one isn't expected. -int __attribute__ ((noclone, noinline)) -sink (void *p, int line, bool expect, const char *expr) -{ - if (!p != expect) - { - __builtin_printf ("line %i: Assertion failed: '%s': " - "exception unexpectedly %sthrown\n", - line, expr, !p ? "" : "not "); - ++fail; - } - else - { -#if defined DEBUG && DEBUG - __builtin_printf ("line %i: Assertion passed: '%s': " - "exception %sthrown as expected\n", - line, expr, !p ? "" : "not "); -#endif - } - return 0; -} - -template <class T, int> -int test (); - -#define _CAT(name, line) name ## line -#define CAT(name, line) _CAT (name, line) - -#define STR(...) #__VA_ARGS__ - -// Macro to define a unique specialization of a function template to -// exercise a VLA of type T, rank N, with dimensions given by Dims -// and initializer Init. Expect is true when the VLA initialization -// is expected to trigger an exception. -// The macro creates a unique global dummy int object and initializes -// it with the result of the function. The dummy object servers no -// other purpose but to call the function. The function verifies -// the expected postconditions. -#define TEST(T, Dims, Init, Expect) \ - template <> \ - int test<T, __LINE__>() \ - { \ - const char str[] = "char a" #Dims " = { " STR (Init) " }"; \ - try { \ - T a Dims = { Init }; \ - return sink (a, __LINE__, Expect, str); \ - } \ - catch (...) { \ - return sink (0, __LINE__, Expect, str); \ - } \ - } \ - const int CAT (dummy, __LINE__) = test<T, __LINE__>() - - -// Create and run a test function exercising a VLA definition -// +-- Element Type -// | +-- VLA Dimensions -// | | +-- VLA Initializer -// | | | -// | | | +-- Expect Exception -// | | | | -// V V V V -TEST (char, [d(-1)], "", true); - -TEST (char, [d(0)], "", true); -TEST (char, [d(0)], (""), true); - -TEST (char, [d(1)], "", false); -TEST (char, [d(1)], (""), false); - -TEST (char, [d(1)], "1", true); -TEST (char, [d(1)], ("1"), true); - -TEST (char, [d(1)], "12", true); -TEST (char, [d(1)], "1234567890", true); - -TEST (char, [d(2)], "", false); -TEST (char, [d(2)], (""), false); - -TEST (char, [d(2)], "1", false); -TEST (char, [d(2)], "12", true); -TEST (char, [d(2)], "123", true); -TEST (char, [d(2)], "1234567890", true); - -TEST (char, [d(3)], "", false); -TEST (char, [d(3)], "1", false); -TEST (char, [d(3)], "12", false); -TEST (char, [d(3)], "123", true); -TEST (char, [d(3)], "1234", true); -TEST (char, [d(3)], "1234567890", true); - -#if TEST_NEAR_VLA_MAX_SIZE - -# if !BUG_69487 -// The following crash due to c++/69487. -TEST (char, [d(MAX)], "", false); -TEST (char, [d(MAX)], "1", false); -TEST (char, [d(MAX)], "12", false); -TEST (char, [d(MAX)], "1234567890", false); -# endif - -TEST (char, [d(MAX)], Init (), false); -TEST (char, [d(MAX)], Init (1), false); -TEST (char, [d(MAX)], Init (1, 2), false); -TEST (char, [d(MAX)], Init (1, 2, 3, 4, 5, 6, 7, 8, 9, 0), false); -#endif - -TEST (char, [d(SIZE_MAX / 2 + 1)], "", true); -TEST (char, [d(SIZE_MAX - 2)], "", true); -TEST (char, [d(SIZE_MAX - 1)], "", true); - -TEST (wchar_t, [d(1)], L"", false); -TEST (wchar_t, [d(1)], (L""), false); -TEST (wchar_t, [d(1)], L"1", true); -TEST (wchar_t, [d(1)], L"12", true); -TEST (wchar_t, [d(1)], L"1234567890", true); - -TEST (wchar_t, [d(2)], L"", false); -TEST (wchar_t, [d(2)], L"1", false); -TEST (wchar_t, [d(2)], L"12", true); -TEST (wchar_t, [d(2)], L"123", true); -TEST (wchar_t, [d(2)], L"1234567890", true); - -TEST (char, [d(1)][d(1)], Init (""), false); -TEST (char, [1] [d(1)], Init (""), false); -TEST (char, [d(1)][1], Init (""), false); - -TEST (char, [d(1)][d(1)], Init ("1"), true); - -// The following is accepted at compile time but throws an exception -// at runtime since in C++ a one-element array cannot be initialized -// with a string literal of length one because there isn't room for -// the terminating NUL -TEST (char, [1][d(1)], Init ("1"), true); - -// The following is rejected at compile-time since a one-element array -// cannot be initialized with a string literal of length one because -// there isn't room for the terminating NUL (see vla14.C). -// TEST (char, [d(1)][1], Init ("1"), false); - -TEST (char, [d(1)][d(1)], Init ("12"), true); -TEST (char, [d(1)][d(1)], Init ("1", "2"), true); -TEST (char, [d(1)][d(1)], Init ("1", "23"), true); - -TEST (char, [d(2)][d(2)], Init ("", ""), false); -TEST (char, [d(2)][d(2)], Init ("", "1"), false); -TEST (char, [d(2)][d(2)], Init ("1", ""), false); -TEST (char, [d(2)][d(2)], Init ("1", "1"), false); -TEST (char, [2][d(2)], Init ("", "1"), false); -TEST (char, [2][d(2)], Init ("1", ""), false); -TEST (char, [2][d(2)], Init ("1", "1"), false); -TEST (char, [d(2)][2], Init ("", "1"), false); -TEST (char, [d(2)][2], Init ("1", ""), false); -TEST (char, [d(2)][2], Init ("1", "1"), false); - -TEST (char, [2][d(2)], Init ("1", "23"), true); -TEST (char, [d(2)][d(2)], Init ("1", "23"), true); -TEST (char, [d(2)][d(2)], Init ("1", "23"), true); -TEST (char, [d(2)][d(2)], Init ("12","3"), true); - -#if TEST_NEAR_VLA_MAX_SIZE -# if !BUG_69487 - // The following crash due to c++/69487. -TEST (char, [1][d(MAX)], Init (""), false); -TEST (char, [1][d(MAX)], Init ("1"), false); -TEST (char, [1][d(MAX)], Init ("12"), false); -TEST (char, [1][d(MAX)], Init ("1234567890"), false); -# endif - -# if !BUG_58646 -// The following causes an ICE due to c++/58646. -TEST (char, [1][d(MAX)], Init (), false); -# endif - -TEST (char, [1][d(MAX)], Init ({1}), false); -TEST (char, [1][d(MAX)], Init ({1, 2}), false); -TEST (char, [1][d(MAX)], Init ({1, 2, 3}), false); -TEST (char, [1][d(MAX)], Init ({1, 2, 3, 4, 5, 6, 7, 8, 9, 0}), false); - -TEST (char, [d(MAX)][1], Init ({1}), false); -TEST (char, [d(MAX)][1], Init ({1}, {2}), false); -TEST (char, [d(MAX)][1], Init ({1}, {2}, {3}), false); -TEST (char, [d(MAX)][1], Init ({1}, {2}, {3}, {4}, {5}, - {6}, {7}, {8}, {9}, {0}), false); -#endif // TEST_NEAR_VLA_MAX_SIZE - -// The following are expected to throw due to excessive size. -TEST (char, [2][d(MAX)], Init ({1}), true); -TEST (char, [2][d(MAX)], Init ({1, 2}), true); -TEST (char, [2][d(MAX)], Init ({1}, {2}), true); -TEST (char, [2][d(MAX)], Init ({1, 2}, {3, 4}), true); -TEST (char, [2][d(MAX)], Init ({1, 2, 3}, {4, 5, 6}), true); -TEST (char, [2][d(MAX)], Init ({1, 2, 3, 4}, {5, 6, 7, 8}), true); - -TEST (char, [d(MAX)][2], Init ({1}), true); -TEST (char, [d(MAX)][2], Init ({1, 2}), true); -TEST (char, [d(MAX)][2], Init ({1}, {2}), true); -TEST (char, [d(MAX)][2], Init ({1, 2}, {3, 4}), true); -TEST (char, [d(MAX)][2], Init ({1, 2}, {3, 4}, {5, 6}), true); -TEST (char, [d(MAX)][2], Init ({1, 2}, {3, 4}, {5, 6}, {7, 8}), true); - -TEST (char, [d(MAX)][d(MAX)], Init ({1}), true); -TEST (char, [d(MAX)][d(MAX)], Init ({1, 2}), true); -TEST (char, [d(MAX)][d(MAX)], Init ({1}, {2}), true); -TEST (char, [d(MAX)][d(MAX)], Init ({1, 2}, {3, 4}), true); -TEST (char, [d(MAX)][d(MAX)], Init ({1, 2}, {3, 4}, {5, 6}), true); -TEST (char, [d(MAX)][d(MAX)], Init ({1, 2}, {3, 4}, {5, 6}, {7, 8}), true); - -int main () -{ - if (fail) - __builtin_abort (); -} diff --git a/gcc/testsuite/g++.dg/cpp1y/vla14.C b/gcc/testsuite/g++.dg/cpp1y/vla14.C deleted file mode 100644 index 4a0e827..0000000 --- a/gcc/testsuite/g++.dg/cpp1y/vla14.C +++ /dev/null @@ -1,48 +0,0 @@ -// PR c++/70019 - VLA size overflow not detected -// Compile-time test to verify that attempting to initialize a VLA with -// a string that's longer than the VLA's constant bound is diagnosed at -// compile time. For a runtime version of the test see vla13.C. - -// { dg-do run } -// { dg-additional-options "-Wno-vla" } - - -void test (int n) -{ - char a1[n][1] = { { "a" } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a1; - - char a2[1][n] = { { "a" } }; - (void)a2; - - char a3[n][1][1] = { { { "a" } } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a3; - - char a4[1][1][n] = { { { "a" } } }; - (void)a4; - - char a5[1][n][1] = { { { "a" } } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a5; - - char a6[n][1][n] = { { { "a" } } }; - (void)a6; - - - wchar_t a7[n][1] = { { L"a" } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a7; - - wchar_t a8[1][n] = { { L"a" } }; - (void)a8; - - wchar_t a9[n][1][1] = { { { L"a" } } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a9; - - wchar_t a10[1][1][n] = { { { L"a" } } }; - (void)a10; - - wchar_t a11[][n][1] = { { { L"a" } } }; // { dg-error "initializer-string for array of chars is too long" } - (void)a11; - - wchar_t a12[n][1][n] = { { { L"a" } } }; - (void)a12; -} diff --git a/gcc/testsuite/g++.dg/cpp1y/vla3.C b/gcc/testsuite/g++.dg/cpp1y/vla3.C deleted file mode 100644 index 9b2d6b307..0000000 --- a/gcc/testsuite/g++.dg/cpp1y/vla3.C +++ /dev/null @@ -1,43 +0,0 @@ -// Test for throwing bad_array_length on invalid array length. -// { dg-do run { target c++14 } } -// { dg-additional-options "-Wno-vla" } - -namespace std -{ -struct exception -{ - virtual ~exception (); - virtual const char* what () const throw (); -}; -} - -int f(int i) -{ - int ar[i]{1,2,3,4}; - return ar[i-1]; -} - -void g(int i) -{ - int ar[i]; - ar[0] = 42; -} - -int main() -{ - int ok = 0; - f(4); // OK - try { - f(3); // too small - } - catch (std::exception &e) { - ++ok; - } - try { g(-24); } // negative - catch (std::exception &e) { - ++ok; - } - - if (ok != 2) - __builtin_abort (); -} diff --git a/gcc/testsuite/g++.dg/init/array24.C b/gcc/testsuite/g++.dg/init/array24.C index fc10c0a..2d72df4 100644 --- a/gcc/testsuite/g++.dg/init/array24.C +++ b/gcc/testsuite/g++.dg/init/array24.C @@ -3,5 +3,5 @@ void foo(int i) { - int x[][i] = { { 0 } }; + int x[][i] = { 0 }; } diff --git a/gcc/testsuite/g++.dg/ubsan/vla-1.C b/gcc/testsuite/g++.dg/ubsan/vla-1.C index 374c80a..311cdb1 100644 --- a/gcc/testsuite/g++.dg/ubsan/vla-1.C +++ b/gcc/testsuite/g++.dg/ubsan/vla-1.C @@ -1,8 +1,5 @@ // { dg-do run } -// Disable exceptions to prevent the erroneous initializer from -// throwing before the sanitizer instrumentation has detected -// the problem. -// { dg-options "-Wno-vla -fno-exceptions -fsanitize=undefined" } +// { dg-options "-Wno-vla -fsanitize=undefined" } // { dg-output "index 1 out of bounds" } void f(int i) { |