PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer elements
PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer elements PR c++/70019 - VLA size overflow not detected PR c++/70588 - SIGBUS on a VLA larger than SIZE_MAX / 2 gcc/testsuite/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * c-c++-common/ubsan/vla-1.c (main): Catch exceptions. * g++.dg/cpp1y/vla11.C: New test. * g++.dg/cpp1y/vla12.C: New test. * g++.dg/cpp1y/vla13.C: New test. * g++.dg/cpp1y/vla14.C: New test. * g++.dg/cpp1y/vla3.C: Restore deleted test. * gcc/testsuite/g++.dg/init/array24.C: Fully brace VLA initializer. * g++.dg/ubsan/vla-1.C: Disable exceptions. gcc/cp/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * cp-tree.h (throw_bad_array_length, build_vla_check): Declare new functions. * decl.c (check_initializer, cp_finish_decl): Call them. (reshape_init_r): Reject incompletely braced intializer-lists for VLAs. * init.c (throw_bad_array_length, build_vla_check) (build_vla_size_check, build_vla_init_check): Define new functions. * typeck2.c (split_nonconstant_init_1): Use variably_modified_type_p() to detect a VLA. (store_init_value): Same. gcc/doc/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * extend.texi (Variable Length): Document C++ specifics. libstdc++-v3/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 * testsuite/25_algorithms/rotate/moveable2.cc: Make sure VLA upper bound is positive. From-SVN: r234966
This commit is contained in:
parent
2ecc0c837b
commit
342fac9537
18 changed files with 1628 additions and 20 deletions
|
@ -1,3 +1,10 @@
|
|||
2016-04-13 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/69517
|
||||
PR c++/70019
|
||||
PR c++/70588
|
||||
* doc/extend.texi (Variable Length): Document C++ specifics.
|
||||
|
||||
2016-04-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/70641
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
2016-04-13 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/69517
|
||||
PR c++/70019
|
||||
PR c++/70588
|
||||
* cp-tree.h (throw_bad_array_length, build_vla_check): Declare new
|
||||
functions.
|
||||
* decl.c (check_initializer, cp_finish_decl): Call them.
|
||||
(reshape_init_r): Reject incompletely braced intializer-lists
|
||||
for VLAs.
|
||||
* init.c (throw_bad_array_length, build_vla_check)
|
||||
(build_vla_size_check, build_vla_init_check): Define new functions.
|
||||
* typeck2.c (split_nonconstant_init_1): Use variably_modified_type_p()
|
||||
to detect a VLA.
|
||||
(store_init_value): Same.
|
||||
|
||||
2016-04-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Warn about empty parameter ABI with -Wabi=9.
|
||||
|
|
|
@ -5950,6 +5950,7 @@ 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,
|
||||
|
@ -5971,6 +5972,7 @@ 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);
|
||||
|
|
|
@ -5896,6 +5896,16 @@ 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);
|
||||
}
|
||||
|
@ -6048,6 +6058,10 @@ 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));
|
||||
|
@ -6199,7 +6213,9 @@ 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));
|
||||
init = NULL;
|
||||
|
||||
saved_init_for_vla_check = init;
|
||||
init = NULL_TREE;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -6213,6 +6229,33 @@ 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);
|
||||
|
||||
|
|
315
gcc/cp/init.c
315
gcc/cp/init.c
|
@ -2262,6 +2262,20 @@ 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. */
|
||||
|
@ -4709,3 +4723,304 @@ 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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|| array_of_runtime_bound_p (type))
|
||||
|| variably_modified_type_p (type, NULL_TREE))
|
||||
{
|
||||
/* 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)
|
||||
|| array_of_runtime_bound_p (type)
|
||||
|| variably_modified_type_p (type, NULL_TREE)
|
||||
|| ! 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
|
||||
|
|
|
@ -1638,14 +1638,48 @@ 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 more elegant.
|
||||
variable-length arrays are available in GCC for all targets and
|
||||
provide type safety.
|
||||
|
||||
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.
|
||||
|
||||
You can also use variable-length arrays as arguments to functions:
|
||||
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:
|
||||
|
||||
@smallexample
|
||||
struct entry
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
2016-04-13 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/69517
|
||||
PR c++/70019
|
||||
PR c++/70588
|
||||
* c-c++-common/ubsan/vla-1.c (main): Catch exceptions.
|
||||
* g++.dg/cpp1y/vla11.C: New test.
|
||||
* g++.dg/cpp1y/vla12.C: New test.
|
||||
* g++.dg/cpp1y/vla13.C: New test.
|
||||
* g++.dg/cpp1y/vla14.C: New test.
|
||||
* g++.dg/cpp1y/vla3.C: Restore deleted test.
|
||||
* gcc/testsuite/g++.dg/init/array24.C: Fully brace VLA initializer.
|
||||
* g++.dg/ubsan/vla-1.C: Disable exceptions.
|
||||
|
||||
2016-04-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/70641
|
||||
|
|
|
@ -87,18 +87,24 @@ fn12 (void)
|
|||
int
|
||||
main (void)
|
||||
{
|
||||
fn1 ();
|
||||
fn2 ();
|
||||
fn3 ();
|
||||
fn4 ();
|
||||
fn5 ();
|
||||
fn6 ();
|
||||
fn7 ();
|
||||
fn8 ();
|
||||
fn9 ();
|
||||
fn10 ();
|
||||
fn11 ();
|
||||
fn12 ();
|
||||
#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 ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
711
gcc/testsuite/g++.dg/cpp1y/vla11.C
Normal file
711
gcc/testsuite/g++.dg/cpp1y/vla11.C
Normal file
|
@ -0,0 +1,711 @@
|
|||
// PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer
|
||||
// elements
|
||||
// PR c++/70019 - VLA size overflow not detected
|
||||
//
|
||||
// Runtime test to verify that attempting to either construct a VLA with
|
||||
// erroneous bounds, or initialize one with an initializer-list that
|
||||
// contains more elements than the VLA's non-constant (runtime) bounds
|
||||
// causes an exception to be thrown. Test also verifies that valid
|
||||
// VLAs and their initializers don't cause such an exception.
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-additional-options "-Wno-vla" }
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wvla"
|
||||
|
||||
#define INT_MAX __INT_MAX__
|
||||
#define LONG_MAX __LONG_MAX__
|
||||
#define SIZE_MAX __SIZE_MAX__
|
||||
#define UINT_MAX (~0U)
|
||||
#define ULONG_MAX (~0LU)
|
||||
|
||||
#define INT_MIN (-__INT_MAX__ - 1)
|
||||
#define LONG_MIN (-__LONG_MAX__ - 1)
|
||||
|
||||
// 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
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#define _CAT(name, line) name ## line
|
||||
#define CAT(name, line) _CAT (name, line)
|
||||
|
||||
#define STR(...) #__VA_ARGS__
|
||||
|
||||
// Type to exercise VLA with. TYPESIZE is the size of the type in bytes.
|
||||
// Using a template serves two purposes. First, it makes it possible to
|
||||
// parameterize the test on VLAs of different size. Second, it verifies
|
||||
// that the checking code can deal with templates (i.e., completes
|
||||
// the element type of the VLA when necessary).
|
||||
template <unsigned TypeSize>
|
||||
struct alignas (TypeSize) TestType
|
||||
{
|
||||
char data;
|
||||
};
|
||||
|
||||
// Test function invoked with a pointer to each test case. Must
|
||||
// return a value though what value doesn't matter.
|
||||
int __attribute__ ((noclone, noinline))
|
||||
tester (int (*testcase)(const char*),
|
||||
const char *str, int line, bool expect)
|
||||
{
|
||||
try
|
||||
{
|
||||
return testcase (str);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return sink (0, line, expect, str);
|
||||
}
|
||||
}
|
||||
|
||||
// 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(TypeSize, Dims, Init, Expect) \
|
||||
static int CAT (testcase, __LINE__)(const char *str) \
|
||||
{ \
|
||||
TestType<TypeSize> vla Dims Init; \
|
||||
static_assert (sizeof (TestType<TypeSize>) == TypeSize, \
|
||||
"wrong test type size"); \
|
||||
return sink (vla, __LINE__, Expect, str); \
|
||||
} \
|
||||
const int CAT (dummy, __LINE__) \
|
||||
= tester (CAT (testcase, __LINE__), \
|
||||
"T<" #TypeSize "> a" #Dims " " STR (Init) ";", \
|
||||
__LINE__, Expect)
|
||||
|
||||
|
||||
// Create and run a test function exercising a VLA definition
|
||||
// of one of the following forms:
|
||||
// TestType<Size> VLA Dims; // uninitialized (with Init ())
|
||||
// or:
|
||||
// TestType<Size> VLA Dims Init; // initialized (with = Init ({...})
|
||||
//
|
||||
// +-- Element Size (in Bytes)
|
||||
// | +-- VLA Dimensions (constant as in [3], otherwise d(3))
|
||||
// | | +-- VLA Initializer Expression (if any)
|
||||
// | | | +-- Expect Exception
|
||||
// | | | |
|
||||
// V V V V
|
||||
TEST (1, [d(0)], Init (/* none*/), true); // uninitialized
|
||||
|
||||
#if !BUG_58646
|
||||
// The following causes an ICE due to c++/58646.
|
||||
TEST (1, [d(0)], Init ({}), true);
|
||||
#endif
|
||||
TEST (1, [d(0)], Init ({1}), true); // initialized with " {1}"
|
||||
TEST (1, [d(0)], = Init ({1}), true); // initialized with "= {1}"
|
||||
|
||||
TEST (1, [d(1)], Init (), false);
|
||||
TEST (1, [d(1)], Init ({}), false);
|
||||
TEST (1, [d(1)], = Init ({}), false);
|
||||
TEST (1, [d(1)], Init ({1}), false);
|
||||
TEST (1, [d(1)], = Init ({1}), false);
|
||||
TEST (1, [d(1)], Init ({1, 2}), true);
|
||||
TEST (1, [d(1)], = Init ({1, 2}), true);
|
||||
|
||||
TEST (1, [d(2)], Init (), false);
|
||||
TEST (1, [d(2)], Init ({}), false);
|
||||
TEST (1, [d(2)], Init ({1}), false);
|
||||
TEST (1, [d(2)], Init ({1, 2}), false);
|
||||
TEST (1, [d(2)], Init ({1, 2, 3}), true);
|
||||
|
||||
#if TEST_NEAR_VLA_MAX_SIZE
|
||||
// Very large but not erroneous one dimensional VLAs.
|
||||
TEST (1, [d(MAX)], Init (), false);
|
||||
TEST (1, [d(MAX)], Init ({}), false);
|
||||
TEST (1, [d(MAX)], Init ({1}), false);
|
||||
TEST (1, [d(MAX)], Init ({1, 2}), false);
|
||||
TEST (1, [d(MAX)], Init ({1, 2, 3}), false);
|
||||
|
||||
TEST ( 2, [d(MAX / 2)], Init (), false);
|
||||
TEST ( 4, [d(MAX / 4)], Init (), false);
|
||||
TEST ( 8, [d(MAX / 8)], Init (), false);
|
||||
TEST (16, [d(MAX / 16)], Init (), false);
|
||||
TEST (32, [d(MAX / 32)], Init (), false);
|
||||
TEST (64, [d(MAX / 64)], Init (), false);
|
||||
#endif // TEST_NEAR_VLA_MAX_SIZE
|
||||
|
||||
// One dimensional VLAs with a negative upper bound.
|
||||
TEST (1, [d(LONG_MIN)], Init (), true);
|
||||
TEST (1, [d(INT_MIN)], Init (), true);
|
||||
TEST (1, [d(-1234)], Init (), true);
|
||||
TEST (1, [d(-1)], Init (), true);
|
||||
|
||||
// Excessively large one dimensional VLAs.
|
||||
TEST ( 1, [d(MAX + 1)], Init (), true);
|
||||
TEST ( 2, [d(MAX)], Init (), true);
|
||||
TEST ( 4, [d(MAX / 2)], Init (), true);
|
||||
TEST ( 4, [d(MAX / 3)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 2)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 3)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 4)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 5)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 6)], Init (), true);
|
||||
TEST ( 8, [d(MAX / 7)], Init (), true);
|
||||
TEST (16, [d(MAX / 15)], Init (), true);
|
||||
TEST (32, [d(MAX / 31)], Init (), true);
|
||||
TEST (64, [d(MAX / 63)], Init (), true);
|
||||
TEST ( 1, [d(SIZE_MAX)], Init (), true);
|
||||
|
||||
TEST (1, [d(LONG_MIN)], Init ({}), true);
|
||||
TEST (1, [d(INT_MIN)], Init ({}), true);
|
||||
TEST (1, [d(-1)], Init ({}), true);
|
||||
|
||||
TEST (1, [d(SIZE_MAX)], Init ({}), true);
|
||||
|
||||
TEST (1, [d(LONG_MIN)], Init ({0}), true);
|
||||
TEST (1, [d(INT_MIN)], Init ({0}), true);
|
||||
TEST (1, [d(-1)], Init ({0}), true);
|
||||
|
||||
TEST (1, [d(SIZE_MAX)], Init ({0}), true);
|
||||
|
||||
TEST ( 1, [d(SIZE_MAX/2) + 1], Init (), true);
|
||||
TEST ( 2, [d(SIZE_MAX/4) + 1], Init (), true);
|
||||
TEST ( 4, [d(SIZE_MAX/8) + 1], Init (), true);
|
||||
TEST ( 8, [d(SIZE_MAX/16) + 1], Init (), true);
|
||||
TEST (16, [d(SIZE_MAX/32) + 1], Init (), true);
|
||||
|
||||
TEST ( 1, [d(SIZE_MAX/2) + 1], Init ({1}), true);
|
||||
TEST ( 2, [d(SIZE_MAX/4) + 1], Init ({1, 2}), true);
|
||||
TEST ( 4, [d(SIZE_MAX/8) + 1], Init ({1, 2, 3}), true);
|
||||
TEST ( 8, [d(SIZE_MAX/16) + 1], Init ({1, 2, 3, 4}), true);
|
||||
TEST (16, [d(SIZE_MAX/32) + 1], Init ({1, 2, 3, 4, 5}), true);
|
||||
|
||||
// Two dimensional VLAs with one constant bound.
|
||||
|
||||
TEST (1, [1][d(0)], Init (), true);
|
||||
|
||||
#if !BUG_58646
|
||||
// The following causes an ICE due to c++/58646.
|
||||
TEST (1, [1][d(0)], Init ({}), true);
|
||||
#endif
|
||||
TEST (1, [ ][d(0)], Init ({{1}}), true); // unspecified bound
|
||||
TEST (1, [1][d(0)], Init ({{1}}), true);
|
||||
|
||||
TEST (1, [1][d(1)], Init (), false);
|
||||
TEST (1, [1][d(1)], Init ({{1}}), false);
|
||||
TEST (1, [1][d(1)], Init ({{1, 2}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1, 2}}), true);
|
||||
|
||||
TEST (1, [1][d(2)], Init (), false);
|
||||
TEST (1, [1][d(2)], Init ({{1}}), false);
|
||||
TEST (1, [1][d(2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [ ][d(2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [1][d(2)], Init ({{1, 2, 3}}), true);
|
||||
TEST (1, [ ][d(2)], Init ({{1, 2, 3}}), true);
|
||||
|
||||
TEST (1, [2][d(1)], Init (), false);
|
||||
TEST (1, [2][d(1)], Init ({{1}}), false);
|
||||
TEST (1, [ ][d(1)], Init ({{1}}), false);
|
||||
TEST (1, [2][d(1)], Init ({{1}, {2}}), false);
|
||||
TEST (1, [ ][d(1)], Init ({{1}, {2}}), false);
|
||||
TEST (1, [2][d(1)], Init ({{1, 2}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1, 2}}), true);
|
||||
TEST (1, [2][d(1)], Init ({{1}, {2, 3}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1}, {2, 3}}), true);
|
||||
TEST (1, [2][d(1)], Init ({{1, 2, 3}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1, 2, 3}}), true);
|
||||
TEST (1, [2][d(1)], Init ({{1, 2, 3}, {4}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1, 2, 3}, {4}}), true);
|
||||
TEST (1, [2][d(1)], Init ({{1, 2}, {3, 4}}), true);
|
||||
TEST (1, [ ][d(1)], Init ({{1, 2}, {3, 4}}), true);
|
||||
|
||||
TEST (1, [2][d(2)], Init (), false);
|
||||
TEST (1, [2][d(2)], Init ({{1}}), false);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [2][d(2)], Init ({{1}, {2, 3, 4}}), true);
|
||||
TEST (1, [2][d(2)], Init ({{1}, {2, 3, 4, 5}}), true);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2}, {3, 4, 5}}), true);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2, 3}, {4, 5}}), true);
|
||||
TEST (1, [2][d(2)], Init ({{1, 2, 3}, {4, 5, 6}}), true);
|
||||
|
||||
TEST (1, [2][d(3)], Init (), false);
|
||||
TEST (1, [2][d(3)], Init ({{1}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1}, {2, 3, 4}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1}, {2, 3, 4, 5}}), true);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2}, {3, 4, 5}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5, 6, 7}}), true);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3, 4}, {5, 6, 7}}), true);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5}, {6, 7}}), true);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5, 6}, {7}}), true);
|
||||
TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5, 6, 7}}), true);
|
||||
|
||||
#if TEST_NEAR_VLA_MAX_SIZE
|
||||
TEST (1, [1][d(MAX)], Init (), false);
|
||||
# if !BUG_58646
|
||||
// The following causes an ICE due to c++/58646.
|
||||
TEST (1, [1][d(MAX)], Init ({}), false);
|
||||
# endif
|
||||
TEST (1, [1][d(MAX)], Init ({{1}}), false);
|
||||
TEST (1, [1][d(MAX)], Init ({{1, 2}}), false);
|
||||
TEST (1, [1][d(MAX)], Init ({{1, 2, 3}}), false);
|
||||
TEST (1, [1][d(MAX)], Init ({{1, 2, 3, 4}}), false);
|
||||
|
||||
TEST (1, [2][d(MAX / 2)], Init (), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3, 4}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1}, {2}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1}, {2, 3}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5}}), false);
|
||||
TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
|
||||
#endif // TEST_NEAR_VLA_MAX_SIZE
|
||||
|
||||
// Excessively large two dimensional VLAs.
|
||||
TEST (1, [1][d(LONG_MIN)], Init (), true);
|
||||
TEST (1, [1][d(INT_MIN)], Init (), true);
|
||||
TEST (1, [1][d(-1)], Init (), true);
|
||||
|
||||
TEST (1, [1][d(SIZE_MAX)], Init (), true);
|
||||
|
||||
#if !BUG_58646
|
||||
// The following cause an ICE due to c++/58646.
|
||||
TEST (1, [1][d(LONG_MIN)], Init ({}), true);
|
||||
TEST (1, [1][d(INT_MIN)], Init ({}), true);
|
||||
TEST (1, [1][d(-1)], Init ({}), true);
|
||||
TEST (1, [1][d(SIZE_MAX)], Init ({}), true);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][d(LONG_MIN)], Init ({{0}}), true);
|
||||
TEST (1, [1][d(INT_MIN)], Init ({{0}}), true);
|
||||
TEST (1, [1][d(-1)], Init ({{0}}), true);
|
||||
TEST (1, [1][d(SIZE_MAX)], Init ({{0}}), true);
|
||||
|
||||
TEST (1, [d(LONG_MIN)][1], Init (), true);
|
||||
TEST (1, [d(INT_MIN)][1], Init (), true);
|
||||
TEST (1, [d(-1)][1], Init (), true);
|
||||
TEST (1, [d(SIZE_MAX)][1], Init (), true);
|
||||
|
||||
TEST (1, [d(LONG_MIN)][1], Init ({}), true);
|
||||
TEST (1, [d(INT_MIN)][1], Init ({}), true);
|
||||
TEST (1, [d(-1)][1], Init ({}), true);
|
||||
TEST (1, [d(SIZE_MAX)][1], Init ({}), true);
|
||||
|
||||
TEST (1, [d(LONG_MIN)][1], Init ({{0}}), true);
|
||||
TEST (1, [d(INT_MIN)][1], Init ({{0}}), true);
|
||||
TEST (1, [d(-1)][1], Init ({{0}}), true);
|
||||
TEST (1, [d(SIZE_MAX)][1], Init ({{0}}), true);
|
||||
|
||||
// Two dimensional VLAs with no constant bound.
|
||||
TEST (1, [d(0)][d(0)], Init (), true);
|
||||
TEST (1, [d(0)][d(0)], Init ({}), true);
|
||||
#if !BUG_58646
|
||||
// The following cause an ICE due to c++/58646.
|
||||
TEST (1, [d(0)][d(0)], Init ({{}}), true);
|
||||
TEST (1, [d(0)][d(0)], Init ({{}, {}}), true);
|
||||
#endif
|
||||
|
||||
TEST (1, [d(0)][d(0)], Init ({{1}}), true);
|
||||
TEST (1, [d(0)][d(0)], Init ({{1, 2}}), true);
|
||||
#if !BUG_58646
|
||||
TEST (1, [d(0)][d(0)], Init ({{1}, {}}), true);
|
||||
TEST (1, [d(0)][d(0)], Init ({{}, {1}}), true);
|
||||
#endif
|
||||
|
||||
TEST (1, [d(1)][d(0)], Init (), true);
|
||||
TEST (1, [d(1)][d(0)], Init ({}), true);
|
||||
TEST (1, [d(1)][d(0)], Init ({{1}}), true);
|
||||
|
||||
TEST (1, [d(1)][d(1)], Init (), false);
|
||||
TEST (1, [d(1)][d(1)], Init ({{1}}), false);
|
||||
TEST (1, [d(1)][d(1)], Init ({{1, 2}}), true);
|
||||
|
||||
TEST (1, [d(1)][d(2)], Init (), false);
|
||||
TEST (1, [d(1)][d(2)], Init ({{1}}), false);
|
||||
TEST (1, [d(1)][d(2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [d(1)][d(2)], Init ({{1, 2, 3}}), true);
|
||||
|
||||
TEST (1, [d(2)][d(1)], Init (), false);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1}}), false);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1}, {2}}), false);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1, 2}}), true);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1}, {2, 3}}), true);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1, 2, 3}}), true);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1, 2, 3}, {4}}), true);
|
||||
TEST (1, [d(2)][d(1)], Init ({{1, 2}, {3, 4}}), true);
|
||||
|
||||
TEST (1, [d(2)][d(2)], Init (), false);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1}}), false);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1}, {2, 3, 4}}), true);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1}, {2, 3, 4, 5}}), true);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3, 4, 5}}), true);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2, 3}, {4, 5}}), true);
|
||||
TEST (1, [d(2)][d(2)], Init ({{1, 2, 3}, {4, 5, 6}}), true);
|
||||
|
||||
TEST (1, [d(2)][d(3)], Init (), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1}, {2, 3, 4}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1}, {2, 3, 4, 5}}), true);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3, 4, 5}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5, 6, 7}}), true);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4}, {5, 6, 7}}), true);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5}, {6, 7}}), true);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5, 6}, {7}}), true);
|
||||
TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5, 6, 7}}), true);
|
||||
|
||||
#if TEST_NEAR_VLA_MAX_SIZE
|
||||
TEST (1, [d(1)][d(MAX)], Init (), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7, 8}}), false);
|
||||
TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7, 8, 9}}), false);
|
||||
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init (), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7, 8}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7, 8, 9}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1}, {2}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1}, {2, 3}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}, {3}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}, {3, 4}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5}}), false);
|
||||
TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [d(2)][d(MAX)], Init (), true);
|
||||
TEST (1, [d(2)][d(MAX)], Init ({{1}}), true);
|
||||
TEST (1, [d(MAX)][d(MAX)], Init ({{1, 2}}), true);
|
||||
TEST (1, [d(0)][d(MAX)], Init ({{1}, {2}}), true);
|
||||
TEST (1, [d(INT_MAX)][d(MAX)], Init ({{1}, {2, 3}}), true);
|
||||
TEST (1, [d(SIZE_MAX)][d(MAX)], Init ({{1, 2}, {3, 4}, {5}}), true);
|
||||
|
||||
// Erroneous two-dimensional VLAs with size exceeding SIZE_MAX / 2
|
||||
// (those must be rejected because no object can be bigger than that,
|
||||
// otherwise pointer arithmetic breaks).
|
||||
TEST ( 1, [2][d(SIZE_MAX/2)], Init (), true);
|
||||
TEST ( 2, [2][d(SIZE_MAX/4)], Init (), true);
|
||||
TEST ( 4, [2][d(SIZE_MAX/8)], Init (), true);
|
||||
TEST ( 8, [2][d(SIZE_MAX/16)], Init (), true);
|
||||
TEST (16, [2][d(SIZE_MAX/32)], Init (), true);
|
||||
|
||||
TEST ( 1, [d(SIZE_MAX/2)][2], Init (), true);
|
||||
TEST ( 2, [d(SIZE_MAX/4)][2], Init (), true);
|
||||
TEST ( 4, [d(SIZE_MAX/8)][2], Init (), true);
|
||||
TEST ( 8, [d(SIZE_MAX/16)][2], Init (), true);
|
||||
TEST (16, [d(SIZE_MAX/32)][2], Init (), true);
|
||||
|
||||
// Verify that the unspecified bound is factored into the computation
|
||||
// of the total size.
|
||||
TEST ( 1, [][d(SIZE_MAX/2)], Init ({{1}, {2}}), true);
|
||||
TEST ( 2, [][d(SIZE_MAX/4)], Init ({{1}, {2}}), true);
|
||||
TEST ( 4, [][d(SIZE_MAX/8)], Init ({{1}, {2}}), true);
|
||||
TEST ( 8, [][d(SIZE_MAX/16)], Init ({{1}, {2}}), true);
|
||||
TEST (16, [][d(SIZE_MAX/32)], Init ({{1}, {2}}), true);
|
||||
TEST (16, [][d(SIZE_MAX/64)], Init ({{1}, {2}, {3}}), true);
|
||||
|
||||
// Three dimensional VLAs with two constant bounds.
|
||||
|
||||
TEST (1, [1][1][d(-1)], Init (), true);
|
||||
TEST (1, [1][1][d(0)], Init (), true);
|
||||
|
||||
#if !BUG_58646
|
||||
// The following causes an ICE due to c++/58646.
|
||||
TEST (1, [1][1][d(0)], Init ({}), true);
|
||||
TEST (1, [1][1][d(-1)], Init ({{}}), true);
|
||||
TEST (1, [1][d(-1)][1], Init ({{}}), true);
|
||||
TEST (1, [d(-1)][1][1], Init ({{}}), true);
|
||||
|
||||
TEST (1, [1][1][d(0)], Init ({{}}), true);
|
||||
TEST (1, [1][d(0)][1], Init ({{}}), true);
|
||||
TEST (1, [d(0)][1][1], Init ({{}}), true);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][1][d(1)], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [1][1][d(1)], Init ({{}}), false);
|
||||
TEST (1, [1][1][d(1)], Init ({{{}}}), false);
|
||||
TEST (1, [1][1][d(1)], Init ({{{1}}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][1][d(1)], Init ({{{1, 2}}}), true);
|
||||
TEST (1, [1][1][d(1)], Init ({{{1, 2, 3}}}), true);
|
||||
|
||||
TEST (1, [1][d(1)][1], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [1][d(1)][1], Init ({{}}), false);
|
||||
TEST (1, [1][d(1)][1], Init ({{{}}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][d(1)][1], Init ({{{1}}}), false);
|
||||
TEST (1, [1][d(1)][1], Init ({{{1}, {2}}}), true);
|
||||
TEST (1, [1][d(1)][1], Init ({{{1}, {2}, {3}}}), true);
|
||||
|
||||
TEST (1, [d(1)][1][1], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [d(1)][1][1], Init ({{}}), false);
|
||||
TEST (1, [d(1)][1][1], Init ({{{}}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [d(1)][1][1], Init ({{{1}}}), false);
|
||||
TEST (1, [d(1)][1][1], Init ({{{1}}, {{2}}}), true);
|
||||
TEST (1, [d(1)][1][1], Init ({{{1}}, {{2}}, {{3}}}), true);
|
||||
|
||||
TEST (1, [1][1][d(2)], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [1][1][d(2)], Init ({{}}), false);
|
||||
TEST (1, [1][1][d(2)], Init ({{{}}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][1][d(2)], Init ({{{1}}}), false);
|
||||
TEST (1, [1][1][d(2)], Init ({{{1, 2}}}), false);
|
||||
TEST (1, [1][1][d(2)], Init ({{{1, 2, 3}}}), true);
|
||||
|
||||
TEST (1, [1][d(2)][1], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [1][d(2)][1], Init ({{}}), false);
|
||||
TEST (1, [1][d(2)][1], Init ({{{}}}), false);
|
||||
#endif
|
||||
TEST (1, [1][d(2)][1], Init ({{{1}}}), false);
|
||||
TEST (1, [1][d(2)][1], Init ({{{1}, {2}}}), false);
|
||||
TEST (1, [1][d(2)][1], Init ({{{1}, {2}, {3}}}), true);
|
||||
|
||||
TEST (1, [d(2)][1][1], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [d(2)][1][1], Init ({{}}), false);
|
||||
TEST (1, [d(2)][1][1], Init ({{{}}}), false);
|
||||
#endif
|
||||
TEST (1, [d(2)][1][1], Init ({{{1}}}), false);
|
||||
TEST (1, [d(2)][1][1], Init ({{{1}}, {{2}}}), false);
|
||||
TEST (1, [d(2)][1][1], Init ({{{1}}, {{2}}, {{3}}}), true);
|
||||
|
||||
TEST (1, [1][2][d(2)], Init (), false);
|
||||
|
||||
#if !BUG_58646
|
||||
TEST (1, [1][2][d(2)], Init ({{}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{}}}), false);
|
||||
#endif
|
||||
|
||||
TEST (1, [1][2][d(2)], Init ({{{1}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}}}), true);
|
||||
|
||||
TEST (1, [1][2][d(2)], Init ({{{1}, {2}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1}, {2, 3}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2}, {3}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}, {}}}), true);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}}}), true);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
|
||||
TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
|
||||
|
||||
TEST (1, [2][2][d(2)], Init ({{{1}, {2}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1}, {2, 3}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7}}}), false);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
|
||||
|
||||
TEST (1, [2][2][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8, 9}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4, 5}}, {{6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1}, {2}}, {{3}, {4, 5, 6}}}), true);
|
||||
TEST (1, [2][2][d(2)], Init ({{{1}}, {{2}, {3, 4, 5, 6}}}), true);
|
||||
|
||||
// Three dimensional VLAs with one constant bound.
|
||||
TEST (1, [2][d(-1)][d(-1)], Init (), true);
|
||||
TEST (1, [2][d(-1)][d(0)], Init (), true);
|
||||
TEST (1, [2][d(0)][d(-1)], Init (), true);
|
||||
TEST (1, [2][d(1)][d(-1)], Init (), true);
|
||||
TEST (1, [2][d(1)][d(0)], Init (), true);
|
||||
TEST (1, [2][d(-1)][d(1)], Init (), true);
|
||||
TEST (1, [2][d(0)][d(1)], Init (), true);
|
||||
|
||||
TEST (1, [2][d(2)][d(2)], Init (), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}, {4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8, 9}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4, 5}}, {{6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}}, {{3}, {4, 5, 6}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}}, {{2}, {3, 4, 5, 6}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}, {3}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}, {4}}}), true);
|
||||
TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}, {5}}}), true);
|
||||
|
||||
#if TEST_NEAR_VLA_MAX_SIZE
|
||||
// Very large but not erroneous three-dimensional VLAs.
|
||||
TEST ( 1, [2][d(1)][d(MAX/2)], Init (), false);
|
||||
TEST ( 2, [2][d(1)][d(MAX/4)], Init (), false);
|
||||
TEST ( 4, [2][d(1)][d(MAX/8)], Init (), false);
|
||||
TEST ( 8, [2][d(1)][d(MAX/16)], Init (), false);
|
||||
TEST (16, [2][d(1)][d(MAX/32)], Init (), false);
|
||||
|
||||
TEST ( 1, [2][d(MAX/2)][d(1)], Init (), false);
|
||||
TEST ( 2, [2][d(MAX/4)][d(1)], Init (), false);
|
||||
TEST ( 4, [2][d(MAX/8)][d(1)], Init (), false);
|
||||
TEST ( 8, [2][d(MAX/16)][d(1)], Init (), false);
|
||||
TEST (16, [2][d(MAX/32)][d(1)], Init (), false);
|
||||
|
||||
TEST ( 1, [d(MAX/2)][2][d(1)], Init (), false);
|
||||
TEST ( 2, [d(MAX/4)][2][d(1)], Init (), false);
|
||||
TEST ( 4, [d(MAX/8)][2][d(1)], Init (), false);
|
||||
TEST ( 8, [d(MAX/16)][2][d(1)], Init (), false);
|
||||
TEST (16, [d(MAX/32)][2][d(1)], Init (), false);
|
||||
#endif // TEST_NEAR_VLA_MAX_SIZE
|
||||
|
||||
// Erroneous three-dimensional VLAs with size exceeding SIZE_MAX / 2
|
||||
// (those must be rejected because no object can be bigger than that,
|
||||
// otherwise pointer arithmetic breaks).
|
||||
TEST ( 1, [2][d(1)][d(SIZE_MAX/2)], Init (), true);
|
||||
TEST ( 2, [2][d(1)][d(SIZE_MAX/4)], Init (), true);
|
||||
TEST ( 4, [2][d(1)][d(SIZE_MAX/8)], Init (), true);
|
||||
TEST ( 8, [2][d(1)][d(SIZE_MAX/16)], Init (), true);
|
||||
TEST (16, [2][d(1)][d(SIZE_MAX/32)], Init (), true);
|
||||
|
||||
TEST ( 1, [2][d(SIZE_MAX/2)][d(1)], Init (), true);
|
||||
TEST ( 2, [2][d(SIZE_MAX/4)][d(1)], Init (), true);
|
||||
TEST ( 4, [2][d(SIZE_MAX/8)][d(1)], Init (), true);
|
||||
TEST ( 8, [2][d(SIZE_MAX/16)][d(1)], Init (), true);
|
||||
TEST (16, [2][d(SIZE_MAX/32)][d(1)], Init (), true);
|
||||
|
||||
TEST ( 1, [d(SIZE_MAX/2)][2][d(1)], Init (), true);
|
||||
TEST ( 2, [d(SIZE_MAX/4)][2][d(1)], Init (), true);
|
||||
TEST ( 4, [d(SIZE_MAX/8)][2][d(1)], Init (), true);
|
||||
TEST ( 8, [d(SIZE_MAX/16)][2][d(1)], Init (), true);
|
||||
TEST (16, [d(SIZE_MAX/32)][2][d(1)], Init (), true);
|
||||
|
||||
TEST (16, [3][d(SIZE_MAX)][d(SIZE_MAX)], Init (), true);
|
||||
TEST (32, [d(SIZE_MAX)][5][d(SIZE_MAX)], Init (), true);
|
||||
TEST (64, [d(SIZE_MAX)][d(SIZE_MAX)][7], Init (), true);
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (fail)
|
||||
__builtin_abort ();
|
||||
}
|
99
gcc/testsuite/g++.dg/cpp1y/vla12.C
Normal file
99
gcc/testsuite/g++.dg/cpp1y/vla12.C
Normal file
|
@ -0,0 +1,99 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
260
gcc/testsuite/g++.dg/cpp1y/vla13.C
Normal file
260
gcc/testsuite/g++.dg/cpp1y/vla13.C
Normal file
|
@ -0,0 +1,260 @@
|
|||
// 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 ();
|
||||
}
|
48
gcc/testsuite/g++.dg/cpp1y/vla14.C
Normal file
48
gcc/testsuite/g++.dg/cpp1y/vla14.C
Normal file
|
@ -0,0 +1,48 @@
|
|||
// 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;
|
||||
}
|
43
gcc/testsuite/g++.dg/cpp1y/vla3.C
Normal file
43
gcc/testsuite/g++.dg/cpp1y/vla3.C
Normal file
|
@ -0,0 +1,43 @@
|
|||
// 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 ();
|
||||
}
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
void foo(int i)
|
||||
{
|
||||
int x[][i] = { 0 };
|
||||
int x[][i] = { { 0 } };
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// { dg-do run }
|
||||
// { dg-options "-Wno-vla -fsanitize=undefined" }
|
||||
// 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-output "index 1 out of bounds" }
|
||||
|
||||
void f(int i) {
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2016-04-13 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/69517
|
||||
* testsuite/25_algorithms/rotate/moveable2.cc: Make sure VLA
|
||||
upper bound is positive.
|
||||
|
||||
2016-04-13 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/c++config (_GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES,
|
||||
|
|
|
@ -44,7 +44,8 @@ template<typename Con>
|
|||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
rvalstruct array[length];
|
||||
/* Make sure the VLA upper bound is positive. */
|
||||
rvalstruct array[length + 1];
|
||||
for(int i = 0; i < length; ++i)
|
||||
array[i] = i;
|
||||
Con con(array, array + length);
|
||||
|
|
Loading…
Add table
Reference in a new issue