diff options
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/decl.c | 28 | ||||
-rw-r--r-- | gcc/cp/init.c | 21 | ||||
-rw-r--r-- | gcc/cp/parser.c | 20 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 54 | ||||
-rw-r--r-- | gcc/cp/tree.c | 15 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 20 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 6 | ||||
-rw-r--r-- | gcc/gimplify.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla2.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla3.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/vla4.C | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array24.C | 4 | ||||
-rw-r--r-- | libstdc++-v3/ChangeLog | 10 | ||||
-rw-r--r-- | libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver | 3 | ||||
-rw-r--r-- | libstdc++-v3/config/abi/pre/gnu.ver | 3 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/Makefile.in | 17 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/bad_array_length.cc | 36 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/cxxabi.h | 2 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_aux_runtime.cc | 4 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/new | 17 |
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; |