From 96e780c0873477bb2b9ab34306e4694dad6626aa Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 9 Oct 2014 14:05:17 -0400 Subject: [PATCH] re PR c++/63437 ([C++14] Parenthesized "movable but not copyable" object doesn't compile in return statement) 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 | 7 +++++++ gcc/cp/cp-tree.h | 9 +++++---- gcc/cp/semantics.c | 2 ++ gcc/cp/typeck.c | 14 +++++++++++++ gcc/testsuite/g++.dg/cpp1y/paren1.C | 31 +++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/paren1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ed71ec27ff2..744854855c6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2014-10-09 Jason Merrill + + 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 * decl.c (grokdeclarator): constexpr only implies const in C++11. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 857af769f2b..cdc892762f7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b11ec0905cb..ba09e720573 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; } } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6a357bfca99..b4e6824796b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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 index 00000000000..809f2510099 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/paren1.C @@ -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 +T parenthesized_t() +{ + T t; + return (t); +} + +template X parenthesized_t(); -- 2.30.2