aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl.c28
-rw-r--r--gcc/cp/init.c21
-rw-r--r--gcc/cp/parser.c20
-rw-r--r--gcc/cp/semantics.c54
-rw-r--r--gcc/cp/tree.c15
-rw-r--r--gcc/cp/typeck.c20
-rw-r--r--gcc/cp/typeck2.c6
-rw-r--r--gcc/gimplify.c4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/vla2.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/vla3.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/vla4.C24
-rw-r--r--gcc/testsuite/g++.dg/init/array24.C4
-rw-r--r--libstdc++-v3/ChangeLog10
-rw-r--r--libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver3
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver3
-rw-r--r--libstdc++-v3/libsupc++/Makefile.in17
-rw-r--r--libstdc++-v3/libsupc++/bad_array_length.cc36
-rw-r--r--libstdc++-v3/libsupc++/cxxabi.h2
-rw-r--r--libstdc++-v3/libsupc++/eh_aux_runtime.cc4
-rw-r--r--libstdc++-v3/libsupc++/new17
23 files changed, 331 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e16316537bb..da27792fb3b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,9 @@
2013-05-09 Jason Merrill <jason@redhat.com>
+ N3639 C++1y VLA support
+ * gimplify.c (gimplify_vla_decl): Don't touch an existing
+ DECL_VALUE_EXPR.
+
* tree.c (build_constructor_va): New.
* tree.h: Declare it.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7a1484fa43f..57d6a0a67e3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2013-05-09 Jason Merrill <jason@redhat.com>
+
+ N3639 C++1y VLA support
+ * decl.c (compute_array_index_type): Allow VLAs in C++1y mode.
+ (check_array_initializer): Allow VLA init.
+ (reshape_init_array_1): Adjust.
+ (cp_finish_decl): Check for invalid VLA length.
+ * typeck2.c (process_init_constructor_array): Adjust.
+ (store_init_value): Use build_vec_init for VLAs.
+ * semantics.c (add_capture): Capture VLA as ptr+len.
+ (vla_capture_type): New.
+ (build_capture_proxy): Rebuild the VLA.
+ * typeck.c (build_simple_component_ref): Split out from...
+ (build_ptrmemfunc_access_expr): ...here.
+ * tree.c (array_of_runtime_bound_p): New.
+ * init.c (throw_bad_array_length): New.
+ (build_vec_init): Use it.
+ * parser.c (cp_convert_range_for): When iterating over a VLA,
+ use it directly rather than bind a reference.
+ * cp-tree.h: Declare new functions.
+
2013-05-08 Jason Merrill <jason@redhat.com>
* except.c (is_admissible_throw_operand_or_catch_parameter): Check
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dec73906167..a2f59df9b1a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5358,6 +5358,7 @@ extern tree build_value_init_noctor (tree, tsubst_flags_t);
extern tree build_offset_ref (tree, tree, bool,
tsubst_flags_t);
extern tree throw_bad_array_new_length (void);
+extern tree throw_bad_array_length (void);
extern tree build_new (vec<tree, va_gc> **, tree, tree,
vec<tree, va_gc> **, int,
tsubst_flags_t);
@@ -5849,6 +5850,7 @@ extern tree get_target_expr (tree);
extern tree get_target_expr_sfinae (tree, tsubst_flags_t);
extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int);
+extern bool array_of_runtime_bound_p (tree);
extern tree build_array_copy (tree);
extern tree build_vec_init_expr (tree, tree, tsubst_flags_t);
extern void diagnose_non_constexpr_vec_init (tree);
@@ -6032,6 +6034,7 @@ extern tree cp_build_binary_op (location_t,
enum tree_code, tree, tree,
tsubst_flags_t);
#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
+extern tree build_simple_component_ref (tree, tree);
extern tree build_ptrmemfunc_access_expr (tree, tree);
extern tree build_address (tree);
extern tree build_typed_address (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d6e286184a4..cebd36103b7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5064,7 +5064,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
tsubst_flags_t complain)
{
tree new_init;
- bool sized_array_p = (max_index != NULL_TREE);
+ bool sized_array_p = (max_index && TREE_CONSTANT (max_index));
unsigned HOST_WIDE_INT max_index_cst = 0;
unsigned HOST_WIDE_INT index;
@@ -5514,15 +5514,12 @@ check_array_initializer (tree decl, tree type, tree init)
error ("elements of array %q#T have incomplete type", type);
return true;
}
- /* It is not valid to initialize a VLA. */
- if (init
+ /* A compound literal can't have variable size. */
+ if (init && !decl
&& ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
|| !TREE_CONSTANT (TYPE_SIZE (element_type))))
{
- if (decl)
- error ("variable-sized object %qD may not be initialized", decl);
- else
- error ("variable-sized compound literal");
+ error ("variable-sized compound literal");
return true;
}
return false;
@@ -6405,6 +6402,21 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
error ("non-static data member %qD has Java class type", decl);
+ if (array_of_runtime_bound_p (type))
+ {
+ /* If the VLA bound is larger than half the address space, or less
+ than zero, throw std::bad_array_length. */
+ tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
+ /* C++1y says we should throw for length <= 0, but we have
+ historically supported zero-length arrays. Let's treat that as an
+ extension to be disabled by -std=c++NN. */
+ int lower = flag_iso ? 0 : -1;
+ tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower));
+ comp = build3 (COND_EXPR, void_type_node, comp,
+ throw_bad_array_length (), void_zero_node);
+ finish_expr_stmt (comp);
+ }
+
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_EXPR for a
reference temp is added before the DECL_EXPR for the reference itself. */
@@ -8289,7 +8301,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
error ("size of array is not an integral constant-expression");
size = integer_one_node;
}
- else if (pedantic && warn_vla != 0)
+ else if (cxx_dialect < cxx1y && pedantic && warn_vla != 0)
{
if (name)
pedwarn (input_location, OPT_Wvla, "ISO C++ forbids variable length array %qD", name);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 765c47192cf..d687a8428ce 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2185,6 +2185,20 @@ throw_bad_array_new_length (void)
return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
}
+/* Call __cxa_bad_array_length to indicate that there were too many
+ initializers. */
+
+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);
+}
+
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
@@ -3350,6 +3364,10 @@ build_vec_init (tree base, tree maxindex, tree init,
store_constructor will handle the semantics for us. */
stmt_expr = build2 (INIT_EXPR, atype, base, init);
+ if (length_check)
+ stmt_expr = build3 (COND_EXPR, atype, length_check,
+ throw_bad_array_length (),
+ stmt_expr);
return stmt_expr;
}
@@ -3467,6 +3485,9 @@ build_vec_init (tree base, tree maxindex, tree init,
if (length_check)
{
tree throw_call;
+ if (array_of_runtime_bound_p (atype))
+ throw_call = throw_bad_array_length ();
+ else
throw_call = throw_bad_array_new_length ();
length_check = build3 (COND_EXPR, void_type_node, length_check,
throw_call, void_zero_node);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8d3f6c70fff..f65ec970654 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9842,13 +9842,21 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
begin_expr = end_expr = iter_type = error_mark_node;
else
{
- tree range_temp = build_range_temp (range_expr);
- pushdecl (range_temp);
- cp_finish_decl (range_temp, range_expr,
- /*is_constant_init*/false, NULL_TREE,
- LOOKUP_ONLYCONVERTING);
+ tree range_temp;
- range_temp = convert_from_reference (range_temp);
+ if (TREE_CODE (range_expr) == VAR_DECL
+ && array_of_runtime_bound_p (TREE_TYPE (range_expr)))
+ /* Can't bind a reference to an array of runtime bound. */
+ range_temp = range_expr;
+ else
+ {
+ range_temp = build_range_temp (range_expr);
+ pushdecl (range_temp);
+ cp_finish_decl (range_temp, range_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ range_temp = convert_from_reference (range_temp);
+ }
iter_type = cp_parser_perform_range_for_lookup (range_temp,
&begin_expr, &end_expr);
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2165649313d..591750315eb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9379,6 +9379,21 @@ build_capture_proxy (tree member)
name = DECL_NAME (member);
type = lambda_proxy_type (object);
+
+ if (TREE_CODE (type) == RECORD_TYPE
+ && TYPE_NAME (type) == NULL_TREE)
+ {
+ /* Rebuild the VLA type from the pointer and maxindex. */
+ tree field = next_initializable_field (TYPE_FIELDS (type));
+ tree ptr = build_simple_component_ref (object, field);
+ field = next_initializable_field (DECL_CHAIN (field));
+ tree max = build_simple_component_ref (object, field);
+ type = build_array_type (TREE_TYPE (TREE_TYPE (ptr)),
+ build_index_type (max));
+ object = convert (build_reference_type (type), ptr);
+ object = convert_from_reference (object);
+ }
+
var = build_decl (input_location, VAR_DECL, name, type);
SET_DECL_VALUE_EXPR (var, object);
DECL_HAS_VALUE_EXPR_P (var) = 1;
@@ -9400,6 +9415,28 @@ build_capture_proxy (tree member)
return var;
}
+/* Return a struct containing a pointer and a length for lambda capture of
+ an array of runtime length. */
+
+static tree
+vla_capture_type (tree array_type)
+{
+ static tree ptr_id, max_id;
+ if (!ptr_id)
+ {
+ ptr_id = get_identifier ("ptr");
+ max_id = get_identifier ("max");
+ }
+ tree ptrtype = build_pointer_type (TREE_TYPE (array_type));
+ tree field1 = build_decl (input_location, FIELD_DECL, ptr_id, ptrtype);
+ tree field2 = build_decl (input_location, FIELD_DECL, max_id, sizetype);
+ DECL_CHAIN (field2) = field1;
+ tree type = make_node (RECORD_TYPE);
+ finish_builtin_struct (type, "__cap", field2, NULL_TREE);
+ TYPE_NAME (type) = NULL_TREE;
+ return type;
+}
+
/* From an ID and INITIALIZER, create a capture (by reference if
BY_REFERENCE_P is true), add it to the capture-list for LAMBDA,
and return it. */
@@ -9415,7 +9452,22 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
tf_warning_or_error);
type = lambda_capture_field_type (initializer, explicit_init_p);
- if (by_reference_p)
+ if (array_of_runtime_bound_p (type))
+ {
+ /* For a VLA, we capture the address of the first element and the
+ maximum index, and then reconstruct the VLA for the proxy. */
+ gcc_assert (by_reference_p);
+ tree elt = cp_build_array_ref (input_location, initializer,
+ integer_zero_node, tf_warning_or_error);
+ tree ctype = vla_capture_type (type);
+ tree ptr_field = next_initializable_field (TYPE_FIELDS (ctype));
+ tree nelts_field = next_initializable_field (DECL_CHAIN (ptr_field));
+ initializer = build_constructor_va (ctype, 2,
+ ptr_field, build_address (elt),
+ nelts_field, array_type_nelts (type));
+ type = ctype;
+ }
+ else if (by_reference_p)
{
type = build_reference_type (type);
if (!real_lvalue_p (initializer))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 5117319a708..2df2087afb2 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -871,6 +871,21 @@ build_array_of_n_type (tree elt, int n)
return build_cplus_array_type (elt, build_index_type (size_int (n - 1)));
}
+/* True iff T is a C++1y array of runtime bound (VLA). */
+
+bool
+array_of_runtime_bound_p (tree t)
+{
+ if (!t || TREE_CODE (t) != ARRAY_TYPE)
+ return false;
+ tree dom = TYPE_DOMAIN (t);
+ if (!dom)
+ return false;
+ tree max = TYPE_MAX_VALUE (dom);
+ return (!value_dependent_expression_p (max)
+ && !TREE_CONSTANT (max));
+}
+
/* Return a reference type node referring to TO_TYPE. If RVAL is
true, return an rvalue reference type, otherwise return an lvalue
reference type. If a type node exists, reuse it, otherwise create
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 2d9711b96a3..47670f2a5d8 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2788,6 +2788,19 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
return expr;
}
+/* Build a COMPONENT_REF of OBJECT and MEMBER with the appropriate
+ type. */
+
+tree
+build_simple_component_ref (tree object, tree member)
+{
+ tree type = cp_build_qualified_type (TREE_TYPE (member),
+ cp_type_quals (TREE_TYPE (object)));
+ return fold_build3_loc (input_location,
+ COMPONENT_REF, type,
+ object, member, NULL_TREE);
+}
+
/* Return an expression for the MEMBER_NAME field in the internal
representation of PTRMEM, a pointer-to-member function. (Each
pointer-to-member function type gets its own RECORD_TYPE so it is
@@ -2800,7 +2813,6 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
{
tree ptrmem_type;
tree member;
- tree member_type;
/* This code is a stripped down version of
build_class_member_access_expr. It does not work to use that
@@ -2810,11 +2822,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
/*want_type=*/false, tf_warning_or_error);
- member_type = cp_build_qualified_type (TREE_TYPE (member),
- cp_type_quals (ptrmem_type));
- return fold_build3_loc (input_location,
- COMPONENT_REF, member_type,
- ptrmem, member, NULL_TREE);
+ return build_simple_component_ref (ptrmem, member);
}
/* Given an expression PTR for a pointer, return an expression
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index a0bc50b2a5e..e0ebae95723 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -795,10 +795,12 @@ 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)
|| ! reduced_constant_expression_p (value)))
{
if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
+ && (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))
+ || array_of_runtime_bound_p (type)))
/* For an array, we only need/want a single cleanup region rather
than one per element. */
return build_vec_init (decl, NULL_TREE, value, false, 1,
@@ -1114,7 +1116,7 @@ process_init_constructor_array (tree type, tree init,
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree domain = TYPE_DOMAIN (type);
- if (domain)
+ if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
len = (tree_to_double_int (TYPE_MAX_VALUE (domain))
- tree_to_double_int (TYPE_MIN_VALUE (domain))
+ double_int_one)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index fc7bfcf251c..e2ae8932dfa 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1382,6 +1382,10 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
+ /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
+ if (DECL_HAS_VALUE_EXPR_P (decl))
+ return;
+
/* All occurrences of this decl in final gimplified code will be
replaced by indirection. Setting DECL_VALUE_EXPR does two
things: First, it lets the rest of the gimplifier know what
diff --git a/gcc/testsuite/g++.dg/cpp1y/vla2.C b/gcc/testsuite/g++.dg/cpp1y/vla2.C
new file mode 100644
index 00000000000..4cd95d4ef7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/vla2.C
@@ -0,0 +1,15 @@
+// N3639 allows initialization and capture of VLAs
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+void f(int n)
+{
+ int ar[n] = { 42 };
+ auto l = [&] { return ar[0]; };
+ if (l() != 42) __builtin_abort ();
+}
+
+int main()
+{
+ f(1);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/vla3.C b/gcc/testsuite/g++.dg/cpp1y/vla3.C
new file mode 100644
index 00000000000..a016904604b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/vla3.C
@@ -0,0 +1,30 @@
+// Test for throwing bad_array_length on invalid array length
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+#include <new>
+
+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::bad_array_length) { ++ok; }
+ try { g(-24); } // negative
+ catch (std::bad_array_length) { ++ok; }
+
+ if (ok != 2)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/vla4.C b/gcc/testsuite/g++.dg/cpp1y/vla4.C
new file mode 100644
index 00000000000..78b7effd8f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/vla4.C
@@ -0,0 +1,24 @@
+// Test for range-based for with VLAs.
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+#include <new>
+
+void f(int i)
+{
+ int ar[i];
+ int j = 0;
+ for (int& x : ar)
+ x = ++j;
+ [&ar]{
+ int k = 0;
+ for (int x : ar)
+ if (x != ++k)
+ __builtin_abort();
+ }();
+}
+
+int main()
+{
+ f(42); // OK
+}
diff --git a/gcc/testsuite/g++.dg/init/array24.C b/gcc/testsuite/g++.dg/init/array24.C
index ed4c1d881fe..2d72df40382 100644
--- a/gcc/testsuite/g++.dg/init/array24.C
+++ b/gcc/testsuite/g++.dg/init/array24.C
@@ -1,7 +1,7 @@
// PR c++/29175
-// { dg-options "" }
+// { dg-options "-Wno-vla" }
void foo(int i)
{
- int x[][i] = { 0 }; // { dg-error "variable-sized|storage size" }
+ int x[][i] = { 0 };
}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 2d91012d974..9bbb771cf2e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,13 @@
+2013-05-08 Jason Merrill <jason@redhat.com>
+
+ Add std::bad_array_length (N3639)
+ * libsupc++/new: Add std::bad_array_length.
+ * libsupc++/bad_array_length.cc: New.
+ * libsupc++/eh_aux_runtime.cc: Add __cxa_bad_array_length.
+ * libsupc++/Makefile.in: Build them.
+ * config/abi/pre/gnu.ver: Add new symbols.
+ * config/abi/pre/gnu-versioned-namespace.ver: Add new symbols.
+
2013-05-08 Andi Kleen <ak@linux.intel.com>
PR target/55947
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 07feda06454..33a0068e2d7 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -235,6 +235,9 @@ CXXABI_2.0 {
__cxa_throw_bad_array_new_length;
_Z*St20bad_array_new_length*;
+ __cxa_throw_bad_array_length;
+ _Z*St16bad_array_length*;
+
# Default function.
_ZSt11_Hash_bytesPKv*;
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 7256c6f782e..446a68502e3 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1559,6 +1559,9 @@ CXXABI_1.3.7 {
CXXABI_1.3.8 {
__cxa_throw_bad_array_new_length;
_Z*St20bad_array_new_length*;
+
+ __cxa_throw_bad_array_length;
+ _Z*St16bad_array_length*;
} CXXABI_1.3.7;
# Symbols in the support library (libsupc++) supporting transactional memory.
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 9f24fef30eb..6ff4d0ce886 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -92,8 +92,8 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(bitsdir)" \
LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
libsupc___la_LIBADD =
am__objects_1 = array_type_info.lo atexit_arm.lo atexit_thread.lo \
- bad_alloc.lo bad_array_new.lo bad_cast.lo bad_typeid.lo \
- class_type_info.lo \
+ bad_alloc.lo bad_array_length.lo bad_array_new.lo bad_cast.lo \
+ bad_typeid.lo class_type_info.lo \
del_op.lo del_opnt.lo del_opv.lo del_opvnt.lo dyncast.lo \
eh_alloc.lo eh_arm.lo eh_aux_runtime.lo eh_call.lo eh_catch.lo \
eh_exception.lo eh_globals.lo eh_personality.lo eh_ptr.lo \
@@ -367,6 +367,7 @@ sources = \
atexit_arm.cc \
atexit_thread.cc \
bad_alloc.cc \
+ bad_array_length.cc \
bad_array_new.cc \
bad_cast.cc \
bad_typeid.cc \
@@ -789,16 +790,22 @@ cp-demangle.lo: cp-demangle.c
cp-demangle.o: cp-demangle.c
$(C_COMPILE) -DIN_GLIBCPP_V3 -Wno-error -c $<
-# Use special rules for the C++11 sources so that the proper flags are passed.
+# Use special rules for the C++11 and C++1y sources so that the proper
+# flags are passed.
+bad_array_length.lo: bad_array_length.cc
+ $(LTCXXCOMPILE) -std=gnu++1y -c $<
+bad_array_length.o: bad_array_length.cc
+ $(CXXCOMPILE) -std=gnu++1y -c $<
+
bad_array_new.lo: bad_array_new.cc
$(LTCXXCOMPILE) -std=gnu++11 -c $<
bad_array_new.o: bad_array_new.cc
$(CXXCOMPILE) -std=gnu++11 -c $<
eh_aux_runtime.lo: eh_aux_runtime.cc
- $(LTCXXCOMPILE) -std=gnu++11 -c $<
+ $(LTCXXCOMPILE) -std=gnu++1y -c $<
eh_aux_runtime.o: eh_aux_runtime.cc
- $(CXXCOMPILE) -std=gnu++11 -c $<
+ $(CXXCOMPILE) -std=gnu++1y -c $<
eh_ptr.lo: eh_ptr.cc
$(LTCXXCOMPILE) -std=gnu++11 -c $<
diff --git a/libstdc++-v3/libsupc++/bad_array_length.cc b/libstdc++-v3/libsupc++/bad_array_length.cc
new file mode 100644
index 00000000000..a63d660f20b
--- /dev/null
+++ b/libstdc++-v3/libsupc++/bad_array_length.cc
@@ -0,0 +1,36 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <new>
+
+namespace std {
+
+bad_array_length::~bad_array_length() _GLIBCXX_USE_NOEXCEPT { }
+
+const char*
+bad_array_length::what() const _GLIBCXX_USE_NOEXCEPT
+{
+ return "std::bad_array_length";
+}
+
+} // namespace std
diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h
index 83749ce8038..cf2c0602e5f 100644
--- a/libstdc++-v3/libsupc++/cxxabi.h
+++ b/libstdc++-v3/libsupc++/cxxabi.h
@@ -154,6 +154,8 @@ namespace __cxxabiv1
void
__cxa_throw_bad_array_new_length() __attribute__((__noreturn__));
+ void
+ __cxa_throw_bad_array_length() __attribute__((__noreturn__));
/**
* @brief Demangling routine.
diff --git a/libstdc++-v3/libsupc++/eh_aux_runtime.cc b/libstdc++-v3/libsupc++/eh_aux_runtime.cc
index 1cc831b4b9f..806b4798110 100644
--- a/libstdc++-v3/libsupc++/eh_aux_runtime.cc
+++ b/libstdc++-v3/libsupc++/eh_aux_runtime.cc
@@ -40,3 +40,7 @@ __cxxabiv1::__cxa_bad_typeid ()
extern "C" void
__cxxabiv1::__cxa_throw_bad_array_new_length ()
{ _GLIBCXX_THROW_OR_ABORT(std::bad_array_new_length()); }
+
+extern "C" void
+__cxxabiv1::__cxa_throw_bad_array_length ()
+{ _GLIBCXX_THROW_OR_ABORT(std::bad_array_length()); }
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 3087502190e..cdf4cab85b9 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -79,6 +79,23 @@ namespace std
};
#endif
+ // We throw this exception for GNU VLAs of negative length in all C++
+ // dialects, so declare it if we aren't in strict conformance mode.
+#if __cplusplus > 201103L || !defined(__STRICT_ANSI__)
+ class bad_array_length : public bad_alloc
+ {
+ public:
+ bad_array_length() throw() { };
+
+ // This declaration is not useless:
+ // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
+ virtual ~bad_array_length() throw();
+
+ // See comment in eh_exception.cc.
+ virtual const char* what() const throw();
+ };
+#endif
+
struct nothrow_t { };
extern const nothrow_t nothrow;