Re: [PATCH] Vector to scalar casting and widening

Andrew Burgess
2013-01-08T15:08:39Z

Ulrich,

On 07/01/2013 4:23 PM, Ulrich Weigand wrote:
> Andrew Burgess wrote:
>
>> In addressing the two problems you pointed out above, I first created a
>> new function opencl_value_cast, which I use throughout opencl-lang.c,
>> however, a quick grep of the codebase shows other places that call
>> value_cast, for example, within the varobj.c code. I suspect that
>> creating an opencl_value_cast function will mean that I am introducing
>> bugs when, for example, we create varobj objects for opencl code.
>>
>> The first issue you pointed out above "vector <binop> scalar" seems even
>> harder to fix. The current problem with my patch is that I call
>> value_vector_widen from value_binop, which will error if the scalar
>> value is truncated when casting to the vector type. For OpenCL this is
>> the wrong thing to do. I don't want to add an "if (language == opencl)"
>> switch to value_binop, and value_binop is called extensively throughout
>> the codebase. This would suggest then that it is value_vector_widen
>> that should change, however, this feels very much like the original
>> patch to which you objected.
>>
>> So, to summarise the problem as I see it, your suggested solution was to
>> filter the different behaviours within opencl-lang.c, however, the
>> problem behaviours live within value_cast and value_binop, both of which
>> I believe are called from core gdb code, not just from opencl-lang.c, I
>> therefore believe there's no reliable way to intercept all calls to
>> these functions.
>
> I don't actually think you need (or even *should*) intercept all such
> calls. Taking a step back, the underlying problem is that GDB supports
> operating on expressions in various different languages that all have
> their own special rules on how to perform certain operations, but maps
> them all to a single GDB "value" type, with a single set of operations
> on them.
>
> My understanding of how this is supposed to work out is that GDB
> "value" operations *do not* actually implement the precise semantics
> of any of the languages GDB supports; rather, they implement a GDB
> private semantics of "GDB value" objects. Now, as those are private
> to GDB, we are free to implement them however we wish; for pragmatic
> and historical reasons, they do mostly (but not completely!) match
> C semantics.
>
> When evaluating language expressions, the eval* routines are free
> to use value_* operations directly **when their semantics match the
> language semantics**, but must use a different implementation when
> the language requires special semantics. (Note how e.g. the particular
> C type promotions rules for binary operations are *not* implemented
> in value_binop, but are handled specially in the C expression
> evaluation code.)
>
> [ For historical reasons, some of the value_* operations currently
> change aspects of their behaviour depending on current_language.
> This is really a bug, and we ought to (and slowly do) move away
> from this. For example, in a program employing multiple languages
> simultaneously, GDB value objects might have been created from
> values in a different language than the "current" one. ]
>
> Now, as you point out, value_* operations are also used throughout
> the rest of GDB (not part of expression evaluation). This is fine,
> as long as those parts **do not assume they follow any particular
> language semantics, but rather the generic GDB value semantics**.
>
> In general, I think this is in fact the case. For example, the
> value_cast uses in varobj.c you mention appear to only rely on
> common properties of the GDB value semantics (casting C++ objects
> between base and derived types). If there are indeed instances
> of value_ operations that assume specific C (or OpenCL) semantics,
> those would have to be fixed. [ In particular for OpenCL, I'm
> quite sure that no-one outside of opencl-lang.c relies on any
> particular OpenCL semantics of the value_ operations. ]

Thanks for taking the time to explain this all for me, apologies
for not catching on sooner.

I have a new patch which I believe should be closer to what we want,
I'd be grateful if you could test the opencl parts of this again and
let me know how it gets on. Also any other feedback is of course
welcome too.

Thanks,
Andrew

gdb/ChangeLog

2013-01-08 Andrew Burgess <aburgess@broadcom.com>

* valarith.c (value_vector_widen): New function for replicating a
scalar into a vector.
(vector_binop): No longer static.
(value_binop): Use value_vector_widen to widen scalar to vector
rather than casting, this better matches gcc C behaviour.
* valops.c (value_casst): Update logic for casting between vector
types, and for casting from scalar to vector, try to match gcc C
behaviour.
* value.h (value_vector_widen, vector_binop): Declare.
* opencl-lang.c (opencl_value_cast): New opencl specific casting
function, handle special case for casting scalar to vector.
(opencl_binop): Wrapper used for most biary operations, handles
special scalar to vector casting behaviour.
(opencl_relop): Use opencl_value_cast.
(evaluate_subexp_opencl): Use opencl_value_cast instead of
value_cast, and handle the UNOP_CAST case, calling
opencl_value_cast. Use opencl_binop for all binary operations
that might result in a scalar to vector cast.

diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 01e02c8..896d33c 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -683,6 +683,91 @@ vector_relop (struct expression *exp, struct value *val1, struct value *val2,
return ret;
}

+/* Perform a cast of ARG into TYPE. There's sadly a lot of duplication in
+ here from valops.c:value_cast, opencl is different only in the
+ behaviour of scalar to vector casting. As far as possibly we're going
+ to try and delegate back to the standard value_cast function. */
+
+static struct value *
+opencl_value_cast (struct type *type, struct value *arg)
+{
+ if (type != value_type (arg))
+ {
+ /* Casting scalar to vector is a special case for OpenCL, scalar
+ is cast to element type of vector then replicated into each
+ element of the vector. First though, we need to work out if
+ this is a scalar to vector cast; code lifted from
+ valops.c:value_cast. */
+ enum type_code code1, code2;
+ struct type *to_type;
+ int scalar;
+
+ to_type = check_typedef (type);
+
+ code1 = TYPE_CODE (to_type);
+ code2 = TYPE_CODE (check_typedef (value_type (arg)));
+
+ if (code2 == TYPE_CODE_REF)
+ code2 = TYPE_CODE (check_typedef (value_type (coerce_ref (arg))));
+
+ scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL
+ || code2 == TYPE_CODE_CHAR || code2 == TYPE_CODE_FLT
+ || code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM
+ || code2 == TYPE_CODE_RANGE);
+
+ if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (to_type) && scalar)
+ {
+ struct type *eltype;
+
+ /* Cast to the element type of the vector here as
+ value_vector_widen will error if the scalar value is
+ truncated by the cast. To avoid the error, cast (and
+ possibly truncate) here. */
+ eltype = check_typedef (TYPE_TARGET_TYPE (to_type));
+ arg = value_cast (eltype, arg);
+
+ return value_vector_widen (arg, type);
+ }
+ else
+ /* Standard cast handler. */
+ arg = value_cast (type, arg);
+ }
+ return arg;
+}
+
+/* Perform a binary operation on two operands. */
+static struct value *
+opencl_binop (struct value *arg1, struct value *arg2,
+ enum exp_opcode op)
+{
+ struct value *val;
+ struct type *type1 = check_typedef (value_type (arg1));
+ struct type *type2 = check_typedef (value_type (arg2));
+ int t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type1));
+ int t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type2));
+
+ if (!t1_is_vec && !t2_is_vec)
+ val = value_binop (arg1, arg2, op);
+ else if (t1_is_vec && t2_is_vec)
+ val = vector_binop (arg1, arg2, op);
+ else
+ {
+ /* Widen the scalar operand to a vector. */
+ struct value **v = t1_is_vec ? &arg2 : &arg1;
+ struct type *t = t1_is_vec ? type2 : type1;
+
+ if (TYPE_CODE (t) != TYPE_CODE_FLT && !is_integral_type (t))
+ error (_("Argument to operation not a number or boolean."));
+
+ *v = opencl_value_cast (t1_is_vec ? type1 : type2, *v);
+ val = vector_binop (arg1, arg2, op);
+ }
+
+ return val;
+}
+
/* Perform a relational operation on two operands. */

static struct value *
@@ -718,7 +803,7 @@ opencl_relop (struct expression *exp, struct value *arg1, struct value *arg2,
if (TYPE_CODE (t) != TYPE_CODE_FLT && !is_integral_type (t))
error (_("Argument to operation not a number or boolean."));

- *v = value_cast (t1_is_vec ? type1 : type2, *v);
+ *v = opencl_value_cast (t1_is_vec ? type1 : type2, *v);
val = vector_relop (exp, arg1, arg2, op);
}

