Commit df5c89cb by Jason Merrill Committed by Jason Merrill

cp-tree.h (enum cp_lvalue_kind_flags): Add clk_rvalueref.

	* cp-tree.h (enum cp_lvalue_kind_flags): Add clk_rvalueref.
	* tree.c (lvalue_p_1): Return it.  Remove
	treat_class_rvalues_as_lvalues parm.
	(real_lvalue_p): Disallow pseudo-lvalues here.
	(lvalue_or_rvalue_with_address_p): New fn.
	* call.c (initialize_reference): Use it instead of real_lvalue_p.

From-SVN: r149534
parent 25357d1e
2009-07-12 Jason Merrill <jason@redhat.com> 2009-07-12 Jason Merrill <jason@redhat.com>
PR c++/37206
* cp-tree.h (enum cp_lvalue_kind_flags): Add clk_rvalueref.
* tree.c (lvalue_p_1): Return it. Remove
treat_class_rvalues_as_lvalues parm.
(real_lvalue_p): Disallow pseudo-lvalues here.
(lvalue_or_rvalue_with_address_p): New fn.
* call.c (initialize_reference): Use it instead of real_lvalue_p.
PR c++/40689 PR c++/40689
* init.c (build_new_1): Handle initializer list as array initializer. * init.c (build_new_1): Handle initializer list as array initializer.
(build_vec_init): Likewise. (build_vec_init): Likewise.
......
...@@ -7622,7 +7622,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) ...@@ -7622,7 +7622,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
expr = error_mark_node; expr = error_mark_node;
else else
{ {
if (!real_lvalue_p (expr)) if (!lvalue_or_rvalue_with_address_p (expr))
{ {
tree init; tree init;
var = set_up_extended_ref_temp (decl, expr, cleanup, &init); var = set_up_extended_ref_temp (decl, expr, cleanup, &init);
......
...@@ -3509,9 +3509,10 @@ enum tag_types { ...@@ -3509,9 +3509,10 @@ enum tag_types {
enum cp_lvalue_kind_flags { enum cp_lvalue_kind_flags {
clk_none = 0, /* Things that are not an lvalue. */ clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */ clk_ordinary = 1, /* An ordinary lvalue. */
clk_class = 2, /* An rvalue of class-type. */ clk_rvalueref = 2,/* An rvalue formed using an rvalue reference */
clk_bitfield = 4, /* An lvalue for a bit-field. */ clk_class = 4, /* An rvalue of class-type. */
clk_packed = 8 /* An lvalue for a packed field. */ clk_bitfield = 8, /* An lvalue for a bit-field. */
clk_packed = 16 /* An lvalue for a packed field. */
}; };
/* This type is used for parameters and variables which hold /* This type is used for parameters and variables which hold
...@@ -4884,6 +4885,7 @@ extern tree copy_binfo (tree, tree, tree, ...@@ -4884,6 +4885,7 @@ extern tree copy_binfo (tree, tree, tree,
tree *, int); tree *, int);
extern int member_p (const_tree); extern int member_p (const_tree);
extern cp_lvalue_kind real_lvalue_p (tree); extern cp_lvalue_kind real_lvalue_p (tree);
extern bool lvalue_or_rvalue_with_address_p (const_tree);
extern bool builtin_valid_in_constant_expr_p (const_tree); extern bool builtin_valid_in_constant_expr_p (const_tree);
extern tree build_min (enum tree_code, tree, ...); extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...); extern tree build_min_nt (enum tree_code, ...);
......
...@@ -44,7 +44,7 @@ static tree build_cplus_array_type_1 (tree, tree); ...@@ -44,7 +44,7 @@ static tree build_cplus_array_type_1 (tree, tree);
static int list_hash_eq (const void *, const void *); static int list_hash_eq (const void *, const void *);
static hashval_t list_hash_pieces (tree, tree, tree); static hashval_t list_hash_pieces (tree, tree, tree);
static hashval_t list_hash (const void *); static hashval_t list_hash (const void *);
static cp_lvalue_kind lvalue_p_1 (const_tree, int); static cp_lvalue_kind lvalue_p_1 (const_tree);
static tree build_target_expr (tree, tree); static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *); static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *); static tree verify_stmt_tree_r (tree *, int *, void *);
...@@ -55,12 +55,10 @@ static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *); ...@@ -55,12 +55,10 @@ static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is. /* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is Otherwise, returns clk_none. */
nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind static cp_lvalue_kind
lvalue_p_1 (const_tree ref, lvalue_p_1 (const_tree ref)
int treat_class_rvalues_as_lvalues)
{ {
cp_lvalue_kind op1_lvalue_kind = clk_none; cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none; cp_lvalue_kind op2_lvalue_kind = clk_none;
...@@ -72,8 +70,7 @@ lvalue_p_1 (const_tree ref, ...@@ -72,8 +70,7 @@ lvalue_p_1 (const_tree ref,
if (TREE_CODE (ref) == INDIRECT_REF if (TREE_CODE (ref) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
== REFERENCE_TYPE) == REFERENCE_TYPE)
return lvalue_p_1 (TREE_OPERAND (ref, 0), return lvalue_p_1 (TREE_OPERAND (ref, 0));
treat_class_rvalues_as_lvalues);
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{ {
...@@ -82,12 +79,7 @@ lvalue_p_1 (const_tree ref, ...@@ -82,12 +79,7 @@ lvalue_p_1 (const_tree ref,
&& TREE_CODE (ref) != PARM_DECL && TREE_CODE (ref) != PARM_DECL
&& TREE_CODE (ref) != VAR_DECL && TREE_CODE (ref) != VAR_DECL
&& TREE_CODE (ref) != COMPONENT_REF) && TREE_CODE (ref) != COMPONENT_REF)
{ return clk_rvalueref;
if (CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ref))))
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
else
return clk_none;
}
/* lvalue references and named rvalue references are lvalues. */ /* lvalue references and named rvalue references are lvalues. */
return clk_ordinary; return clk_ordinary;
...@@ -108,12 +100,10 @@ lvalue_p_1 (const_tree ref, ...@@ -108,12 +100,10 @@ lvalue_p_1 (const_tree ref,
case WITH_CLEANUP_EXPR: case WITH_CLEANUP_EXPR:
case REALPART_EXPR: case REALPART_EXPR:
case IMAGPART_EXPR: case IMAGPART_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0), return lvalue_p_1 (TREE_OPERAND (ref, 0));
treat_class_rvalues_as_lvalues);
case COMPONENT_REF: case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
treat_class_rvalues_as_lvalues);
/* Look at the member designator. */ /* Look at the member designator. */
if (!op1_lvalue_kind) if (!op1_lvalue_kind)
; ;
...@@ -164,35 +154,28 @@ lvalue_p_1 (const_tree ref, ...@@ -164,35 +154,28 @@ lvalue_p_1 (const_tree ref,
if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0)) if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
|| TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1))) || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
return clk_none; return clk_none;
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
treat_class_rvalues_as_lvalues); op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
break; break;
case COND_EXPR: case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1) op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
? TREE_OPERAND (ref, 1) ? TREE_OPERAND (ref, 1)
: TREE_OPERAND (ref, 0), : TREE_OPERAND (ref, 0));
treat_class_rvalues_as_lvalues); op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues);
break; break;
case MODIFY_EXPR: case MODIFY_EXPR:
return clk_ordinary; return clk_ordinary;
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1), return lvalue_p_1 (TREE_OPERAND (ref, 1));
treat_class_rvalues_as_lvalues);
case TARGET_EXPR: case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none; return clk_class;
case VA_ARG_EXPR: case VA_ARG_EXPR:
return (treat_class_rvalues_as_lvalues return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
&& CLASS_TYPE_P (TREE_TYPE (ref))
? clk_class : clk_none);
case CALL_EXPR: case CALL_EXPR:
/* Any class-valued call would be wrapped in a TARGET_EXPR. */ /* Any class-valued call would be wrapped in a TARGET_EXPR. */
...@@ -209,8 +192,7 @@ lvalue_p_1 (const_tree ref, ...@@ -209,8 +192,7 @@ lvalue_p_1 (const_tree ref,
with a BASELINK. */ with a BASELINK. */
/* This CONST_CAST is okay because BASELINK_FUNCTIONS returns /* This CONST_CAST is okay because BASELINK_FUNCTIONS returns
its argument unmodified and we assign it to a const_tree. */ its argument unmodified and we assign it to a const_tree. */
return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)), return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
treat_class_rvalues_as_lvalues);
case NON_DEPENDENT_EXPR: case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
...@@ -246,18 +228,33 @@ lvalue_p_1 (const_tree ref, ...@@ -246,18 +228,33 @@ lvalue_p_1 (const_tree ref,
cp_lvalue_kind cp_lvalue_kind
real_lvalue_p (tree ref) real_lvalue_p (tree ref)
{ {
return lvalue_p_1 (ref, cp_lvalue_kind kind = lvalue_p_1 (ref);
/*treat_class_rvalues_as_lvalues=*/0); if (kind & (clk_rvalueref|clk_class))
return clk_none;
else
return kind;
} }
/* This differs from real_lvalue_p in that class rvalues are /* This differs from real_lvalue_p in that class rvalues are considered
considered lvalues. */ lvalues. */
bool bool
lvalue_p (const_tree ref) lvalue_p (const_tree ref)
{ {
return return (lvalue_p_1 (ref) != clk_none);
(lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none); }
/* This differs from real_lvalue_p in that rvalues formed by dereferencing
rvalue references are considered rvalues. */
bool
lvalue_or_rvalue_with_address_p (const_tree ref)
{
cp_lvalue_kind kind = lvalue_p_1 (ref);
if (kind & clk_class)
return false;
else
return (kind != clk_none);
} }
/* Test whether DECL is a builtin that may appear in a /* Test whether DECL is a builtin that may appear in a
......
2009-07-12 Jason Merrill <jason@redhat.com> 2009-07-12 Jason Merrill <jason@redhat.com>
PR c++/37206
* g++.dg/cpp0x/rv10.C: New.
2009-07-12 Jason Merrill <jason@redhat.com>
PR c++/40689 PR c++/40689
* g++.dg/cpp0x/initlist20.C: New. * g++.dg/cpp0x/initlist20.C: New.
* g++.dg/cpp0x/initlist21.C: New. * g++.dg/cpp0x/initlist21.C: New.
......
// { dg-options "-std=gnu++0x" }
struct A
{
A() = default;
A(const A&) = delete;
};
A&& f();
void h(A&&);
void g()
{
A&& arr = f();
h(f());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment