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
This commit is contained in:
Jason Merrill 2014-10-09 14:05:17 -04:00 committed by Jason Merrill
parent 94c4084cf0
commit 96e780c087
5 changed files with 59 additions and 4 deletions

View 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.

View 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. */

View 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;
}
}

View 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.

View File

@ -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>();