c++: reject class lvalues in 'rvalue'
authorJason Merrill <jason@redhat.com>
Wed, 5 May 2021 01:33:33 +0000 (21:33 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 7 May 2021 16:10:07 +0000 (12:10 -0400)
Wrapping a class lvalue in NON_LVALUE_EXPR is not sufficient to make it a
usable prvalue; callers must use force_rvalue instead.

gcc/cp/ChangeLog:

* tree.c (rvalue): Assert expr is not a class lvalue.

gcc/cp/tree.c

index 4ccd7a3..7f148b4 100644 (file)
@@ -940,7 +940,12 @@ rvalue (tree expr)
   /* We need to do this for rvalue refs as well to get the right answer
      from decltype; see c++/36628.  */
   if (!processing_template_decl && glvalue_p (expr))
-    expr = build1 (NON_LVALUE_EXPR, type, expr);
+    {
+      /* But don't use this function for class lvalues; use move (to treat an
+        lvalue as an xvalue) or force_rvalue (to make a prvalue copy).  */
+      gcc_checking_assert (!CLASS_TYPE_P (type));
+      expr = build1 (NON_LVALUE_EXPR, type, expr);
+    }
   else if (type != TREE_TYPE (expr))
     expr = build_nop (type, expr);