+2021-04-07  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * valops.c (value_cast): Call value_deeply_equal before performing
+       any cast.
+
 2021-04-07  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdbtypes.c (types_equal): Move pointer equality check earlier in
 
+2021-04-07  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * 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  <andrew.burgess@embecosm.com>
 
        * gdb.dwarf2/fission-relative-dwo.c: New file.
 
   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 <int> (var_f);
+}
+
 struct OtherParent
 {
   OtherParent (int other_id0) : other_id (other_id0) { }
   return mf1 (std::move (C));
 }
 
+/* These are used from within GDB.  */
+int global_int = 7;
+float global_float = 3.5f;
+
 int
 main ()
 {
 
   mf2 (std::move (MQ));                        /* Set breakpoint MQ here.  */
 
+  (void) f3 (-1);
+  (void) f4 (3.5);
+
   return 0;
 }
 
 gdb_start_again "marker1 here" $t
 gdb_test "print f1(static_cast<Child&&>(Q))" ".* = 40.*" $t
 
+gdb_test "print f3(static_cast<int&&> (global_int))" " = 8"
+gdb_test "print f4(static_cast<float&&> (global_float))" " = 3"
+
+gdb_test "print static_cast<int&> (global_int)" " = \\(int &\\) @$hex: 7"
+gdb_test "print static_cast<int&&> (global_int)" " = \\(int &&\\) @$hex: 7"
+
+gdb_test "print static_cast<float&> (global_float)" " = \\(float &\\) @$hex: 3\\.$decimal"
+gdb_test "print static_cast<float&&> (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<Child&&>(Q))" ".* = 40.*" $t
 
 
   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);