aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-07-12 15:19:15 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-07-12 15:19:15 -0400
commitdf5c89cb75836adc825e218cdb4307364889902e (patch)
treef66df5c05f93e0914a3aa2b839403fc721add63c
parent25357d1ee0ce69a5b1c194e7e1c7b6437c189b01 (diff)
downloadgcc-df5c89cb75836adc825e218cdb4307364889902e.zip
gcc-df5c89cb75836adc825e218cdb4307364889902e.tar.gz
gcc-df5c89cb75836adc825e218cdb4307364889902e.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/tree.c75
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv10.C15
6 files changed, 70 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cff424f..d3fceab 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
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
* init.c (build_new_1): Handle initializer list as array initializer.
(build_vec_init): Likewise.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f0d624e..5edeb3a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7622,7 +7622,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
expr = error_mark_node;
else
{
- if (!real_lvalue_p (expr))
+ if (!lvalue_or_rvalue_with_address_p (expr))
{
tree init;
var = set_up_extended_ref_temp (decl, expr, cleanup, &init);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 24351b4..933da19 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3509,9 +3509,10 @@ enum tag_types {
enum cp_lvalue_kind_flags {
clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */
- clk_class = 2, /* An rvalue of class-type. */
- clk_bitfield = 4, /* An lvalue for a bit-field. */
- clk_packed = 8 /* An lvalue for a packed field. */
+ clk_rvalueref = 2,/* An rvalue formed using an rvalue reference */
+ clk_class = 4, /* An rvalue of class-type. */
+ 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
@@ -4884,6 +4885,7 @@ extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_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 tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 644e53c..6981388 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -44,7 +44,7 @@ static tree build_cplus_array_type_1 (tree, tree);
static int list_hash_eq (const void *, const void *);
static hashval_t list_hash_pieces (tree, tree, tree);
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 count_trees_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 *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
- Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- nonzero, rvalues of class type are considered lvalues. */
+ Otherwise, returns clk_none. */
static cp_lvalue_kind
-lvalue_p_1 (const_tree ref,
- int treat_class_rvalues_as_lvalues)
+lvalue_p_1 (const_tree ref)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -72,8 +70,7 @@ lvalue_p_1 (const_tree ref,
if (TREE_CODE (ref) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
== REFERENCE_TYPE)
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{
@@ -82,12 +79,7 @@ lvalue_p_1 (const_tree ref,
&& TREE_CODE (ref) != PARM_DECL
&& TREE_CODE (ref) != VAR_DECL
&& TREE_CODE (ref) != COMPONENT_REF)
- {
- if (CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ref))))
- return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
- else
- return clk_none;
- }
+ return clk_rvalueref;
/* lvalue references and named rvalue references are lvalues. */
return clk_ordinary;
@@ -108,12 +100,10 @@ lvalue_p_1 (const_tree ref,
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
case COMPONENT_REF:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
/* Look at the member designator. */
if (!op1_lvalue_kind)
;
@@ -164,35 +154,28 @@ lvalue_p_1 (const_tree ref,
if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
|| TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
return clk_none;
- 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),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
? TREE_OPERAND (ref, 1)
- : TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ : TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 1));
case TARGET_EXPR:
- return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
+ return clk_class;
case VA_ARG_EXPR:
- return (treat_class_rvalues_as_lvalues
- && CLASS_TYPE_P (TREE_TYPE (ref))
- ? clk_class : clk_none);
+ return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
case CALL_EXPR:
/* Any class-valued call would be wrapped in a TARGET_EXPR. */
@@ -209,8 +192,7 @@ lvalue_p_1 (const_tree ref,
with a BASELINK. */
/* This CONST_CAST is okay because BASELINK_FUNCTIONS returns
its argument unmodified and we assign it to a const_tree. */
- return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
@@ -246,18 +228,33 @@ lvalue_p_1 (const_tree ref,
cp_lvalue_kind
real_lvalue_p (tree ref)
{
- return lvalue_p_1 (ref,
- /*treat_class_rvalues_as_lvalues=*/0);
+ cp_lvalue_kind kind = lvalue_p_1 (ref);
+ if (kind & (clk_rvalueref|clk_class))
+ return clk_none;
+ else
+ return kind;
}
-/* This differs from real_lvalue_p in that class rvalues are
- considered lvalues. */
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
bool
lvalue_p (const_tree ref)
{
- return
- (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
+ return (lvalue_p_1 (ref) != 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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a12a5d2..7fdbcf4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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
* g++.dg/cpp0x/initlist20.C: New.
* g++.dg/cpp0x/initlist21.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv10.C b/gcc/testsuite/g++.dg/cpp0x/rv10.C
new file mode 100644
index 0000000..5e78b1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv10.C
@@ -0,0 +1,15 @@
+// { 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());
+}