@@ -769,6 +854,16 @@ evaluate_subexp_opencl (struct type *expect_type, struct expression *exp,

return opencl_logical_not (exp, arg1);

+ case UNOP_CAST:
+ type1 = exp->elts[*pos + 1].type;
+ (*pos) += 2;
+ arg1 = evaluate_subexp (type1, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ return value_from_longest (builtin_type (exp->gdbarch)->
+ builtin_int, 1);
+ arg1 = opencl_value_cast (type1, arg1);
+ return arg1;
+
/* Handle the logical operator and(&&) and or(||). */
case BINOP_LOGICAL_AND:
case BINOP_LOGICAL_OR:
@@ -852,12 +947,12 @@ evaluate_subexp_opencl (struct type *expect_type, struct expression *exp,
/* Widen the scalar operand to a vector if necessary. */
if (t2_is_vec || !t3_is_vec)
{
- arg3 = value_cast (type2, arg3);
+ arg3 = opencl_value_cast (type2, arg3);
type3 = value_type (arg3);
}
else if (!t2_is_vec || t3_is_vec)
{
- arg2 = value_cast (type3, arg2);
+ arg2 = opencl_value_cast (type3, arg2);
type2 = value_type (arg2);
}
else if (!t2_is_vec || !t3_is_vec)
@@ -954,6 +1049,31 @@ Cannot perform conditional operation on vectors with different sizes"));
"structure");
}
}
+
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_INTDIV:
+ case BINOP_REM:
+ case BINOP_MOD:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ {
+ (*pos)++;
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
+
+ if (noside == EVAL_SKIP)
+ return value_from_longest (builtin_type (exp->gdbarch)->
+ builtin_int, 1);
+
+ return opencl_binop (arg1, arg2, op);
+ }
+
default:
break;
}
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 074cf36..f813ede 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -1346,10 +1346,53 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
return val;
}

+/* Widen a scalar value SCALAR_VALUE to vector type VECTOR_TYPE by
+ replicating SCALAR_VALUE for each element of the vector. Only scalar
+ types that can be cast to the type of one element of the vector are
+ acceptable. The newly created vector value is returned upon success,
+ otherwise an error is thrown. */
+
+struct value *
+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;
+ LONGEST low_bound, high_bound;
+ int i;
+
+ CHECK_TYPEDEF (vector_type);
+
+ gdb_assert (TYPE_CODE (vector_type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (vector_type));
+
+ if (!get_array_bounds (vector_type, &low_bound, &high_bound))
+ error (_("Could not determine the vector bounds"));
+
+ eltype = check_typedef (TYPE_TARGET_TYPE (vector_type));
+ elval = value_cast (eltype, scalar_value);
+
+ scalar_type = check_typedef (value_type (scalar_value));
+
+ /* If we reduced the length of the scalar then check we didn't loose any
+ important bits. */
+ if (TYPE_LENGTH (eltype) < TYPE_LENGTH (scalar_type)
+ && !value_equal (elval, scalar_value))
+ error (_("conversion of scalar to vector involves truncation"));
+
+ val = allocate_value (vector_type);
+ for (i = 0; i < high_bound - low_bound + 1; i++)
+ /* Duplicate the contents of elval into the destination vector. */
+ memcpy (value_contents_writeable (val) + (i * TYPE_LENGTH (eltype)),
+ value_contents_all (elval), TYPE_LENGTH (eltype));
+
+ return val;
+}
+
/* Performs a binary operation on two vector operands by calling scalar_binop
for each pair of vector components. */

-static struct value *
+struct value *
vector_binop (struct value *val1, struct value *val2, enum exp_opcode op)
{
struct value *val, *tmp, *mark;
@@ -1425,7 +1468,9 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
&& !is_integral_type (t))
error (_("Argument to operation not a number or boolean."));

- *v = value_cast (t1_is_vec ? type1 : type2, *v);
+ /* Replicate the scalar value to make a vector value. */
+ *v = value_vector_widen (*v, t1_is_vec ? type1 : type2);
+
val = vector_binop (arg1, arg2, op);
}

