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] |
Just pinging a patch I submitted two weeks ago. The patch attached to this post is mostly the same as the one I originally posted, but the template type deduction logic has been simplified and now follows DR606 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#606). The original patch submission is at http://gcc.gnu.org/ml/gcc-patches/2007-02/msg01760.html -- - Russell Yanofsky (PGP ID: 0x5FAA0216) - http://russ.yanofsky.org/ --
2007-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 (maybe_adjust_types_for_deduction): implement special template parameter deduction rule for rvalue references (type_unification_real, try_one_overload): update calls to maybe_adjust_types_for_deduction * 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 88) +++ gcc/tree.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/tree.h (.../trunk) (revision 88) @@ -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/testsuite/g++.dg/cpp0x/rref.hh/rv7p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv8p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/not_special.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/elision.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/named_refs.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/unnamed_refs.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/reference_collapsing.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/template_deduction.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/README =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv1n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv2n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/iop.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv3n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv1p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv4n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv2p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv3p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/cast.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv5n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv4p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/elision_neg.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv6n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv5p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv7n.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref.hh/rv6p.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/overload.py =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/collapse.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/implicit-copy.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/temp-constructor-bug.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/named.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/cast-bug.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/deduce.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/elision_weak.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/overload.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/temp-va-arg-bug.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/README =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/bind.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/overload-conv-1.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/collapse-bug.C =================================================================== Index: gcc/testsuite/g++.dg/cpp0x/rref/overload-conv-2.C =================================================================== Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (.../vendor/gcc/svn-122166) (revision 88) +++ gcc/cp/typeck.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/decl.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/call.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/except.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/error.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/tree.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/mangle.c (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/cp-tree.h (.../trunk) (revision 88) @@ -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 88) +++ gcc/cp/pt.c (.../trunk) (revision 88) @@ -116,7 +116,8 @@ static void tsubst_enum (tree, tree, tre static tree add_to_template_args (tree, tree); static tree add_outermost_template_args (tree, tree); static bool check_instantiated_args (tree, tree, tsubst_flags_t); -static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*); +static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*, + tree); static int type_unification_real (tree, tree, tree, tree, int, unification_kind_t, int); static void note_template_header (int); @@ -7624,8 +7625,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 +7665,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) @@ -9889,12 +9902,14 @@ fn_type_unification (tree fn, sections are symmetric. PARM is the type of a function parameter or the return type of the conversion function. ARG is the type of the argument passed to the call, or the type of the value - initialized with the result of the conversion function. */ + initialized with the result of the conversion function. + ARG_EXPR is the original argument expression, which may be null. */ static int maybe_adjust_types_for_deduction (unification_kind_t strict, tree* parm, - tree* arg) + tree* arg, + tree arg_expr) { int result = 0; @@ -9948,6 +9963,16 @@ maybe_adjust_types_for_deduction (unific *arg = TYPE_MAIN_VARIANT (*arg); } + /* From C++0x [14.8.2.1/3 temp.deduct.call] (after DR606), "If P is + of the form T&&, where T is a template parameter, and the argument + is an lvalue, T is deduced as A& */ + if (TREE_CODE (*parm) == REFERENCE_TYPE + && TYPE_REF_IS_RVALUE (*parm) + && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM + && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED + && arg_expr && real_lvalue_p (arg_expr)) + *arg = build_reference_type (*arg); + /* [temp.deduct.call] If P is a cv-qualified type, the top level cv-qualifiers @@ -9984,7 +10009,7 @@ type_unification_real (tree tparms, unification_kind_t strict, int flags) { - tree parm, arg; + tree parm, arg, arg_expr; int i; int ntparms = TREE_VEC_LENGTH (tparms); int sub_strict; @@ -10026,6 +10051,7 @@ type_unification_real (tree tparms, parms = TREE_CHAIN (parms); arg = TREE_VALUE (args); args = TREE_CHAIN (args); + arg_expr = NULL; if (arg == error_mark_node) return 1; @@ -10074,6 +10100,7 @@ type_unification_real (tree tparms, return 1; continue; } + arg_expr = arg; arg = TREE_TYPE (arg); if (arg == error_mark_node) return 1; @@ -10083,7 +10110,8 @@ type_unification_real (tree tparms, int arg_strict = sub_strict; if (!subr) - arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg); + arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, + arg_expr); if (unify (tparms, targs, parm, arg, arg_strict)) return 1; @@ -10258,7 +10286,7 @@ try_one_overload (tree tparms, else if (addr_p) arg = build_pointer_type (arg); - sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg); + sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL); /* We don't copy orig_targs for this because if we have already deduced some template args from previous args, unify would complain when we Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (.../vendor/gcc/svn-122166) (revision 88) +++ gcc/cp/parser.c (.../trunk) (revision 88) @@ -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 Index: ChangeLog ===================================================================
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] |