This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] rvalue reference implementation for C++0x


I'm submitting a patch that adds support for rvalue references to G++
when --std=c++0x mode is enabled.

A good, in depth description of rvalue references is available at
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm, but
basically, rvalue references work the same as normal C++ references,
only they are allowed to bind to temporary objects that hold the results
of rvalue expressions. Example:

  struct S{};
  S foo();

  // invalid in C++, normal non-const references can't bind to rvalues
  S & lvalue_ref = foo(); 

  // rvalue references are declared with && and can bind to rvalues
  S && rvalue_ref = foo();

The situations that require rvalue references are complicated and
described in the link above. But the essential idea is that when you
have a modifiable reference to an temporary, you can work with it
directly instead of having to create unnecessary copies of it. Generic
code can use rvalue references to work well with objects that may be
expensive to copy (like strings, containers) or impossible to copy (like
auto_ptrs).

The patch changes the C++ front end to understand && syntax for rvalue
reference declarations, and to follow some new rules for && types when
doing things like resolving function overloads and performing template
type deduction. The changes to the compiler are straightforward and
follow
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html,
which describes the changes made to the standard to support rvalue
references.

Rvalue references are backwards compatible, and do not in affect the
compilation or behavior of existing C++ code. They have already been
implemented for some time in Metrowerks Codewarrior and are used in
ConceptGCC. The patch attached to this email has been in the works for
quite a while. It's been used by a number of people and includes almost
40 testcases. I completed copyright assignment paperwork for it, and
set up a homepage at http://russ.yanofsky.org/rref/ that provides more
information about it.

Attached is a ChangeLog entry, the patch, and a tarball containing new
test cases.

-- 
-  Russell Yanofsky (PGP ID: 0x5FAA0216)
-  http://russ.yanofsky.org/
--

2006-02-20  Russell Yanofsky <russ@yanofsky.org>
            Pedro Lamarao <pedro.lamarao@mndfck.org>
            Doug Gregor <doug.gregor@gmail.com>
            Howard Hinnant <howard.hinnant@gmail.com>

	Add support for rvalue references to G++ under --std=c++0x mode
	* gcc/cp/call.c (conversion): new "valuedness_matches_p" member
	(convert_class_to_reference): require reference type as first
	parameter instead of base type
	(reference_binding): add logic to handle rvalue references
	(implicit_conversion): update inaccurate comment
	(convert_like_real): disable creation of temporaries that are
	impossible to initialize for types with move constructors
	(maybe_handle_implicit_object): set "valuedness_matches_p"
	(maybe_handle_ref_bind): return conversion instead of type node
	(compare_ics): add logic to use "valuedness_matches_p" values to
	determine preferred conversion sequences
	* gcc/cp/cp-tree.h (declarator): new "rvalue_ref" flag
	(LOOKUP_PREFER_RVALUE): new lookup flag
	* gcc/cp/decl.c (grokdeclarator): implement reference collapsing
	(copy_fn_p): don't consider constructors taking rvalue references
	to be copy constructors
	* gcc/cp/error.c (dump_type_prefix): format rvalue reference types
	correctly in error messages
	* gcc/cp/except.c (build_throw): move from certain lvalues when
	throwing.
	* gcc/cp/mangle.c (write_type): mangle rvalue references differently
	than regular references
	* gcc/cp/parser.c (make_reference_declarator): new boolean parameter
	(cp_parser_make_indirect_declarator): new function
	(cp_parser_new_declarator_opt): call cp_parser_make_indirect_declarator
	(cp_parser_conversion_declarator_opt): same
	(cp_parser_declarator): same
	(cp_parser_ptr_operator): parse "&&" tokens into rvalue reference
	declarators
	* gcc/cp/pt.c (tsubst): implement reference collapsing
	(type_unification_real): implement special template parameter
	deduction rule for rvalue references
	(try_one_overload): update call to unify
	(try_class_unification): same
	(unify): new "deduce_ref" parameter and more logic to implement the
	special rvalue reference template parameter deduction rule
	(more_specialized_fn): update calls to unify
	(get_class_bindings): same
	* gcc/cp/tree.c (lvalue_p_1): handle rvalue reference types
	* gcc/cp/typeck.c (comptypes): don't consider rvalue and lvalue
	reference types to be equivalent
	(check_return_expr): move from certain lvalues when returning them
	* gcc/tree.h
	(TYPE_REF_IS_RVALUE): new macro for REFERENCE_TYPE nodes
	(build_rval_reference_type_for_mode): new function
	(build_rval_reference_type): new function
	* gcc/tree.c (build_rval_reference_type_for_mode): new function
	(build_rval_reference_type): new function
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/tree.c	(.../trunk)	(revision 85)
@@ -5324,8 +5324,8 @@ build_pointer_type (tree to_type)
 /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
 
 tree
-build_reference_type_for_mode (tree to_type, enum machine_mode mode,
-			       bool can_alias_all)
+build_rval_reference_type_for_mode (tree to_type, enum machine_mode mode,
+				    bool can_alias_all, bool rval)
 {
   tree t;
 
@@ -5344,7 +5344,8 @@ build_reference_type_for_mode (tree to_t
   /* First, if we already have a type for pointers to TO_TYPE and it's
      the proper mode, use it.  */
   for (t = TYPE_REFERENCE_TO (to_type); t; t = TYPE_NEXT_REF_TO (t))
-    if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all)
+    if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all
+	&& TYPE_REF_IS_RVALUE(t) == rval)
       return t;
 
   t = make_node (REFERENCE_TYPE);
