re PR c++/63437 ([C++14] Parenthesized "movable but not copyable" object doesn't...
authorJason Merrill <jason@redhat.com>
Thu, 9 Oct 2014 18:05:17 +0000 (14:05 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 9 Oct 2014 18:05:17 +0000 (14:05 -0400)
PR c++/63437
* cp-tree.h (REF_PARENTHESIZED_P): Also allow INDIRECT_REF.
* semantics.c (force_paren_expr): And set it.
* typeck.c (check_return_expr): And handle it.

From-SVN: r216042

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp1y/paren1.C [new file with mode: 0644]

index ed71ec27ff27d5b006561e7cdf06218d9873c473..744854855c668bb3e3f93f0360abd92f71d0ae0b 100644 (file)
@@ -1,3 +1,10 @@
+2014-10-09  Jason Merrill  <jason@redhat.com>
+
+       PR c++/63437
+       * cp-tree.h (REF_PARENTHESIZED_P): Also allow INDIRECT_REF.
+       * semantics.c (force_paren_expr): And set it.
+       * typeck.c (check_return_expr): And handle it.
+
 2014-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        * decl.c (grokdeclarator): constexpr only implies const in C++11.
index 857af769f2b0b2521743eee3f45ab9fa5aba8c82..cdc892762f71ed1d9e290974d5bd6afb0ed77349 100644 (file)
@@ -101,7 +101,7 @@ c-common.h, not after.
       TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
       FNDECL_USED_AUTO (in FUNCTION_DECL)
       DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
-      REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF)
+      REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF)
       AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
    3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
       ICS_BAD_FLAG (in _CONV)
@@ -3059,11 +3059,12 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #define PAREN_STRING_LITERAL_P(NODE) \
   TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE))
 
-/* Indicates whether a COMPONENT_REF has been parenthesized.  Currently
-   only set some of the time in C++14 mode.  */
+/* Indicates whether a COMPONENT_REF has been parenthesized, or an
+   INDIRECT_REF comes from parenthesizing a VAR_DECL.  Currently only set
+   some of the time in C++14 mode.  */
 
 #define REF_PARENTHESIZED_P(NODE) \
-  TREE_LANG_FLAG_2 (COMPONENT_REF_CHECK (NODE))
+  TREE_LANG_FLAG_2 (TREE_CHECK2 ((NODE), COMPONENT_REF, INDIRECT_REF))
 
 /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
    constructor call, rather than an ordinary function call.  */
index b11ec0905cbf5a6824110683d6c17eb01003b353..ba09e72057340e87201300479de2df6ec6f9256f 100644 (file)
@@ -1637,6 +1637,8 @@ force_paren_expr (tree expr)
          bool rval = !!(kind & clk_rvalueref);
          type = cp_build_reference_type (type, rval);
          expr = build_static_cast (type, expr, tf_error);
+         if (expr != error_mark_node)
+           REF_PARENTHESIZED_P (expr) = true;
        }
     }
 
index 6a357bfca99ed0d96637a3cd6339d4f95a5f2622..b4e6824796b26b2ecb03a9794d221eccaf72e294 100644 (file)
@@ -8671,6 +8671,20 @@ check_return_expr (tree retval, bool *no_warning)
       if (VOID_TYPE_P (functype))
        return error_mark_node;
 
+      /* If we had an id-expression obfuscated by force_paren_expr, we need
+        to undo it so we can try to treat it as an rvalue below.  */
+      if (cxx_dialect >= cxx14
+         && INDIRECT_REF_P (retval)
+         && REF_PARENTHESIZED_P (retval))
+       {
+         retval = TREE_OPERAND (retval, 0);
+         while (TREE_CODE (retval) == NON_LVALUE_EXPR
+                || TREE_CODE (retval) == NOP_EXPR)
+           retval = TREE_OPERAND (retval, 0);
+         gcc_assert (TREE_CODE (retval) == ADDR_EXPR);
+         retval = TREE_OPERAND (retval, 0);
+       }
+
       /* Under C++11 [12.8/32 class.copy], a returned lvalue is sometimes
         treated as an rvalue for the purposes of overload resolution to
         favor move constructors over copy constructors.
diff --git a/gcc/testsuite/g++.dg/cpp1y/paren1.C b/gcc/testsuite/g++.dg/cpp1y/paren1.C
new file mode 100644 (file)
index 0000000..809f251
--- /dev/null
@@ -0,0 +1,31 @@
+// PR c++/63437
+// { dg-do compile { target c++11 } }
+
+struct X // movable but not copyable
+{
+    X() = default;
+    X(X &&) = default;
+
+    X(const X &) = delete;
+};
+
+X non_parenthesized()
+{
+    X x;
+    return x; // works
+}
+
+X parenthesized()
+{
+    X x;
+    return (x); // error: use of deleted function 'X::X(const X&)'
+}
+
+template <class T>
+T parenthesized_t()
+{
+  T t;
+  return (t);
+}
+
+template X parenthesized_t<X>();