diff --git a/gdb/valops.c b/gdb/valops.c
index e3d36a1..b9bc460 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -546,29 +546,13 @@ value_cast (struct type *type, struct value *arg2)
minus one, instead of biasing the normal case. */
return value_from_longest (type, -1);
}
- else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar)
- {
- /* Widen the scalar to a vector. */
- struct type *eltype;
- struct value *val;
- LONGEST low_bound, high_bound;
- int i;
-
- if (!get_array_bounds (type, &low_bound, &high_bound))
- error (_("Could not determine the vector bounds"));
-
- eltype = check_typedef (TYPE_TARGET_TYPE (type));
- arg2 = value_cast (eltype, arg2);
- val = allocate_value (type);
-
- for (i = 0; i < high_bound - low_bound + 1; i++)
- {
- /* Duplicate the contents of arg2 into the destination vector. */
- memcpy (value_contents_writeable (val) + (i * TYPE_LENGTH (eltype)),
- value_contents_all (arg2), TYPE_LENGTH (eltype));
- }
- return val;
- }
+ else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
+ && code2 == TYPE_CODE_ARRAY && TYPE_VECTOR (type2)
+ && TYPE_LENGTH (type) != TYPE_LENGTH (type2))
+ error (_("Cannot convert between vector values of different sizes"));
+ else if (code1 == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && scalar
+ && TYPE_LENGTH (type) != TYPE_LENGTH (type2))
+ error (_("can only cast scalar to vector of same size"));
else if (code1 == TYPE_CODE_VOID)
{
return value_zero (type, not_lval);
diff --git a/gdb/value.h b/gdb/value.h
index 67f1d04..e354e7a 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -482,6 +482,12 @@ extern void read_value_memory (struct value *val, int embedded_offset,
int stack, CORE_ADDR memaddr,
gdb_byte *buffer, size_t length);

+/* Cast SCALAR_VALUE to the element type of VECTOR_TYPE, then replicate
+ into each element of a new vector value with VECTOR_TYPE. */
+
+struct value *value_vector_widen (struct value *scalar_value,
+ struct type *vector_type);
+
\f

#include "symtab.h"
@@ -601,6 +607,9 @@ extern struct value *value_concat (struct value *arg1, struct value *arg2);
extern struct value *value_binop (struct value *arg1, struct value *arg2,
enum exp_opcode op);

+extern struct value *vector_binop (struct value *arg1, struct value *arg2,
+ enum exp_opcode op);
+
extern struct value *value_ptradd (struct value *arg1, LONGEST arg2);

extern LONGEST value_ptrdiff (struct value *arg1, struct value *arg2);

gdb/testsuite/ChangeLog

2013-01-08 Andrew Burgess <aburgess@broadcom.com>

* gdb.base/gnu_vector.c: New variable for use in tests.
* gdb.base/gnu_vector.exp: Update and extend tests to reflect
changes in scalar to vector casting and widening.
* gdb.python/py-type.c: New variables for use in tests.
* gdb.python/py-type.exp: Update vector related tests to reflect
changes in scalar to vector casting and widening.

diff --git a/gdb/testsuite/gdb.base/gnu_vector.c b/gdb/testsuite/gdb.base/gnu_vector.c
index 76eefed..062aadb 100644
--- a/gdb/testsuite/gdb.base/gnu_vector.c
+++ b/gdb/testsuite/gdb.base/gnu_vector.c
@@ -31,6 +31,7 @@ int ia = 2;
int ib = 1;
float fa = 2;
float fb = 1;
+long long lla __attribute__ ((mode(DI))) = 0x0000000100000001ll;
char4 c4 = {1, 2, 3, 4};
int4 i4a = {2, 4, 8, 16};
int4 i4b = {1, 2, 8, 4};
diff --git a/gdb/testsuite/gdb.base/gnu_vector.exp b/gdb/testsuite/gdb.base/gnu_vector.exp
index 5f5b40f..f65627b 100644
--- a/gdb/testsuite/gdb.base/gnu_vector.exp
+++ b/gdb/testsuite/gdb.base/gnu_vector.exp
@@ -82,32 +82,52 @@ gdb_test "print f4a / f4b" "\\\$$decimal = \\{2, 2, 1, 4\\}"
gdb_test "print +f4a" "\\\$$decimal = \\{2, 4, 8, 16\\}"
gdb_test "print -f4a" "\\\$$decimal = \\{-2, -4, -8, -16\\}"

-# Test scalar to vector widening
-gdb_test "print (int2) 1" "\\\$$decimal = \\{1, 1\\}"
-gdb_test "print (longlong2) 2" "\\\$$decimal = \\{2, 2\\}"
-gdb_test "print (float2) 3" "\\\$$decimal = \\{3, 3\\}"
-gdb_test "print (double2) 4" "\\\$$decimal = \\{4, 4\\}"
-gdb_test "print (char4) 12" "\\\$$decimal = \\{12, 12, 12, 12\\}"
-gdb_test "print (uint4) ia" "\\\$$decimal = \\{2, 2, 2, 2\\}"
-gdb_test "print (int4) -3" "\\\$$decimal = \\{-3, -3, -3, -3\\}"
-gdb_test "print (float4) 4" "\\\$$decimal = \\{4, 4, 4, 4\\}"
-
+# When casting to vector the input type must have the same length as
+# the total length of the vector.
+gdb_test "print (char4) 0x01010101" "\\\$$decimal = \\{1, 1, 1, 1\\}"
+gdb_test "print (char4) ia" "\\\$$decimal = \\{2, 0, 0, 0\\}"
+gdb_test "print (int2) lla" "\\\$$decimal = \\{1, 1\\}"
+
+gdb_test "print (int2) 1" "can only cast scalar to vector of same size"
+gdb_test "print (longlong2) 2" "can only cast scalar to vector of same size"
+gdb_test "print (float2) 3" "can only cast scalar to vector of same size"
+gdb_test "print (double2) 4" "can only cast scalar to vector of same size"
+gdb_test "print (uint4) ia" "can only cast scalar to vector of same size"
+gdb_test "print (int4) -3" "can only cast scalar to vector of same size"
+gdb_test "print (float4) 4" "can only cast scalar to vector of same size"
+
+gdb_test "print i4b = ia" "can only cast scalar to vector of same size"
+gdb_test "print i4a = 3" "can only cast scalar to vector of same size"
+gdb_test "print f4a = fb" "can only cast scalar to vector of same size"
+gdb_test "print f4b = 2" "can only cast scalar to vector of same size"
+
+gdb_test "print c4 + lla" "conversion of scalar to vector involves truncation"
+gdb_test "print i4a + lla" "conversion of scalar to vector involves truncation"
+gdb_test "print lla + c4" "conversion of scalar to vector involves truncation"
+gdb_test "print lla + i4a" "conversion of scalar to vector involves truncation"
+
+gdb_test "print c4 + ib" "\\\$$decimal = \\{2, 3, 4, 5\\}"
gdb_test "print i4a + ib" "\\\$$decimal = \\{3, 5, 9, 17\\}"
+gdb_test "print i4a + 1" "\\\$$decimal = \\{3, 5, 9, 17\\}"
+gdb_test "print 1 + i4a" "\\\$$decimal = \\{3, 5, 9, 17\\}"
gdb_test "print fa - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}"
+gdb_test "print 2 - f4b" "\\\$$decimal = \\{1, 0, -6, -2\\}"
gdb_test "print f4a * fb" "\\\$$decimal = \\{2, 4, 8, 16\\}"
+gdb_test "print f4a * 1" "\\\$$decimal = \\{2, 4, 8, 16\\}"
gdb_test "print ia / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}"
+gdb_test "print 2 / i4b" "\\\$$decimal = \\{2, 1, 0, 0\\}"
gdb_test "print i4a % ib" "\\\$$decimal = \\{0, 0, 0, 0\\}"
-
+gdb_test "print i4a % 1" "\\\$$decimal = \\{0, 0, 0, 0\\}"
gdb_test "print ia & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}"
+gdb_test "print 2 & i4b" "\\\$$decimal = \\{0, 2, 0, 0\\}"
gdb_test "print i4a | ib" "\\\$$decimal = \\{3, 5, 9, 17\\}"
+gdb_test "print i4a | 1" "\\\$$decimal = \\{3, 5, 9, 17\\}"
gdb_test "print ia ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}"
+gdb_test "print 2 ^ i4b" "\\\$$decimal = \\{3, 0, 10, 6\\}"
gdb_test "print i4a << ib" "\\\$$decimal = \\{4, 8, 16, 32\\}"
+gdb_test "print i4a << 1" "\\\$$decimal = \\{4, 8, 16, 32\\}"
gdb_test "print i4a >> ib" "\\\$$decimal = \\{1, 2, 4, 8\\}"
-
-gdb_test "print i4b = ia" "\\\$$decimal = \\{2, 2, 2, 2\\}"
-gdb_test "print i4a = 3" "\\\$$decimal = \\{3, 3, 3, 3\\}"
-gdb_test "print f4a = fb" "\\\$$decimal = \\{1, 1, 1, 1\\}"
-gdb_test "print f4b = 2" "\\\$$decimal = \\{2, 2, 2, 2\\}"
+gdb_test "print i4a >> 1" "\\\$$decimal = \\{1, 2, 4, 8\\}"

gdb_test "print i4a = \{2, 4, 8, 16\}" "\\\$$decimal = \\{2, 4, 8, 16\\}"
gdb_test "print i4a <<= ib" "\\\$$decimal = \\{4, 8, 16, 32\\}"
@@ -130,6 +150,10 @@ gdb_test "print i2 + i4a" "Cannot perform operation on vectors with different ty
gdb_test "print f4a + f2" "Cannot perform operation on vectors with different types"
gdb_test "print f2 + f4a" "Cannot perform operation on vectors with different types"

+gdb_test "print (double2) f2" "Cannot convert between vector values of different sizes"
+gdb_test "print (int4) c4" "Cannot convert between vector values of different sizes"
+gdb_test "print (char4) i4a" "Cannot convert between vector values of different sizes"
+
# Test ptype on vector types.
gdb_test "ptype c4" "type = char __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
gdb_test "ptype char4" "type = char __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c
index 641844e..03015a8 100644
--- a/gdb/testsuite/gdb.python/py-type.c
+++ b/gdb/testsuite/gdb.python/py-type.c
@@ -50,6 +50,9 @@ enum E
{ v1, v2, v3
};

+struct s vec_data_1 = {1, 1};
+struct s vec_data_2 = {1, 2};
+
int
main ()
{
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index ec59bc8..16b2de2 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -118,7 +118,7 @@ proc test_fields {lang} {
# Test gdb.Type.array.
gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(1)))" \
".1, 2." "cast to array with one argument"
- gdb_test "python print (ar\[0\].cast(ar\[0\].type.array(0, 1)))" \
+ gdb_test "python print ar\[0\].cast(ar\[0\].type.array(0, 1))" \
".1, 2." "cast to array with two arguments"

gdb_test "python print (ar\[0\].type == ar\[0\].type)" "True"
@@ -126,16 +126,19 @@ proc test_fields {lang} {
# Test gdb.Type.vector.
# Note: vectors cast differently than arrays. Here ar[0] is replicated
# for the size of the vector.
- gdb_py_test_silent_cmd \
- "python vec1 = ar\[0\].cast(ar\[0\].type.vector(1))" "set vec1" 1
- gdb_test "python print (vec1)" ".1, 1." "cast to vector with one argument"
- gdb_py_test_silent_cmd \
- "python vec2 = ar\[0\].cast(ar\[0\].type.vector(0, 1))" "set vec2" 1
- gdb_test "python print (vec2)" ".1, 1." "cast to vector with two arguments"
- gdb_test "python print (vec1 == vec2)" "True"
- gdb_py_test_silent_cmd \
- "python vec3 = ar\[1\].cast(ar\[1\].type.vector(1))" "set vec3" 1
- gdb_test "python print (vec1 == vec3)" "False"
+ gdb_py_test_silent_cmd "print vec_data_1" "print value (vec_data_1)" 1
+ gdb_py_test_silent_cmd "python vec_data_1 = gdb.history (0)" "get value (vec_data_1) from history" 1
+
+ gdb_py_test_silent_cmd "print vec_data_2" "print value (vec_data_2)" 1
+ gdb_py_test_silent_cmd "python vec_data_2 = gdb.history (0)" "get value (vec_data_2) from history" 1
+
+ gdb_py_test_silent_cmd "python vec1 = vec_data_1.cast(ar\[0\].type.vector(1))" "set vec1" 1
+ gdb_test "python print vec1" ".1, 1." "cast to vector with one argument"
+ gdb_py_test_silent_cmd "python vec2 = vec_data_1.cast(ar\[0\].type.vector(0, 1))" "set vec2" 1
+ gdb_test "python print vec2" ".1, 1." "cast to vector with two arguments"
+ gdb_test "python print vec1 == vec2" "True"
+ gdb_py_test_silent_cmd "python vec3 = vec_data_2.cast(ar\[0\].type.vector(1))" "set vec3" 1
+ gdb_test "python print vec1 == vec3" "False"
}
}