@@ -5352,6 +5353,7 @@ build_reference_type_for_mode (tree to_t
   TREE_TYPE (t) = to_type;
   TYPE_MODE (t) = mode;
   TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
+  TYPE_REF_IS_RVALUE(t) = rval;
   TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
   TYPE_REFERENCE_TO (to_type) = t;
 
@@ -5359,19 +5361,35 @@ build_reference_type_for_mode (tree to_t
     SET_TYPE_STRUCTURAL_EQUALITY (t);
   else if (TYPE_CANONICAL (to_type) != to_type)
     TYPE_CANONICAL (t) 
-      = build_reference_type_for_mode (TYPE_CANONICAL (to_type),
-				       mode, can_alias_all);
+      = build_rval_reference_type_for_mode (TYPE_CANONICAL (to_type),
+					    mode, can_alias_all, rval);
 
   layout_type (t);
 
   return t;
 }
 
+tree
+build_reference_type_for_mode (tree to_type, enum machine_mode mode,
+			       bool can_alias_all)
+{
+  return build_rval_reference_type_for_mode (to_type, mode,
+					     can_alias_all,
+					     false);
+}
 
 /* Build the node for the type of references-to-TO_TYPE by default
    in ptr_mode.  */
 
 tree
+build_rval_reference_type (tree to_type, bool rval)
+{
+  return build_rval_reference_type_for_mode (to_type, ptr_mode, false, rval);
+}
+
+/* Build the node for lvalue references. */
+
+tree
 build_reference_type (tree to_type)
 {
   return build_reference_type_for_mode (to_type, ptr_mode, false);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/tree.h	(.../trunk)	(revision 85)
@@ -484,6 +484,8 @@ struct gimple_stmt GTY(())
 	   ..._DECL
        CALL_FROM_THUNK_P in
            CALL_EXPR
+       TYPE_REF_IS_RVALUE in
+	 REFERENCE_TYPE
 
    side_effects_flag:
 
@@ -1282,6 +1284,10 @@ extern void omp_clause_range_check_faile
 #define CALL_FROM_THUNK_P(NODE) \
   (CALL_EXPR_CHECK (NODE)->base.protected_flag)
 
+/* In a REFERENCE_TYPE, means that reference is an rvalue reference */
+#define TYPE_REF_IS_RVALUE(NODE) \
+  (REFERENCE_TYPE_CHECK (NODE)->base.protected_flag)
+
 /* In a type, nonzero means that all objects of the type are guaranteed by the
    language or front-end to be properly aligned, so we can indicate that a MEM
    of this type is aligned at least to the alignment of the type, even if it
@@ -3748,7 +3754,10 @@ extern void set_sizetype (tree);
 extern void fixup_unsigned_type (tree);
 extern tree build_pointer_type_for_mode (tree, enum machine_mode, bool);
 extern tree build_pointer_type (tree);
+extern tree build_rval_reference_type_for_mode
+  (tree, enum machine_mode, bool, bool);
 extern tree build_reference_type_for_mode (tree, enum machine_mode, bool);
+extern tree build_rval_reference_type (tree, bool);
 extern tree build_reference_type (tree);
 extern tree build_vector_type_for_mode (tree, enum machine_mode);
 extern tree build_vector_type (tree innertype, int nunits);
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/typeck.c	(.../trunk)	(revision 85)
@@ -1027,8 +1027,12 @@ structural_comptypes (tree t1, tree t2, 
 	return false;
       break;
 
-    case POINTER_TYPE:
     case REFERENCE_TYPE:
+      if (TYPE_REF_IS_RVALUE(t1) != TYPE_REF_IS_RVALUE(t2))
+	return false;
+      /* fall through to checks for pointer types */
+
+    case POINTER_TYPE:
       if (TYPE_MODE (t1) != TYPE_MODE (t2)
 	  || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)
 	  || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
@@ -6737,18 +6741,40 @@ check_return_expr (tree retval, bool *no
     {
       /* The type the function is declared to return.  */
       tree functype = TREE_TYPE (TREE_TYPE (current_function_decl));
+      int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
 
       /* The functype's return type will have been set to void, if it
 	 was an incomplete type.  Just treat this as 'return;' */
       if (VOID_TYPE_P (functype))
 	return error_mark_node;
 
+      /* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes
+	 treated as an rvalue for the purposes of overload resolution to
+	 favor move constructors over copy constructors.  */
+      if (/* Must be a local, automatic variable.  */
+	  TREE_CODE (retval) == VAR_DECL
+	  && DECL_CONTEXT (retval) == current_function_decl
+	  && ! TREE_STATIC (retval)
+	  && (DECL_ALIGN (retval)
+	      >= DECL_ALIGN (DECL_RESULT (current_function_decl)))
+	   /* The variable much not have the `volatile' qualifier.  */
+	  && !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)
+	  /* The return type must be a class type.  */
+	  && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
+	  /* The cv-unqualified type of the returned value must be the
+	     same as the cv-unqualified return type of the
+	     function.  */
+	  && same_type_p ((TYPE_MAIN_VARIANT
+			   (TREE_TYPE (retval))),
+			  (TYPE_MAIN_VARIANT
+			   (TREE_TYPE (TREE_TYPE (current_function_decl))))))
+	flags = flags | LOOKUP_PREFER_RVALUE;
+
       /* First convert the value to the function's return type, then
 	 to the type of return value's location to handle the
 	 case that functype is smaller than the valtype.  */
       retval = convert_for_initialization
-	(NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
-	 "return", NULL_TREE, 0);
+	(NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0);
       retval = convert (valtype, retval);
 
       /* If the conversion failed, treat this just like `return;'.  */
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/decl.c	(.../trunk)	(revision 85)
@@ -7747,10 +7747,24 @@ grokdeclarator (const cp_declarator *dec
 
 	  if (TREE_CODE (type) == REFERENCE_TYPE)
 	    {
-	      error (declarator->kind == cdk_reference
-		     ? "cannot declare reference to %q#T"
-		     : "cannot declare pointer to %q#T", type);
-	      type = TREE_TYPE (type);
+	      if (declarator->kind != cdk_reference)
+		{
+		  error ("cannot declare pointer to %q#T", type);
+		  type = TREE_TYPE (type);
+		}
+
+	      /* In C++0x, we allow reference to reference declarations
+		 that occur indirectly through typedefs [7.1.3/8 dcl.typedef]
+		 and template type arguments [14.3.1/4 temp.arg.type]. The
+		 check for direct reference to reference declarations, which
+		 are still forbidden, occurs below. Reasoning behind the change
+		 can be found in DR106, DR540, and the rvalue reference
+		 proposals. */
+	      else if (!flag_cpp0x)
+		{
+		  error ("cannot declare reference to %q#T", type);
+		  type = TREE_TYPE (type);
+		}
 	    }
 	  else if (VOID_TYPE_P (type))
 	    {
@@ -7776,8 +7790,32 @@ grokdeclarator (const cp_declarator *dec
 
 	  if (declarator->kind == cdk_reference)
 	    {
+	      /* In C++0x, the type we are creating a reference to might be
+		 a typedef which is itself a reference type. In that case,
+		 we follow the reference collapsing rules in
+		 [7.1.3/8 dcl.typedef] to create the final reference type. */
 	      if (!VOID_TYPE_P (type))
-		type = build_reference_type (type);
+		type = build_rval_reference_type
+		       ((TREE_CODE (type) == REFERENCE_TYPE
+			 ? TREE_TYPE (type) : type),
+			(declarator->u.pointer.rvalue_ref
+			 && (TREE_CODE(type) != REFERENCE_TYPE
+			     || TYPE_REF_IS_RVALUE (type))));
+
+	      /* In C++0x, we need this check for direct reference to
+		 reference declarations, which are forbidden by
+		 [8.3.2/5 dcl.ref]. Reference to reference declarations
+		 are only allowed indirectly through typedefs and template
+		 type arguments. Example:
+
+		   void foo(int & &);      // invalid ref-to-ref decl
+
+		   typedef int & int_ref;
+		   void foo(int_ref &);    // valid ref-to-ref decl
+	      */
+	      if (inner_declarator && inner_declarator->kind == cdk_reference)
+		error ("cannot declare reference to %q#T, which is not "
+		       "a typedef or a template type argument", type);
 	    }
 	  else if (TREE_CODE (type) == METHOD_TYPE)
 	    type = build_ptrmemfunc_type (build_pointer_type (type));
@@ -9000,6 +9038,7 @@ copy_fn_p (tree d)
       result = -1;
     }
   else if (TREE_CODE (arg_type) == REFERENCE_TYPE
+	   && !TYPE_REF_IS_RVALUE(arg_type)
 	   && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
     {
       if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/call.c	(.../trunk)	(revision 85)
@@ -97,6 +97,10 @@ struct conversion {
   /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
      from a pointer-to-derived to pointer-to-base is being performed.  */
   BOOL_BITFIELD base_p : 1;
+  /* If KIND is ck_ref_bind, true when either an lvalue reference is
+     being bound to an lvalue expression or an rvalue reference is
+     being bound to an rvalue expression. */
+  BOOL_BITFIELD valuedness_matches_p: 1;
   /* The type of the expression resulting from the conversion.  */
   tree type;
   union {
@@ -176,7 +180,7 @@ static conversion *standard_conversion (
 static conversion *reference_binding (tree, tree, tree, int);
 static conversion *build_conv (conversion_kind, tree, conversion *);
 static bool is_subseq (conversion *, conversion *);
-static tree maybe_handle_ref_bind (conversion **);
+static conversion *maybe_handle_ref_bind (conversion **);
 static void maybe_handle_implicit_object (conversion **);
 static struct z_candidate *add_candidate
 	(struct z_candidate **, tree, tree, size_t,
@@ -900,12 +904,12 @@ reference_compatible_p (tree t1, tree t2
    converted to T as in [over.match.ref].  */
 
 static conversion *
-convert_class_to_reference (tree t, tree s, tree expr)
+convert_class_to_reference (tree reference_type, tree s, tree expr)
 {
   tree conversions;
   tree arglist;
   conversion *conv;
-  tree reference_type;
+  tree t;
   struct z_candidate *candidates;
   struct z_candidate *cand;
   bool any_viable_p;
@@ -939,7 +943,7 @@ convert_class_to_reference (tree t, tree
   arglist = build_int_cst (build_pointer_type (s), 0);
   arglist = build_tree_list (NULL_TREE, arglist);
 
-  reference_type = build_reference_type (t);
+  t = TREE_TYPE (reference_type);
 
   while (conversions)
     {
@@ -1002,6 +1006,9 @@ convert_class_to_reference (tree t, tree
 	      cand->second_conv
 		= (direct_reference_binding
 		   (reference_type, identity_conv));
+	      cand->second_conv->valuedness_matches_p
+		= TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn)))
+		  == TYPE_REF_IS_RVALUE(reference_type);
 	      cand->second_conv->bad_p |= cand->convs[0]->bad_p;
 	    }
 	}
@@ -1122,7 +1129,16 @@ reference_binding (tree rto, tree rfrom,
   related_p = reference_related_p (to, from);
   compatible_p = reference_compatible_p (to, from);
 
-  if (lvalue_p && compatible_p)
+  /* Directly bind reference when target expression's type is compatible with
+     the reference and expression is an lvalue. In C++0x, the wording in
+     [8.5.3/5 dcl.init.ref] is changed to also allow direct bindings for const
+     and rvalue references to rvalues of compatible class type, as part of
+     DR391. */
+  if (compatible_p
+      && (lvalue_p
+	  || (flag_cpp0x
+	      && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE(rto))
+	      && CLASS_TYPE_P (from))))
     {
       /* [dcl.init.ref]
 
@@ -1135,6 +1151,16 @@ reference_binding (tree rto, tree rfrom,
 	 lvalue.  */
       conv = build_identity_conv (from, expr);
       conv = direct_reference_binding (rto, conv);
+
+      if (flags & LOOKUP_PREFER_RVALUE)
+	/* The top-level caller requested that we pretend that the lvalue
+	   be treated as an rvalue.  */
+	conv->valuedness_matches_p = TYPE_REF_IS_RVALUE (rto);
+      else
+	conv->valuedness_matches_p
+	  = ((lvalue_p && !TYPE_REF_IS_RVALUE (rto)))
+	     || (!lvalue_p && TYPE_REF_IS_RVALUE (rto));
+
       if ((lvalue_p & clk_bitfield) != 0
 	  || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
 	/* For the purposes of overload resolution, we ignore the fact
@@ -1167,7 +1193,7 @@ reference_binding (tree rto, tree rfrom,
 
 	the reference is bound to the lvalue result of the conversion
 	in the second case.  */
-      conv = convert_class_to_reference (to, from, expr);
+      conv = convert_class_to_reference (rto, from, expr);
       if (conv)
 	return conv;
     }
@@ -1190,8 +1216,10 @@ reference_binding (tree rto, tree rfrom,
 
   /* [dcl.init.ref]
 
-     Otherwise, the reference shall be to a non-volatile const type.  */
-  if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
+     Otherwise, the reference shall be to a non-volatile const type.
+
+     Under C++0x, [8.5.3/5 dcl.init.ref] it may also be an rvalue reference */
+  if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto))
     return NULL;
 
   /* [dcl.init.ref]
@@ -1214,6 +1242,7 @@ reference_binding (tree rto, tree rfrom,
     {
       conv = build_identity_conv (from, expr);
       conv = direct_reference_binding (rto, conv);
+      conv->valuedness_matches_p = TYPE_REF_IS_RVALUE(rto);
       if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
 	conv->u.next->check_copy_constructor_p = true;
       return conv;
@@ -1238,6 +1267,7 @@ reference_binding (tree rto, tree rfrom,
   /* This reference binding, unlike those above, requires the
      creation of a temporary.  */
   conv->need_temporary_p = true;
+  conv->valuedness_matches_p = TYPE_REF_IS_RVALUE(rto);
 
   return conv;
 }
@@ -1279,7 +1309,7 @@ implicit_conversion (tree to, tree from,
 	conv = cand->second_conv;
 
       /* We used to try to bind a reference to a temporary here, but that
-	 is now handled by the recursive call to this function at the end
+	 is now handled after the recursive call to this function at the end
 	 of reference_binding.  */
       return conv;
     }
@@ -4404,13 +4434,22 @@ convert_like_real (conversion *convs, tr
       {
 	tree ref_type = totype;
 
-	/* If necessary, create a temporary.  */
-	if (convs->need_temporary_p || !lvalue_p (expr))
+	/* If necessary, create a temporary.
+
+	   ??? VA_ARG_EXPR and CONSTRUCTOR expressions are special cases
+	   that seem to need temporaries, even when their types are
+	   reference compatible with the type of reference being bound,
+	   so the upcoming call to build_unary_op (ADDR_EXPR, expr, ...)
+	   doesn't fail.  */
+	if (convs->need_temporary_p
+	    || TREE_CODE (expr) == CONSTRUCTOR
+	    || TREE_CODE (expr) == VA_ARG_EXPR)
 	  {
 	    tree type = convs->u.next->type;
 	    cp_lvalue_kind lvalue = real_lvalue_p (expr);
 
-	    if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
+	    if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))
+		&& !TYPE_REF_IS_RVALUE(ref_type))
 	      {
 		/* If the reference is volatile or non-const, we
 		   cannot create a temporary.  */
@@ -5646,28 +5685,28 @@ maybe_handle_implicit_object (conversion
 	t = t->u.next;
       t = build_identity_conv (TREE_TYPE (t->type), NULL_TREE);
       t = direct_reference_binding (reference_type, t);
+      t->valuedness_matches_p = 1;
       *ics = t;
     }
 }
 
 /* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
-   and return the type to which the reference refers.  Otherwise,
-   leave *ICS unchanged and return NULL_TREE.  */
+   and return the initial reference binding conversion. Otherwise,
+   leave *ICS unchanged and return NULL.  */
 
-static tree
+static conversion *
 maybe_handle_ref_bind (conversion **ics)
 {
   if ((*ics)->kind == ck_ref_bind)
     {
       conversion *old_ics = *ics;
-      tree type = TREE_TYPE (old_ics->type);
       *ics = old_ics->u.next;
       (*ics)->user_conv_p = old_ics->user_conv_p;
       (*ics)->bad_p = old_ics->bad_p;
-      return type;
+      return old_ics;
     }
 
-  return NULL_TREE;
+  return NULL;
 }
 
 /* Compare two implicit conversion sequences according to the rules set out in
@@ -5691,18 +5730,18 @@ compare_ics (conversion *ics1, conversio
   conversion_rank rank1, rank2;
 
   /* REF_BINDING is nonzero if the result of the conversion sequence
-     is a reference type.   In that case TARGET_TYPE is the
-     type referred to by the reference.  */
-  tree target_type1;
-  tree target_type2;
+     is a reference type.   In that case REF_CONV is the reference
+     binding conversion. */
+  conversion *ref_conv1;
+  conversion *ref_conv2;
 
   /* Handle implicit object parameters.  */
   maybe_handle_implicit_object (&ics1);
   maybe_handle_implicit_object (&ics2);
 
   /* Handle reference parameters.  */
-  target_type1 = maybe_handle_ref_bind (&ics1);
-  target_type2 = maybe_handle_ref_bind (&ics2);
+  ref_conv1 = maybe_handle_ref_bind (&ics1);
+  ref_conv2 = maybe_handle_ref_bind (&ics2);
 
   /* [over.ics.rank]
 
@@ -5993,15 +6032,31 @@ compare_ics (conversion *ics1, conversio
 
   /* [over.ics.rank]
 
+     --S1 and S2 are reference bindings (_dcl.init.ref_) and neither refers
+     to an implicit object parameter, and either S1 binds an lvalue reference
+     to an lvalue and S2 binds an rvalue reference or S1 binds an rvalue
+     reference to an rvalue and S2 binds an lvalue reference
+     (C++0x draft standard, 13.3.3.2)
+
      --S1 and S2 are reference bindings (_dcl.init.ref_), and the
      types to which the references refer are the same type except for
      top-level cv-qualifiers, and the type to which the reference
      initialized by S2 refers is more cv-qualified than the type to
      which the reference initialized by S1 refers */
 
-  if (target_type1 && target_type2
+  if (ref_conv1 && ref_conv2
       && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
-    return comp_cv_qualification (target_type2, target_type1);
+    {
+      if (ref_conv1->valuedness_matches_p
+	  && !ref_conv2->valuedness_matches_p)
+	return 1;
+      else if (!ref_conv1->valuedness_matches_p
+	  && ref_conv2->valuedness_matches_p)
+	return -1;
+
+      return comp_cv_qualification (TREE_TYPE (ref_conv2->type),
+				    TREE_TYPE (ref_conv1->type));
+    }
 
   /* Neither conversion sequence is better than the other.  */
   return 0;
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/except.c	(.../trunk)	(revision 85)
@@ -709,12 +709,25 @@ build_throw (tree exp)
       /* And initialize the exception object.  */
       if (CLASS_TYPE_P (temp_type))
 	{
+	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
+
+	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
+	     treated as an rvalue for the purposes of overload resolution
+	     to favor move constructors over copy constructors.  */
+	  if (/* Must be a local, automatic variable.  */
+	      TREE_CODE (exp) == VAR_DECL
+	      && DECL_CONTEXT (exp) == current_function_decl
+	      && ! TREE_STATIC (exp)
+	      /* The variable much not have the `volatile' qualifier.  */
+	      && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
+	    flags = flags | LOOKUP_PREFER_RVALUE;
+
 	  /* Call the copy constructor.  */
 	  exp = (build_special_member_call
 		 (object, complete_ctor_identifier,
 		  build_tree_list (NULL_TREE, exp),
 		  TREE_TYPE (object),
-		  LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
+		  flags));
 	  if (exp == error_mark_node)
 	    {
 	      error ("  in thrown expression");
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/error.c	(.../trunk)	(revision 85)
@@ -509,7 +509,15 @@ dump_type_prefix (tree t, int flags)
 	    pp_cxx_whitespace (cxx_pp);
 	    pp_cxx_left_paren (cxx_pp);
 	  }
-	pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]);
+	if (TREE_CODE (t) == POINTER_TYPE)
+	  pp_character(cxx_pp, '*');
+	else if (TREE_CODE (t) == REFERENCE_TYPE)
+	{
+	  if (TYPE_REF_IS_RVALUE (t))
+	    pp_string (cxx_pp, "&&");
+	  else
+	    pp_character (cxx_pp, '&');
+	}
 	pp_base (cxx_pp)->padding = pp_before;
 	pp_cxx_cv_qualifier_seq (cxx_pp, t);
       }
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/tree.c	(.../trunk)	(revision 85)
@@ -64,8 +64,26 @@ lvalue_p_1 (tree ref,
   cp_lvalue_kind op1_lvalue_kind = clk_none;
   cp_lvalue_kind op2_lvalue_kind = clk_none;
 
+  /* Expressions of reference type are sometimes wrapped in
+     INDIRECT_REFs */
+  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);
+
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
-    return clk_ordinary;
+    {
+      /* unnamed rvalue references are rvalues */
+      if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref))
+	  && TREE_CODE (ref) != PARM_DECL
+	  && TREE_CODE (ref) != VAR_DECL
+	  && TREE_CODE (ref) != COMPONENT_REF)
+	return clk_none;
+
+      /* lvalue references and named rvalue refences are lvalues */
+      return clk_ordinary;
+    }
 
   if (ref == current_class_ptr)
     return clk_none;
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/mangle.c	(.../trunk)	(revision 85)
@@ -1621,6 +1621,8 @@ write_type (tree type)
 	  break;
 
 	case REFERENCE_TYPE:
+	  if TYPE_REF_IS_RVALUE(type)
+	    write_string("U6rvalue");
 	  write_char ('R');
 	  write_type (TREE_TYPE (type));
 	  break;
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/cp-tree.h	(.../trunk)	(revision 85)
@@ -3531,6 +3531,8 @@ enum overload_flags { NO_SPECIAL = 0, DT
    (Normally, these entities are registered in the symbol table, but
    not found by lookup.)  */
 #define LOOKUP_HIDDEN (LOOKUP_CONSTRUCTOR_CALLABLE << 1)
+/* Prefer that the lvalue be treated as an rvalue.  */
+#define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1)
 
 #define LOOKUP_NAMESPACES_ONLY(F)  \
   (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
@@ -3847,6 +3849,8 @@ struct cp_declarator {
       cp_cv_quals qualifiers;
       /* For cdk_ptrmem, the class type containing the member.  */
       tree class_type;
+      /* For cdk_reference, is this rvalue reference */
+      bool rvalue_ref;
     } pointer;
   } u;
 };
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/pt.c	(.../trunk)	(revision 85)
@@ -101,7 +101,7 @@ static int resolve_overloaded_unificatio
 					   unification_kind_t, int);
 static int try_one_overload (tree, tree, tree, tree, tree,
 			     unification_kind_t, int, bool);
-static int unify (tree, tree, tree, tree, int);
+static int unify (tree, tree, tree, tree, int, bool);
 static void add_pending_template (tree);
 static int push_tinst_level (tree);
 static void pop_tinst_level (void);
@@ -7624,8 +7624,13 @@ tsubst (tree t, tree args, tsubst_flags_
 
 	   -- Attempting to create a pointer to reference type.
 	   -- Attempting to create a reference to a reference type or
-	      a reference to void.  */
-	if (TREE_CODE (type) == REFERENCE_TYPE
+	      a reference to void.
+
+	  Under C++0x [14.8.2/2 temp.deduct], as part of the solution to
+	  DR106, creating a reference to a reference type during type
+	  deduction is no longer a cause for failure.   */
+	if ((TREE_CODE (type) == REFERENCE_TYPE
+	     && (!flag_cpp0x || code != REFERENCE_TYPE))
 	    || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
 	  {
 	    static location_t last_loc;
@@ -7659,8 +7664,15 @@ tsubst (tree t, tree args, tsubst_flags_
 	    if (TREE_CODE (type) == METHOD_TYPE)
 	      r = build_ptrmemfunc_type (r);
 	  }
+	else if (TREE_CODE (type) == REFERENCE_TYPE)
+	  /* In C++0x, during template argument substitution, when there is an
+	     attempt to create a reference to a reference type, reference
+	     collapsing is applied as described in [14.3.1/4 temp.arg.type]. */
+	  r = build_rval_reference_type
+	      (TREE_TYPE (type),
+	       TYPE_REF_IS_RVALUE (t) && TYPE_REF_IS_RVALUE (type));
 	else
-	  r = build_reference_type (type);
+	  r = build_rval_reference_type (type, TYPE_REF_IS_RVALUE (t));
 	r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
 
 	if (r != error_mark_node)
@@ -9985,6 +9997,7 @@ type_unification_real (tree tparms,
 		       int flags)
 {
   tree parm, arg;
+  bool deduce_ref;
   int i;
   int ntparms = TREE_VEC_LENGTH (tparms);
   int sub_strict;
@@ -10027,6 +10040,13 @@ type_unification_real (tree tparms,
       arg = TREE_VALUE (args);
       args = TREE_CHAIN (args);
 
+      /* From C++0x [14.8.2.1/3 temp.deduct.call], "If P is an rvalue
+	 reference type and the argument is an lvalue, the type A& is
+	 used in place of A for type deduction."  */
+      deduce_ref = (TREE_CODE (parm) == REFERENCE_TYPE
+		    && TYPE_REF_IS_RVALUE (parm)
+		    && real_lvalue_p (arg));
+
       if (arg == error_mark_node)
 	return 1;
       if (arg == unknown_type_node)
@@ -10085,7 +10105,7 @@ type_unification_real (tree tparms,
 	if (!subr)
 	  arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
 
-	if (unify (tparms, targs, parm, arg, arg_strict))
+	if (unify (tparms, targs, parm, arg, arg_strict, deduce_ref))
 	  return 1;
       }
     }
@@ -10267,7 +10287,7 @@ try_one_overload (tree tparms,
   nargs = TREE_VEC_LENGTH (targs);
   tempargs = make_tree_vec (nargs);
 
-  if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+  if (unify (tparms, tempargs, parm, arg, sub_strict, false) != 0)
     return 0;
 
   /* First make sure we didn't deduce anything that conflicts with
@@ -10348,7 +10368,7 @@ try_class_unification (tree tparms, tree
 
   /* If unification failed, we're done.  */
   if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
-	     CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
+	     CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, false))
     return NULL_TREE;
 
   return arg;
@@ -10500,10 +10520,14 @@ check_cv_quals_for_unify (int strict, tr
        qualified at this point.
      UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
        This is the outermost level of a deduction, and PARM can be less CV
-       qualified at this point.  */
+       qualified at this point.
+
+   The DEDUCE_REF parameter is true if a template type parameter should be
+   deduced as a reference.  */
 
 static int
-unify (tree tparms, tree targs, tree parm, tree arg, int strict)
+unify (tree tparms, tree targs, tree parm, tree arg, int strict,
+       bool deduce_ref)
 {
   int idx;
   tree targ;
@@ -10647,7 +10671,7 @@ unify (tree tparms, tree targs, tree par
 		if (unify (tparms, targs,
 			   TREE_VEC_ELT (parmvec, i),
 			   TREE_VEC_ELT (argvec, i),
-			   UNIFY_ALLOW_NONE))
+			   UNIFY_ALLOW_NONE, false))
 		  return 1;
 	      }
 	  }
@@ -10684,6 +10708,12 @@ unify (tree tparms, tree targs, tree par
 	  if (arg == error_mark_node)
 	    return 1;
 
+	  /* In C++0x, deduce_ref will be true when the template argument
+	     needs to be deduced as a reference to satisfy
+	     [14.8.2.1/3 temp.deduct.call], as quoted above. */
+	  if (deduce_ref && TREE_CODE (parm) == TEMPLATE_TYPE_PARM)
+	    arg = build_reference_type (arg);
+
 	  /* Simple cases: Value already set, does match or doesn't.  */
 	  if (targ != NULL_TREE && same_type_p (targ, arg))
 	    return 0;
@@ -10772,7 +10802,7 @@ unify (tree tparms, tree targs, tree par
 
 	 Unification of &A::x and &B::x must succeed.  */
       return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
-		    PTRMEM_CST_MEMBER (arg), strict);
+		    PTRMEM_CST_MEMBER (arg), strict, false);
      }
 
     case POINTER_TYPE:
@@ -10796,14 +10826,14 @@ unify (tree tparms, tree targs, tree par
 	  strict |= (strict_in & UNIFY_ALLOW_DERIVED);
 
 	return unify (tparms, targs, TREE_TYPE (parm),
-		      TREE_TYPE (arg), strict);
+		      TREE_TYPE (arg), strict, false);
       }
 
     case REFERENCE_TYPE:
       if (TREE_CODE (arg) != REFERENCE_TYPE)
 	return 1;
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-		    strict & UNIFY_ALLOW_MORE_CV_QUAL);
+		    strict & UNIFY_ALLOW_MORE_CV_QUAL, false);
 
     case ARRAY_TYPE:
       if (TREE_CODE (arg) != ARRAY_TYPE)
@@ -10866,11 +10896,12 @@ unify (tree tparms, tree targs, tree par
 				   arg_max,
 				   integer_one_node);
 
-	  if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
+	  if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER,
+		     false))
 	    return 1;
 	}
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-		    strict & UNIFY_ALLOW_MORE_CV_QUAL);
+		    strict & UNIFY_ALLOW_MORE_CV_QUAL, false);
 
     case REAL_TYPE:
     case COMPLEX_TYPE:
@@ -10911,7 +10942,7 @@ unify (tree tparms, tree targs, tree par
 	for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
 	  if (unify (tparms, targs,
 		     TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
-		     UNIFY_ALLOW_NONE))
+		     UNIFY_ALLOW_NONE, false))
 	    return 1;
 	return 0;
       }
