aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-09-12 14:04:31 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-09-12 14:04:31 -0400
commitdbbc379eaa586bae7a5f374fb6e294810af2ae80 (patch)
tree5110c2a484935a0f9da3e71b1aca5b87046c7c63
parent4ce1e77017b289c619d22c1bcbb120aae271098b (diff)
downloadgcc-dbbc379eaa586bae7a5f374fb6e294810af2ae80.zip
gcc-dbbc379eaa586bae7a5f374fb6e294810af2ae80.tar.gz
gcc-dbbc379eaa586bae7a5f374fb6e294810af2ae80.tar.bz2
cp-tree.h (LOOKUP_NO_RVAL_BIND): New.
* cp-tree.h (LOOKUP_NO_RVAL_BIND): New. * call.c (conditional_conversion): Use it. (reference_binding): Fix handling of xvalues. From-SVN: r178787
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/call.c61
-rw-r--r--gcc/cp/cp-tree.h2
3 files changed, 44 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0d5ccde..c72d9d0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2011-09-12 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (LOOKUP_NO_RVAL_BIND): New.
+ * call.c (conditional_conversion): Use it.
+ (reference_binding): Fix handling of xvalues.
+
2011-09-09 Jason Merrill <jason@redhat.com>
* call.c (implicit_conversion): Check BRACE_ENCLOSED_INITIALIZER_P
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 62bee2d..81c8a90 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1564,7 +1564,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
tree tfrom;
bool related_p;
bool compatible_p;
- cp_lvalue_kind is_lvalue = clk_none;
+ cp_lvalue_kind gl_kind;
+ bool is_lvalue;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
@@ -1574,14 +1575,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
from = TREE_TYPE (expr);
}
- if (TREE_CODE (from) == REFERENCE_TYPE)
- {
- from = TREE_TYPE (from);
- if (!TYPE_REF_IS_RVALUE (rfrom)
- || TREE_CODE (from) == FUNCTION_TYPE)
- is_lvalue = clk_ordinary;
- }
-
if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
{
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
@@ -1597,11 +1590,28 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
}
}
- if (is_lvalue == clk_none && expr)
- is_lvalue = real_lvalue_p (expr);
+ if (TREE_CODE (from) == REFERENCE_TYPE)
+ {
+ from = TREE_TYPE (from);
+ if (!TYPE_REF_IS_RVALUE (rfrom)
+ || TREE_CODE (from) == FUNCTION_TYPE)
+ gl_kind = clk_ordinary;
+ else
+ gl_kind = clk_rvalueref;
+ }
+ else if (expr)
+ {
+ gl_kind = lvalue_kind (expr);
+ if (gl_kind & clk_class)
+ /* A class prvalue is not a glvalue. */
+ gl_kind = clk_none;
+ }
+ else
+ gl_kind = clk_none;
+ is_lvalue = gl_kind && !(gl_kind & clk_rvalueref);
tfrom = from;
- if ((is_lvalue & clk_bitfield) != 0)
+ if ((gl_kind & clk_bitfield) != 0)
tfrom = unlowered_expr_type (expr);
/* Figure out whether or not the types are reference-related and
@@ -1619,16 +1629,16 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
the reference and expression is an lvalue. In DR391, the wording in
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
const and rvalue references to rvalues of compatible class type.
- We should also do direct bindings for non-class "rvalues" derived from
- rvalue references. */
+ We should also do direct bindings for non-class xvalues. */
if (compatible_p
&& (is_lvalue
|| (((CP_TYPE_CONST_NON_VOLATILE_P (to)
- && !(flags & LOOKUP_NO_TEMP_BIND))
+ && !(flags & LOOKUP_NO_RVAL_BIND))
|| TYPE_REF_IS_RVALUE (rto))
- && (CLASS_TYPE_P (from)
- || TREE_CODE (from) == ARRAY_TYPE
- || (expr && lvalue_p (expr))))))
+ && (gl_kind
+ || (!(flags & LOOKUP_NO_TEMP_BIND)
+ && (CLASS_TYPE_P (from)
+ || TREE_CODE (from) == ARRAY_TYPE))))))
{
/* [dcl.init.ref]
@@ -1661,8 +1671,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
conv->rvaluedness_matches_p
= (TYPE_REF_IS_RVALUE (rto) == !is_lvalue);
- if ((is_lvalue & clk_bitfield) != 0
- || ((is_lvalue & clk_packed) != 0 && !TYPE_PACKED (to)))
+ if ((gl_kind & clk_bitfield) != 0
+ || ((gl_kind & clk_packed) != 0 && !TYPE_PACKED (to)))
/* For the purposes of overload resolution, we ignore the fact
this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
@@ -3575,8 +3585,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
struct z_candidate *old_candidates;
/* If we are called to convert to a reference type, we are trying to
- find an lvalue binding, so don't even consider temporaries. If
- we don't find an lvalue binding, the caller will try again to
+ find a direct binding, so don't even consider temporaries. If
+ we don't find a direct binding, the caller will try again to
look for a temporary binding. */
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
@@ -4297,16 +4307,17 @@ conditional_conversion (tree e1, tree e2)
/* [expr.cond]
If E2 is an lvalue: E1 can be converted to match E2 if E1 can be
- implicitly converted (clause _conv_) to the type "reference to
+ implicitly converted (clause _conv_) to the type "lvalue reference to
T2", subject to the constraint that in the conversion the
- reference must bind directly (_dcl.init.ref_) to E1. */
+ reference must bind directly (_dcl.init.ref_) to an lvalue. */
if (real_lvalue_p (e2))
{
conv = implicit_conversion (build_reference_type (t2),
t1,
e1,
/*c_cast_p=*/false,
- LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING);
+ LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND
+ |LOOKUP_ONLYCONVERTING);
if (conv)
return conv;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ae4cd07..06572fd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4294,6 +4294,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define LOOKUP_ALREADY_DIGESTED (LOOKUP_DEFAULTED << 1)
/* An instantiation with explicit template arguments. */
#define LOOKUP_EXPLICIT_TMPL_ARGS (LOOKUP_ALREADY_DIGESTED << 1)
+/* Like LOOKUP_NO_TEMP_BIND, but also prevent binding to xvalues. */
+#define LOOKUP_NO_RVAL_BIND (LOOKUP_EXPLICIT_TMPL_ARGS << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))