diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ada-lang.c | 17 | ||||
-rw-r--r-- | gdb/dwarf2/expr.c | 4 | ||||
-rw-r--r-- | gdb/unittests/array-view-selftests.c | 104 | ||||
-rw-r--r-- | gdb/valarith.c | 49 | ||||
-rw-r--r-- | gdb/valops.c | 35 | ||||
-rw-r--r-- | gdb/value.c | 22 |
6 files changed, 169 insertions, 62 deletions
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index b84e10f..c6cefe9 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2586,9 +2586,7 @@ ada_value_assign (struct value *toval, struct value *fromval) write_memory_with_notification (to_addr, buffer, len); val = value_copy (toval); - memcpy (value_contents_raw (val).data (), - value_contents (fromval).data (), - TYPE_LENGTH (type)); + copy (value_contents (fromval), value_contents_raw (val)); deprecated_set_value_type (val, type); return val; @@ -4184,9 +4182,7 @@ ada_convert_actual (struct value *actual, struct type *formal_type0) actual_type = ada_check_typedef (value_type (actual)); val = allocate_value (actual_type); - memcpy ((char *) value_contents_raw (val).data (), - (char *) value_contents (actual).data (), - TYPE_LENGTH (actual_type)); + copy (value_contents (actual), value_contents_raw (val)); actual = ensure_lval (val); } result = value_addr (actual); @@ -8898,7 +8894,6 @@ ada_promote_array_of_integrals (struct type *type, struct value *val) { struct type *elt_type = TYPE_TARGET_TYPE (type); LONGEST lo, hi; - struct value *res; LONGEST i; /* Verify that both val and type are arrays of scalars, and @@ -8914,16 +8909,16 @@ ada_promote_array_of_integrals (struct type *type, struct value *val) if (!get_array_bounds (type, &lo, &hi)) error (_("unable to determine array bounds")); - res = allocate_value (type); + value *res = allocate_value (type); + gdb::array_view<gdb_byte> res_contents = value_contents_writeable (res); /* Promote each array element. */ for (i = 0; i < hi - lo + 1; i++) { struct value *elt = value_cast (elt_type, value_subscript (val, lo + i)); + int elt_len = TYPE_LENGTH (elt_type); - memcpy ((value_contents_writeable (res).data () - + (i * TYPE_LENGTH (elt_type))), - value_contents_all (elt).data (), TYPE_LENGTH (elt_type)); + copy (value_contents_all (elt), res_contents.slice (elt_len * i, elt_len)); } return res; diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 6521619..592dbe1 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -1037,8 +1037,8 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type, if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG) subobj_offset += n - max; - memcpy (value_contents_raw (retval).data (), - value_contents_all (val).data () + subobj_offset, len); + copy (value_contents_all (val).slice (subobj_offset, len), + value_contents_raw (retval)); } break; diff --git a/gdb/unittests/array-view-selftests.c b/gdb/unittests/array-view-selftests.c index 9df48db..998bd3a 100644 --- a/gdb/unittests/array-view-selftests.c +++ b/gdb/unittests/array-view-selftests.c @@ -546,6 +546,108 @@ run_tests () } } +template <typename T> +void +run_copy_test () +{ + /* Test non-overlapping copy. */ + { + const std::vector<T> src_v = {1, 2, 3, 4}; + std::vector<T> dest_v (4, -1); + + SELF_CHECK (dest_v != src_v); + copy (gdb::array_view<const T> (src_v), gdb::array_view<T> (dest_v)); + SELF_CHECK (dest_v == src_v); + } + + /* Test overlapping copy, where the source is before the destination. */ + { + std::vector<T> vec = {1, 2, 3, 4, 5, 6, 7, 8}; + gdb::array_view<T> v = vec; + + copy (v.slice (1, 4), + v.slice (2, 4)); + + std::vector<T> expected = {1, 2, 2, 3, 4, 5, 7, 8}; + SELF_CHECK (vec == expected); + } + + /* Test overlapping copy, where the source is after the destination. */ + { + std::vector<T> vec = {1, 2, 3, 4, 5, 6, 7, 8}; + gdb::array_view<T> v = vec; + + copy (v.slice (2, 4), + v.slice (1, 4)); + + std::vector<T> expected = {1, 3, 4, 5, 6, 6, 7, 8}; + SELF_CHECK (vec == expected); + } + + /* Test overlapping copy, where the source is the same as the destination. */ + { + std::vector<T> vec = {1, 2, 3, 4, 5, 6, 7, 8}; + gdb::array_view<T> v = vec; + + copy (v.slice (2, 4), + v.slice (2, 4)); + + std::vector<T> expected = {1, 2, 3, 4, 5, 6, 7, 8}; + SELF_CHECK (vec == expected); + } +} + +/* Class with a non-trivial copy assignment operator, used to test the + array_view copy function. */ +struct foo +{ + /* Can be implicitly constructed from an int, such that we can use the same + templated test function to test against array_view<int> and + array_view<foo>. */ + foo (int n) + : n (n) + {} + + /* Needed to avoid -Wdeprecated-copy-with-user-provided-copy error with + Clang. */ + foo (const foo &other) = default; + + void operator= (const foo &other) + { + this->n = other.n; + this->n_assign_op_called++; + } + + bool operator==(const foo &other) const + { + return this->n == other.n; + } + + int n; + + /* Number of times the assignment operator has been called. */ + static int n_assign_op_called; +}; + +int foo::n_assign_op_called = 0; + +/* Test the array_view copy free function. */ + +static void +run_copy_tests () +{ + /* Test with a trivial type. */ + run_copy_test<int> (); + + /* Test with a non-trivial type. */ + foo::n_assign_op_called = 0; + run_copy_test<foo> (); + + /* Make sure that for the non-trivial type foo, the assignment operator was + called an amount of times that makes sense. */ + SELF_CHECK (foo::n_assign_op_called == 12); +} + } /* namespace array_view_tests */ } /* namespace selftests */ @@ -555,4 +657,6 @@ _initialize_array_view_selftests () { selftests::register_test ("array_view", selftests::array_view_tests::run_tests); + selftests::register_test ("array_view-copy", + selftests::array_view_tests::run_copy_tests); } diff --git a/gdb/valarith.c b/gdb/valarith.c index 11acec6..32898f9 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1537,7 +1537,7 @@ value_vector_widen (struct value *scalar_value, struct type *vector_type) { /* Widen the scalar to a vector. */ struct type *eltype, *scalar_type; - struct value *val, *elval; + struct value *elval; LONGEST low_bound, high_bound; int i; @@ -1560,11 +1560,14 @@ value_vector_widen (struct value *scalar_value, struct type *vector_type) && !value_equal (elval, scalar_value)) error (_("conversion of scalar to vector involves truncation")); - val = allocate_value (vector_type); + value *val = allocate_value (vector_type); + gdb::array_view<gdb_byte> val_contents = value_contents_writeable (val); + int elt_len = TYPE_LENGTH (eltype); + for (i = 0; i < high_bound - low_bound + 1; i++) /* Duplicate the contents of elval into the destination vector. */ - memcpy (value_contents_writeable (val).data () + (i * TYPE_LENGTH (eltype)), - value_contents_all (elval).data (), TYPE_LENGTH (eltype)); + copy (value_contents_all (elval), + val_contents.slice (i * elt_len, elt_len)); return val; } @@ -1575,7 +1578,6 @@ value_vector_widen (struct value *scalar_value, struct type *vector_type) static struct value * vector_binop (struct value *val1, struct value *val2, enum exp_opcode op) { - struct value *val, *tmp, *mark; struct type *type1, *type2, *eltype1, *eltype2; int t1_is_vec, t2_is_vec, elsize, i; LONGEST low_bound1, high_bound1, low_bound2, high_bound2; @@ -1605,15 +1607,15 @@ vector_binop (struct value *val1, struct value *val2, enum exp_opcode op) || low_bound1 != low_bound2 || high_bound1 != high_bound2) error (_("Cannot perform operation on vectors with different types")); - val = allocate_value (type1); - mark = value_mark (); + value *val = allocate_value (type1); + gdb::array_view<gdb_byte> val_contents = value_contents_writeable (val); + value *mark = value_mark (); for (i = 0; i < high_bound1 - low_bound1 + 1; i++) { - tmp = value_binop (value_subscript (val1, i), - value_subscript (val2, i), op); - memcpy (value_contents_writeable (val).data () + i * elsize, - value_contents_all (tmp).data (), - elsize); + value *tmp = value_binop (value_subscript (val1, i), + value_subscript (val2, i), op); + copy (value_contents_all (tmp), + val_contents.slice (i * elsize, elsize)); } value_free_to_mark (mark); @@ -1894,7 +1896,7 @@ value_neg (struct value *arg1) return value_binop (value_zero (type, not_lval), arg1, BINOP_SUB); else if (type->code () == TYPE_CODE_ARRAY && type->is_vector ()) { - struct value *tmp, *val = allocate_value (type); + struct value *val = allocate_value (type); struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); int i; LONGEST low_bound, high_bound; @@ -1902,12 +1904,14 @@ value_neg (struct value *arg1) if (!get_array_bounds (type, &low_bound, &high_bound)) error (_("Could not determine the vector bounds")); + gdb::array_view<gdb_byte> val_contents = value_contents_writeable (val); + int elt_len = TYPE_LENGTH (eltype); + for (i = 0; i < high_bound - low_bound + 1; i++) { - tmp = value_neg (value_subscript (arg1, i)); - memcpy ((value_contents_writeable (val).data () - + i * TYPE_LENGTH (eltype)), - value_contents_all (tmp).data (), TYPE_LENGTH (eltype)); + value *tmp = value_neg (value_subscript (arg1, i)); + copy (value_contents_all (tmp), + val_contents.slice (i * elt_len, elt_len)); } return val; } @@ -1937,7 +1941,6 @@ value_complement (struct value *arg1) val = value_from_longest (type, ~value_as_long (arg1)); else if (type->code () == TYPE_CODE_ARRAY && type->is_vector ()) { - struct value *tmp; struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); int i; LONGEST low_bound, high_bound; @@ -1946,12 +1949,14 @@ value_complement (struct value *arg1) error (_("Could not determine the vector bounds")); val = allocate_value (type); + gdb::array_view<gdb_byte> val_contents = value_contents_writeable (val); + int elt_len = TYPE_LENGTH (eltype); + for (i = 0; i < high_bound - low_bound + 1; i++) { - tmp = value_complement (value_subscript (arg1, i)); - memcpy ((value_contents_writeable (val).data () - + i * TYPE_LENGTH (eltype)), - value_contents_all (tmp).data (), TYPE_LENGTH (eltype)); + value *tmp = value_complement (value_subscript (arg1, i)); + copy (value_contents_all (tmp), + val_contents.slice (i * elt_len, elt_len)); } } else if (type->code () == TYPE_CODE_COMPLEX) diff --git a/gdb/valops.c b/gdb/valops.c index c552e82..ca71c12 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -954,18 +954,19 @@ value_one (struct type *type) struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type1)); int i; LONGEST low_bound, high_bound; - struct value *tmp; if (!get_array_bounds (type1, &low_bound, &high_bound)) error (_("Could not determine the vector bounds")); val = allocate_value (type); + gdb::array_view<gdb_byte> val_contents = value_contents_writeable (val); + int elt_len = TYPE_LENGTH (eltype); + for (i = 0; i < high_bound - low_bound + 1; i++) { - tmp = value_one (eltype); - memcpy ((value_contents_writeable (val).data () - + i * TYPE_LENGTH (eltype)), - value_contents_all (tmp).data (), TYPE_LENGTH (eltype)); + value *tmp = value_one (eltype); + copy (value_contents_all (tmp), + val_contents.slice (i * elt_len, elt_len)); } } else @@ -1342,8 +1343,7 @@ value_assign (struct value *toval, struct value *fromval) implies the returned value is not lazy, even if TOVAL was. */ val = value_copy (toval); set_value_lazy (val, 0); - memcpy (value_contents_raw (val).data (), value_contents (fromval).data (), - TYPE_LENGTH (type)); + copy (value_contents (fromval), value_contents_raw (val)); /* We copy over the enclosing type and pointed-to offset from FROMVAL in the case of pointer types. For object types, the enclosing type @@ -4058,10 +4058,13 @@ value_literal_complex (struct value *arg1, arg1 = value_cast (real_type, arg1); arg2 = value_cast (real_type, arg2); - memcpy (value_contents_raw (val).data (), - value_contents (arg1).data (), TYPE_LENGTH (real_type)); - memcpy (value_contents_raw (val).data () + TYPE_LENGTH (real_type), - value_contents (arg2).data (), TYPE_LENGTH (real_type)); + int len = TYPE_LENGTH (real_type); + + copy (value_contents (arg1), + value_contents_raw (val).slice (0, len)); + copy (value_contents (arg2), + value_contents_raw (val).slice (len, len)); + return val; } @@ -4102,12 +4105,12 @@ cast_into_complex (struct type *type, struct value *val) struct type *val_real_type = TYPE_TARGET_TYPE (value_type (val)); struct value *re_val = allocate_value (val_real_type); struct value *im_val = allocate_value (val_real_type); + int len = TYPE_LENGTH (val_real_type); - memcpy (value_contents_raw (re_val).data (), - value_contents (val).data (), TYPE_LENGTH (val_real_type)); - memcpy (value_contents_raw (im_val).data (), - value_contents (val).data () + TYPE_LENGTH (val_real_type), - TYPE_LENGTH (val_real_type)); + copy (value_contents (val).slice (0, len), + value_contents_raw (re_val)); + copy (value_contents (val).slice (len, len), + value_contents_raw (im_val)); return value_literal_complex (re_val, im_val, type); } diff --git a/gdb/value.c b/gdb/value.c index 7649b02..4e66329 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1344,9 +1344,13 @@ value_contents_copy_raw (struct value *dst, LONGEST dst_offset, TARGET_CHAR_BIT * length)); /* Copy the data. */ - memcpy (value_contents_all_raw (dst).data () + dst_offset * unit_size, - value_contents_all_raw (src).data () + src_offset * unit_size, - length * unit_size); + gdb::array_view<gdb_byte> dst_contents + = value_contents_all_raw (dst).slice (dst_offset * unit_size, + length * unit_size); + gdb::array_view<const gdb_byte> src_contents + = value_contents_all_raw (src).slice (src_offset * unit_size, + length * unit_size); + copy (src_contents, dst_contents); /* Copy the meta-data, adjusted. */ src_bit_offset = src_offset * unit_size * HOST_CHAR_BIT; @@ -1721,13 +1725,11 @@ value_copy (struct value *arg) val->stack = arg->stack; val->is_zero = arg->is_zero; val->initialized = arg->initialized; + if (!value_lazy (val)) - { - memcpy (value_contents_all_raw (val).data (), - value_contents_all_raw (arg).data (), - TYPE_LENGTH (value_enclosing_type (arg))); + copy (value_contents_all_raw (arg), + value_contents_all_raw (val)); - } val->unavailable = arg->unavailable; val->optimized_out = arg->optimized_out; val->parent = arg->parent; @@ -1772,9 +1774,7 @@ value_non_lval (struct value *arg) struct type *enc_type = value_enclosing_type (arg); struct value *val = allocate_value (enc_type); - memcpy (value_contents_all_raw (val).data (), - value_contents_all (arg).data (), - TYPE_LENGTH (enc_type)); + copy (value_contents_all (arg), value_contents_all_raw (val)); val->type = arg->type; set_value_embedded_offset (val, value_embedded_offset (arg)); set_value_pointed_to_offset (val, value_pointed_to_offset (arg)); |