@@ -10929,7 +10960,7 @@ unify (tree tparms, tree targs, tree par
 	  return unify (tparms, targs,
 			TYPE_PTRMEMFUNC_FN_TYPE (parm),
 			TYPE_PTRMEMFUNC_FN_TYPE (arg),
-			strict);
+			strict, false);
 	}
 
       if (CLASSTYPE_TEMPLATE_INFO (parm))
@@ -10970,7 +11001,7 @@ unify (tree tparms, tree targs, tree par
 	    return 1;
 
 	  return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
-			CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
+			CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, false);
 	}
       else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
 	return 1;
@@ -10993,7 +11024,7 @@ unify (tree tparms, tree targs, tree par
 	return 1;
 
       if (unify (tparms, targs, TREE_TYPE (parm),
-		 TREE_TYPE (arg), UNIFY_ALLOW_NONE))
+		 TREE_TYPE (arg), UNIFY_ALLOW_NONE, false))
 	return 1;
       return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
 				    TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
@@ -11013,7 +11044,8 @@ unify (tree tparms, tree targs, tree par
 	    return 1;
 
 	  if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
-		     TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
+		     TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE,
+		     false))
 	    return 1;
 
 	  /* Determine the type of the function we are unifying against. */
@@ -11028,20 +11060,21 @@ unify (tree tparms, tree targs, tree par
 	  cv_quals =
 	    cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
 	  fntype = build_qualified_type (fntype, cv_quals);
-	  return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+	  return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, false);
 	}
 
       if (TREE_CODE (arg) != OFFSET_TYPE)
 	return 1;
       if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
