diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d8b3313030..072fa09e2c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2021-04-07 Andrew Burgess + + * valops.c (value_cast): Call value_deeply_equal before performing + any cast. + 2021-04-07 Andrew Burgess * gdbtypes.c (types_equal): Move pointer equality check earlier in diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index c9c6063c9d..0a081fc073 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2021-04-07 Andrew Burgess + + * gdb.cp/rvalue-ref-params.cc (f3): New function. + (f4): New function. + (global_int): New global variable. + (global_float): Likeiwse. + (main): Call both new functions. + * gdb.cp/rvalue-ref-params.exp: Add new tests. + 2021-04-07 Andrew Burgess * gdb.dwarf2/fission-relative-dwo.c: New file. diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-params.cc b/gdb/testsuite/gdb.cp/rvalue-ref-params.cc index d38c96cd7a..d6340fa32e 100644 --- a/gdb/testsuite/gdb.cp/rvalue-ref-params.cc +++ b/gdb/testsuite/gdb.cp/rvalue-ref-params.cc @@ -42,6 +42,18 @@ f2 (Child &&C) return f1 (std::move (C)); /* Set breakpoint marker2 here. */ } +int +f3 (int &&var_i) +{ + return var_i + 1; +} + +int +f4 (float &&var_f) +{ + return static_cast (var_f); +} + struct OtherParent { OtherParent (int other_id0) : other_id (other_id0) { } @@ -65,6 +77,10 @@ mf2 (MultiChild &&C) return mf1 (std::move (C)); } +/* These are used from within GDB. */ +int global_int = 7; +float global_float = 3.5f; + int main () { @@ -81,5 +97,8 @@ main () mf2 (std::move (MQ)); /* Set breakpoint MQ here. */ + (void) f3 (-1); + (void) f4 (3.5); + return 0; } diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-params.exp b/gdb/testsuite/gdb.cp/rvalue-ref-params.exp index 53bd065d88..1fd3edb058 100644 --- a/gdb/testsuite/gdb.cp/rvalue-ref-params.exp +++ b/gdb/testsuite/gdb.cp/rvalue-ref-params.exp @@ -40,6 +40,15 @@ set t "print value of f1 on (Child&&) in main" gdb_start_again "marker1 here" $t gdb_test "print f1(static_cast(Q))" ".* = 40.*" $t +gdb_test "print f3(static_cast (global_int))" " = 8" +gdb_test "print f4(static_cast (global_float))" " = 3" + +gdb_test "print static_cast (global_int)" " = \\(int &\\) @$hex: 7" +gdb_test "print static_cast (global_int)" " = \\(int &&\\) @$hex: 7" + +gdb_test "print static_cast (global_float)" " = \\(float &\\) @$hex: 3\\.$decimal" +gdb_test "print static_cast (global_float)" " = \\(float &&\\) @$hex: 3\\.$decimal" + set t "print value of f2 on (Child&&) in main" gdb_start_again "marker1 here" $t gdb_test "print f2(static_cast(Q))" ".* = 40.*" $t diff --git a/gdb/valops.c b/gdb/valops.c index b65401c079..8694c124b5 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -415,8 +415,25 @@ value_cast (struct type *type, struct value *arg2) int convert_to_boolean = 0; - if (value_type (arg2) == type) - return arg2; + /* TYPE might be equal in meaning to the existing type of ARG2, but for + many reasons, might be a different type object (e.g. TYPE might be a + gdbarch owned type, while VALUE_TYPE (ARG2) could be an objfile owned + type). + + In this case we want to preserve the LVAL of ARG2 as this allows the + resulting value to be used in more places. We do this by calling + VALUE_COPY if appropriate. */ + if (types_deeply_equal (value_type (arg2), type)) + { + /* If the types are exactly equal then we can avoid creating a new + value completely. */ + if (value_type (arg2) != type) + { + arg2 = value_copy (arg2); + deprecated_set_value_type (arg2, type); + } + return arg2; + } if (is_fixed_point_type (type)) return value_cast_to_fixed_point (type, arg2);