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> 2014-10-09 Marc Glisse <marc.glisse@inria.fr>
* decl.c (grokdeclarator): constexpr only implies const in C++11. * 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) TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
FNDECL_USED_AUTO (in FUNCTION_DECL) FNDECL_USED_AUTO (in FUNCTION_DECL)
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) 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) AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
@ -3059,11 +3059,12 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define PAREN_STRING_LITERAL_P(NODE) \ #define PAREN_STRING_LITERAL_P(NODE) \
TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE)) TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE))
/* Indicates whether a COMPONENT_REF has been parenthesized. Currently /* Indicates whether a COMPONENT_REF has been parenthesized, or an
only set some of the time in C++14 mode. */ INDIRECT_REF comes from parenthesizing a VAR_DECL. Currently only set
some of the time in C++14 mode. */
#define REF_PARENTHESIZED_P(NODE) \ #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 /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
constructor call, rather than an ordinary function call. */ constructor call, rather than an ordinary function call. */

View File

@ -1637,6 +1637,8 @@ force_paren_expr (tree expr)
bool rval = !!(kind & clk_rvalueref); bool rval = !!(kind & clk_rvalueref);
type = cp_build_reference_type (type, rval); type = cp_build_reference_type (type, rval);
expr = build_static_cast (type, expr, tf_error); 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)) if (VOID_TYPE_P (functype))
return error_mark_node; 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 /* Under C++11 [12.8/32 class.copy], a returned lvalue is sometimes
treated as an rvalue for the purposes of overload resolution to treated as an rvalue for the purposes of overload resolution to
favor move constructors over copy constructors. 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>();