-		 TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
+		 TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, false))
 	return 1;
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-		    strict);
+		    strict, false);
 
     case CONST_DECL:
       if (DECL_TEMPLATE_PARM_P (parm))
-	return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
+	return unify (tparms, targs, DECL_INITIAL (parm), arg, strict,
+		      false);
       if (arg != integral_constant_value (parm))
 	return 1;
       return 0;
@@ -11276,8 +11309,8 @@ more_specialized_fn (tree pat1, tree pat
       arg1 = TYPE_MAIN_VARIANT (arg1);
       arg2 = TYPE_MAIN_VARIANT (arg2);
 
-      deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE);
-      deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
+      deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE, false);
+      deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE, false);
 
       if (!deduce1)
 	better2 = -1;
@@ -11449,7 +11482,7 @@ get_class_bindings (tree tparms, tree sp
   if (unify (tparms, deduced_args,
 	     INNERMOST_TEMPLATE_ARGS (spec_args),
 	     INNERMOST_TEMPLATE_ARGS (args),
-	     UNIFY_ALLOW_NONE))
+	     UNIFY_ALLOW_NONE, false))
     return NULL_TREE;
 
   for (i =  0; i < ntparms; ++i)
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(.../vendor/gcc/svn-122166)	(revision 85)
+++ gcc/cp/parser.c	(.../trunk)	(revision 85)
@@ -858,7 +858,7 @@ static cp_declarator *make_array_declara
 static cp_declarator *make_pointer_declarator
   (cp_cv_quals, cp_declarator *);
 static cp_declarator *make_reference_declarator
-  (cp_cv_quals, cp_declarator *);
+  (cp_cv_quals, cp_declarator *, bool);
 static cp_parameter_declarator *make_parameter_declarator
   (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator
@@ -952,7 +952,8 @@ make_pointer_declarator (cp_cv_quals cv_
 /* Like make_pointer_declarator -- but for references.  */
 
 cp_declarator *
-make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
+			   bool rvalue_ref)
 {
   cp_declarator *declarator;
 
@@ -960,6 +961,7 @@ make_reference_declarator (cp_cv_quals c
   declarator->declarator = target;
   declarator->u.pointer.qualifiers = cv_qualifiers;
   declarator->u.pointer.class_type = NULL_TREE;
+  declarator->u.pointer.rvalue_ref = rvalue_ref;
 
   return declarator;
 }
@@ -1943,6 +1945,8 @@ static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
   (cp_parser *, tree, tree);
+static cp_declarator * cp_parser_make_indirect_declarator
+  (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
 /* Returns nonzero if we are parsing tentatively.  */
 
@@ -2615,6 +2619,27 @@ cp_parser_make_typename_type (cp_parser 
   return make_typename_type (scope, id, typename_type, tf_error);
 }
 
+/* This is a wrapper around the
+   make_{pointer,ptrmem,reference}_declarator functions that decides
+   which one to call based on the CODE and CLASS_TYPE arguments. The
+   CODE argument should be one of the values returned by
+   cp_parser_ptr_operator. */
+static cp_declarator *
+cp_parser_make_indirect_declarator (enum tree_code code, tree class_type,
+				    cp_cv_quals cv_qualifiers,
+				    cp_declarator *target)
+{
+  if (code == INDIRECT_REF)
+    if (class_type == NULL_TREE)
+      return make_pointer_declarator (cv_qualifiers, target);
+    else
+      return make_ptrmem_declarator (cv_qualifiers, class_type, target);
+  else if (code == ADDR_EXPR && class_type == NULL_TREE)
+    return make_reference_declarator (cv_qualifiers, target, false);
+  else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE)
+    return make_reference_declarator (cv_qualifiers, target, true);
+  gcc_unreachable ();
+}
 
 /* Create a new C++ parser.  */
 
@@ -5384,15 +5409,8 @@ cp_parser_new_declarator_opt (cp_parser*
       /* Parse another optional declarator.  */
       declarator = cp_parser_new_declarator_opt (parser);
 
-      /* Create the representation of the declarator.  */
-      if (type)
-	declarator = make_ptrmem_declarator (cv_quals, type, declarator);
-      else if (code == INDIRECT_REF)
-	declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-	declarator = make_reference_declarator (cv_quals, declarator);
-
-      return declarator;
+      return cp_parser_make_indirect_declarator
+	(code, type, cv_quals, declarator);
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
@@ -8121,16 +8139,8 @@ cp_parser_conversion_declarator_opt (cp_
       /* Parse another optional declarator.  */
       declarator = cp_parser_conversion_declarator_opt (parser);
 
-      /* Create the representation of the declarator.  */
-      if (class_type)
-	declarator = make_ptrmem_declarator (cv_quals, class_type,
-					     declarator);
-      else if (code == INDIRECT_REF)
-	declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-	declarator = make_reference_declarator (cv_quals, declarator);
-
-      return declarator;
+      return cp_parser_make_indirect_declarator
+	(code, class_type, cv_quals, declarator);
    }
 
   return NULL;
@@ -11589,15 +11599,8 @@ cp_parser_declarator (cp_parser* parser,
 	  && !cp_parser_parse_definitely (parser))
 	declarator = NULL;
 
-      /* Build the representation of the ptr-operator.  */
-      if (class_type)
-	declarator = make_ptrmem_declarator (cv_quals,
-					     class_type,
-					     declarator);
-      else if (code == INDIRECT_REF)
-	declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-	declarator = make_reference_declarator (cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+	(code, class_type, cv_quals, declarator);
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -12038,12 +12041,15 @@ cp_parser_direct_declarator (cp_parser* 
      & cv-qualifier-seq [opt]
 
    Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
-   Returns ADDR_EXPR if a reference was used.  In the case of a
-   pointer-to-member, *TYPE is filled in with the TYPE containing the
-   member.  *CV_QUALS is filled in with the cv-qualifier-seq, or
-   TYPE_UNQUALIFIED, if there are no cv-qualifiers.  Returns
-   ERROR_MARK if an error occurred.  */
-
+   Returns ADDR_EXPR if a reference was used, or NON_LVALUE_EXPR for
+   an rvalue reference. In the case of a pointer-to-member, *TYPE is
+   filled in with the TYPE containing the member.  *CV_QUALS is
+   filled in with the cv-qualifier-seq, or TYPE_UNQUALIFIED, if there
+   are no cv-qualifiers.  Returns ERROR_MARK if an error occurred.
+   Note that the tree codes returned by this function have nothing
+   to do with the types of trees that will be eventually be created
+   to represent the pointer or reference type being parsed. They are
+   just constants with suggestive names. */
 static enum tree_code
 cp_parser_ptr_operator (cp_parser* parser,
 			tree* type,
@@ -12059,13 +12065,18 @@ cp_parser_ptr_operator (cp_parser* parse
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  /* If it's a `*' or `&' we have a pointer or reference.  */
-  if (token->type == CPP_MULT || token->type == CPP_AND)
-    {
-      /* Remember which ptr-operator we were processing.  */
-      code = (token->type == CPP_AND ? ADDR_EXPR : INDIRECT_REF);
 
-      /* Consume the `*' or `&'.  */
+  /* If it's a `*', `&' or `&&' we have a pointer or reference.  */
+  if (token->type == CPP_MULT)
+    code = INDIRECT_REF;
+  else if (token->type == CPP_AND)
+    code = ADDR_EXPR;
+  else if (flag_cpp0x && token->type == CPP_AND_AND) /* C++0x only */
+    code = NON_LVALUE_EXPR;
+
+  if (code != ERROR_MARK)
+    {
+      /* Consume the `*', `&' or `&&'.  */
       cp_lexer_consume_token (parser->lexer);
 
       /* A `*' can be followed by a cv-qualifier-seq, and so can a

Attachment: tests.tar.bz2
Description: application/bzip-compressed-tar

Attachment: signature.asc
Description: This is a digitally signed message part


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]