gcc: revert Rvalue references.
They are very useful but at this time I prefer not to figure out some minor conflicts with the bigger Apple's blocks support patch that is being worked on for current.
This commit is contained in:
parent
ba981145d6
commit
cc1a345c65
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=259660
@ -35,65 +35,6 @@
|
|||||||
|
|
||||||
* typeck.c (build_binary_op): Include types in error.
|
* typeck.c (build_binary_op): Include types in error.
|
||||||
|
|
||||||
2007-05-30 Russell Yanofsky <russ@yanofsky.org> (r125211)
|
|
||||||
Douglas Gregor <doug.gregor@gmail.com>
|
|
||||||
Pedro Lamarao <pedro.lamarao@mndfck.org>
|
|
||||||
Howard Hinnant <howard.hinnant@gmail.com>
|
|
||||||
|
|
||||||
PR c++/7412
|
|
||||||
PR c++/29939
|
|
||||||
* typeck.c (comptypes): Don't consider rvalue and lvalue
|
|
||||||
reference types to be equivalent.
|
|
||||||
(check_return_expr): Move from certain lvalues when returning
|
|
||||||
them.
|
|
||||||
* decl.c (grokdeclarator): Implement reference collapsing.
|
|
||||||
(copy_fn_p): Don't consider constructors taking rvalue references
|
|
||||||
to be copy constructors.
|
|
||||||
(move_fn_p): New.
|
|
||||||
* call.c (conversion): New "rvaluedness_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.
|
|
||||||
(build_over_call): Elide move constructors when possible.
|
|
||||||
(maybe_handle_implicit_object): Set "rvaluedness_matches_p".
|
|
||||||
(maybe_handle_ref_bind): Return conversion instead of type node.
|
|
||||||
(compare_ics): Add logic to use "rvaluedness_matches_p" values to
|
|
||||||
determine preferred conversion sequences.
|
|
||||||
* cp-tree.h (TYPE_REF_IS_RVALUE): New.
|
|
||||||
(LOOKUP_PREFER_RVALUE): New.
|
|
||||||
(DECL_MOVE_CONSTRUCTOR_P): New.
|
|
||||||
(struct cp_declarator): Add "reference" member for reference
|
|
||||||
types, with new "rvalue_ref" flag.
|
|
||||||
(cp_build_reference_type): Declare.
|
|
||||||
(move_fn_p): Declare.
|
|
||||||
* error.c (dump_type_prefix): Format rvalue reference types
|
|
||||||
correctly in error messages.
|
|
||||||
* except.c (build_throw): Move from certain lvalues when
|
|
||||||
throwing.
|
|
||||||
* mangle.c (write_type): Mangle rvalue references differently
|
|
||||||
than regular references.
|
|
||||||
* parser.c (make_reference_declarator): Add boolean parameter for
|
|
||||||
rvalue references.
|
|
||||||
(cp_parser_make_indirect_declarator): New.
|
|
||||||
(cp_parser_new_declarator_opt): Call
|
|
||||||
cp_parser_make_indirect_declarator.
|
|
||||||
(cp_parser_conversion_declarator_opt): Ditto.
|
|
||||||
(cp_parser_declarator): Ditto.
|
|
||||||
(cp_parser_ptr_operator): Parse "&&" tokens into rvalue reference
|
|
||||||
declarators.
|
|
||||||
* pt.c (tsubst): Implement reference collapsing.
|
|
||||||
(maybe_adjust_types_for_deduction): Implement special template
|
|
||||||
parameter deduction rule for rvalue references.
|
|
||||||
(type_unification_real): Update calls to
|
|
||||||
maybe_adjust_types_for_deduction.
|
|
||||||
(try_one_overload): Ditto.
|
|
||||||
(unify_pack_expansion): Ditto.
|
|
||||||
* tree.c (lvalue_p_1): Handle rvalue reference types.
|
|
||||||
(cp_build_reference_type): New.
|
|
||||||
|
|
||||||
2007-05-18 Geoffrey Keating <geoffk@apple.com> (r124839)
|
2007-05-18 Geoffrey Keating <geoffk@apple.com> (r124839)
|
||||||
|
|
||||||
* mangle.c (write_real_cst): Use 'unsigned long' for %lx.
|
* mangle.c (write_real_cst): Use 'unsigned long' for %lx.
|
||||||
|
@ -95,10 +95,6 @@ struct conversion {
|
|||||||
/* If KIND is ck_ptr or ck_pmem, true to indicate that a 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. */
|
from a pointer-to-derived to pointer-to-base is being performed. */
|
||||||
BOOL_BITFIELD base_p : 1;
|
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 rvaluedness_matches_p: 1;
|
|
||||||
/* The type of the expression resulting from the conversion. */
|
/* The type of the expression resulting from the conversion. */
|
||||||
tree type;
|
tree type;
|
||||||
union {
|
union {
|
||||||
@ -178,7 +174,7 @@ static conversion *standard_conversion (tree, tree, tree, bool, int);
|
|||||||
static conversion *reference_binding (tree, tree, tree, bool, int);
|
static conversion *reference_binding (tree, tree, tree, bool, int);
|
||||||
static conversion *build_conv (conversion_kind, tree, conversion *);
|
static conversion *build_conv (conversion_kind, tree, conversion *);
|
||||||
static bool is_subseq (conversion *, conversion *);
|
static bool is_subseq (conversion *, conversion *);
|
||||||
static conversion *maybe_handle_ref_bind (conversion **);
|
static tree maybe_handle_ref_bind (conversion **);
|
||||||
static void maybe_handle_implicit_object (conversion **);
|
static void maybe_handle_implicit_object (conversion **);
|
||||||
static struct z_candidate *add_candidate
|
static struct z_candidate *add_candidate
|
||||||
(struct z_candidate **, tree, tree, size_t,
|
(struct z_candidate **, tree, tree, size_t,
|
||||||
@ -899,12 +895,12 @@ reference_compatible_p (tree t1, tree t2)
|
|||||||
converted to T as in [over.match.ref]. */
|
converted to T as in [over.match.ref]. */
|
||||||
|
|
||||||
static conversion *
|
static conversion *
|
||||||
convert_class_to_reference (tree reference_type, tree s, tree expr)
|
convert_class_to_reference (tree t, tree s, tree expr)
|
||||||
{
|
{
|
||||||
tree conversions;
|
tree conversions;
|
||||||
tree arglist;
|
tree arglist;
|
||||||
conversion *conv;
|
conversion *conv;
|
||||||
tree t;
|
tree reference_type;
|
||||||
struct z_candidate *candidates;
|
struct z_candidate *candidates;
|
||||||
struct z_candidate *cand;
|
struct z_candidate *cand;
|
||||||
bool any_viable_p;
|
bool any_viable_p;
|
||||||
@ -938,7 +934,7 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
|
|||||||
arglist = build_int_cst (build_pointer_type (s), 0);
|
arglist = build_int_cst (build_pointer_type (s), 0);
|
||||||
arglist = build_tree_list (NULL_TREE, arglist);
|
arglist = build_tree_list (NULL_TREE, arglist);
|
||||||
|
|
||||||
t = TREE_TYPE (reference_type);
|
reference_type = build_reference_type (t);
|
||||||
|
|
||||||
while (conversions)
|
while (conversions)
|
||||||
{
|
{
|
||||||
@ -1001,9 +997,6 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
|
|||||||
cand->second_conv
|
cand->second_conv
|
||||||
= (direct_reference_binding
|
= (direct_reference_binding
|
||||||
(reference_type, identity_conv));
|
(reference_type, identity_conv));
|
||||||
cand->second_conv->rvaluedness_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;
|
cand->second_conv->bad_p |= cand->convs[0]->bad_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1130,16 +1123,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
to = build_qualified_type (to, cp_type_quals (from));
|
to = build_qualified_type (to, cp_type_quals (from));
|
||||||
compatible_p = reference_compatible_p (to, from);
|
compatible_p = reference_compatible_p (to, from);
|
||||||
|
|
||||||
/* Directly bind reference when target expression's type is compatible with
|
if (lvalue_p && compatible_p)
|
||||||
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]
|
/* [dcl.init.ref]
|
||||||
|
|
||||||
@ -1152,15 +1136,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
lvalue. */
|
lvalue. */
|
||||||
conv = build_identity_conv (from, expr);
|
conv = build_identity_conv (from, expr);
|
||||||
conv = direct_reference_binding (rto, conv);
|
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->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
|
|
||||||
else
|
|
||||||
conv->rvaluedness_matches_p
|
|
||||||
= (TYPE_REF_IS_RVALUE (rto) == !lvalue_p);
|
|
||||||
|
|
||||||
if ((lvalue_p & clk_bitfield) != 0
|
if ((lvalue_p & clk_bitfield) != 0
|
||||||
|| ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
|
|| ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
|
||||||
/* For the purposes of overload resolution, we ignore the fact
|
/* For the purposes of overload resolution, we ignore the fact
|
||||||
@ -1193,7 +1168,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
|
|
||||||
the reference is bound to the lvalue result of the conversion
|
the reference is bound to the lvalue result of the conversion
|
||||||
in the second case. */
|
in the second case. */
|
||||||
conv = convert_class_to_reference (rto, from, expr);
|
conv = convert_class_to_reference (to, from, expr);
|
||||||
if (conv)
|
if (conv)
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
@ -1216,10 +1191,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
|
|
||||||
/* [dcl.init.ref]
|
/* [dcl.init.ref]
|
||||||
|
|
||||||
Otherwise, the reference shall be to a non-volatile const type.
|
Otherwise, the reference shall be to a non-volatile const type. */
|
||||||
|
if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
|
||||||
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;
|
return NULL;
|
||||||
|
|
||||||
/* [dcl.init.ref]
|
/* [dcl.init.ref]
|
||||||
@ -1242,7 +1215,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
{
|
{
|
||||||
conv = build_identity_conv (from, expr);
|
conv = build_identity_conv (from, expr);
|
||||||
conv = direct_reference_binding (rto, conv);
|
conv = direct_reference_binding (rto, conv);
|
||||||
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
|
|
||||||
if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
|
if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
|
||||||
conv->u.next->check_copy_constructor_p = true;
|
conv->u.next->check_copy_constructor_p = true;
|
||||||
return conv;
|
return conv;
|
||||||
@ -1267,7 +1239,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||||||
/* This reference binding, unlike those above, requires the
|
/* This reference binding, unlike those above, requires the
|
||||||
creation of a temporary. */
|
creation of a temporary. */
|
||||||
conv->need_temporary_p = true;
|
conv->need_temporary_p = true;
|
||||||
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
|
|
||||||
|
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
@ -1309,7 +1280,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
|||||||
conv = cand->second_conv;
|
conv = cand->second_conv;
|
||||||
|
|
||||||
/* We used to try to bind a reference to a temporary here, but that
|
/* We used to try to bind a reference to a temporary here, but that
|
||||||
is now handled after the recursive call to this function at the end
|
is now handled by the recursive call to this function at the end
|
||||||
of reference_binding. */
|
of reference_binding. */
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
@ -4438,22 +4409,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||||||
{
|
{
|
||||||
tree ref_type = totype;
|
tree ref_type = totype;
|
||||||
|
|
||||||
/* If necessary, create a temporary.
|
/* If necessary, create a temporary. */
|
||||||
|
if (convs->need_temporary_p || !lvalue_p (expr))
|
||||||
VA_ARG_EXPR and CONSTRUCTOR expressions are special cases
|
|
||||||
that 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;
|
tree type = convs->u.next->type;
|
||||||
cp_lvalue_kind lvalue = real_lvalue_p (expr);
|
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
|
/* If the reference is volatile or non-const, we
|
||||||
cannot create a temporary. */
|
cannot create a temporary. */
|
||||||
@ -4976,9 +4938,7 @@ build_over_call (struct z_candidate *cand, int flags)
|
|||||||
|
|
||||||
if (! flag_elide_constructors)
|
if (! flag_elide_constructors)
|
||||||
/* Do things the hard way. */;
|
/* Do things the hard way. */;
|
||||||
else if (cand->num_convs == 1
|
else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn))
|
||||||
&& (DECL_COPY_CONSTRUCTOR_P (fn)
|
|
||||||
|| DECL_MOVE_CONSTRUCTOR_P (fn)))
|
|
||||||
{
|
{
|
||||||
tree targ;
|
tree targ;
|
||||||
arg = skip_artificial_parms_for (fn, converted_args);
|
arg = skip_artificial_parms_for (fn, converted_args);
|
||||||
@ -5716,28 +5676,28 @@ maybe_handle_implicit_object (conversion **ics)
|
|||||||
t = t->u.next;
|
t = t->u.next;
|
||||||
t = build_identity_conv (TREE_TYPE (t->type), NULL_TREE);
|
t = build_identity_conv (TREE_TYPE (t->type), NULL_TREE);
|
||||||
t = direct_reference_binding (reference_type, t);
|
t = direct_reference_binding (reference_type, t);
|
||||||
t->rvaluedness_matches_p = 1;
|
|
||||||
*ics = t;
|
*ics = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
|
/* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
|
||||||
and return the initial reference binding conversion. Otherwise,
|
and return the type to which the reference refers. Otherwise,
|
||||||
leave *ICS unchanged and return NULL. */
|
leave *ICS unchanged and return NULL_TREE. */
|
||||||
|
|
||||||
static conversion *
|
static tree
|
||||||
maybe_handle_ref_bind (conversion **ics)
|
maybe_handle_ref_bind (conversion **ics)
|
||||||
{
|
{
|
||||||
if ((*ics)->kind == ck_ref_bind)
|
if ((*ics)->kind == ck_ref_bind)
|
||||||
{
|
{
|
||||||
conversion *old_ics = *ics;
|
conversion *old_ics = *ics;
|
||||||
|
tree type = TREE_TYPE (old_ics->type);
|
||||||
*ics = old_ics->u.next;
|
*ics = old_ics->u.next;
|
||||||
(*ics)->user_conv_p = old_ics->user_conv_p;
|
(*ics)->user_conv_p = old_ics->user_conv_p;
|
||||||
(*ics)->bad_p = old_ics->bad_p;
|
(*ics)->bad_p = old_ics->bad_p;
|
||||||
return old_ics;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare two implicit conversion sequences according to the rules set out in
|
/* Compare two implicit conversion sequences according to the rules set out in
|
||||||
@ -5761,18 +5721,18 @@ compare_ics (conversion *ics1, conversion *ics2)
|
|||||||
conversion_rank rank1, rank2;
|
conversion_rank rank1, rank2;
|
||||||
|
|
||||||
/* REF_BINDING is nonzero if the result of the conversion sequence
|
/* REF_BINDING is nonzero if the result of the conversion sequence
|
||||||
is a reference type. In that case REF_CONV is the reference
|
is a reference type. In that case TARGET_TYPE is the
|
||||||
binding conversion. */
|
type referred to by the reference. */
|
||||||
conversion *ref_conv1;
|
tree target_type1;
|
||||||
conversion *ref_conv2;
|
tree target_type2;
|
||||||
|
|
||||||
/* Handle implicit object parameters. */
|
/* Handle implicit object parameters. */
|
||||||
maybe_handle_implicit_object (&ics1);
|
maybe_handle_implicit_object (&ics1);
|
||||||
maybe_handle_implicit_object (&ics2);
|
maybe_handle_implicit_object (&ics2);
|
||||||
|
|
||||||
/* Handle reference parameters. */
|
/* Handle reference parameters. */
|
||||||
ref_conv1 = maybe_handle_ref_bind (&ics1);
|
target_type1 = maybe_handle_ref_bind (&ics1);
|
||||||
ref_conv2 = maybe_handle_ref_bind (&ics2);
|
target_type2 = maybe_handle_ref_bind (&ics2);
|
||||||
|
|
||||||
/* [over.ics.rank]
|
/* [over.ics.rank]
|
||||||
|
|
||||||
@ -6063,31 +6023,15 @@ compare_ics (conversion *ics1, conversion *ics2)
|
|||||||
|
|
||||||
/* [over.ics.rank]
|
/* [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
|
--S1 and S2 are reference bindings (_dcl.init.ref_), and the
|
||||||
types to which the references refer are the same type except for
|
types to which the references refer are the same type except for
|
||||||
top-level cv-qualifiers, and the type to which the reference
|
top-level cv-qualifiers, and the type to which the reference
|
||||||
initialized by S2 refers is more cv-qualified than the type to
|
initialized by S2 refers is more cv-qualified than the type to
|
||||||
which the reference initialized by S1 refers */
|
which the reference initialized by S1 refers */
|
||||||
|
|
||||||
if (ref_conv1 && ref_conv2
|
if (target_type1 && target_type2
|
||||||
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
|
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
|
||||||
{
|
return comp_cv_qualification (target_type2, target_type1);
|
||||||
if (ref_conv1->rvaluedness_matches_p
|
|
||||||
&& !ref_conv2->rvaluedness_matches_p)
|
|
||||||
return 1;
|
|
||||||
else if (!ref_conv1->rvaluedness_matches_p
|
|
||||||
&& ref_conv2->rvaluedness_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. */
|
/* Neither conversion sequence is better than the other. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -56,7 +56,6 @@ struct diagnostic_context;
|
|||||||
OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
|
OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
|
||||||
BASELINK_QUALIFIED_P (in BASELINK)
|
BASELINK_QUALIFIED_P (in BASELINK)
|
||||||
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
|
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
|
||||||
TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
|
|
||||||
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
|
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
|
||||||
TI_PENDING_TEMPLATE_FLAG.
|
TI_PENDING_TEMPLATE_FLAG.
|
||||||
TEMPLATE_PARMS_FOR_INLINE.
|
TEMPLATE_PARMS_FOR_INLINE.
|
||||||
@ -1667,10 +1666,6 @@ struct lang_decl GTY(())
|
|||||||
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
|
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
|
||||||
(DECL_CONSTRUCTOR_P (NODE) && copy_fn_p (NODE) > 0)
|
(DECL_CONSTRUCTOR_P (NODE) && copy_fn_p (NODE) > 0)
|
||||||
|
|
||||||
/* Nonzero if NODE (a FUNCTION_DECL) is a move constructor. */
|
|
||||||
#define DECL_MOVE_CONSTRUCTOR_P(NODE) \
|
|
||||||
(DECL_CONSTRUCTOR_P (NODE) && move_fn_p (NODE))
|
|
||||||
|
|
||||||
/* Nonzero if NODE is a destructor. */
|
/* Nonzero if NODE is a destructor. */
|
||||||
#define DECL_DESTRUCTOR_P(NODE) \
|
#define DECL_DESTRUCTOR_P(NODE) \
|
||||||
(DECL_LANG_SPECIFIC (NODE)->decl_flags.destructor_attr)
|
(DECL_LANG_SPECIFIC (NODE)->decl_flags.destructor_attr)
|
||||||
@ -2566,10 +2561,6 @@ extern void decl_shadowed_for_var_insert (tree, tree);
|
|||||||
#define TYPE_REF_OBJ_P(NODE) \
|
#define TYPE_REF_OBJ_P(NODE) \
|
||||||
(TREE_CODE (NODE) == REFERENCE_TYPE && TYPE_OBJ_P (TREE_TYPE (NODE)))
|
(TREE_CODE (NODE) == REFERENCE_TYPE && TYPE_OBJ_P (TREE_TYPE (NODE)))
|
||||||
|
|
||||||
/* True if reference type NODE is an rvalue reference */
|
|
||||||
#define TYPE_REF_IS_RVALUE(NODE) \
|
|
||||||
TREE_LANG_FLAG_0 (REFERENCE_TYPE_CHECK (NODE))
|
|
||||||
|
|
||||||
/* Returns true if NODE is a pointer to an object, or a pointer to
|
/* Returns true if NODE is a pointer to an object, or a pointer to
|
||||||
void. Keep these checks in ascending tree code order. */
|
void. Keep these checks in ascending tree code order. */
|
||||||
#define TYPE_PTROBV_P(NODE) \
|
#define TYPE_PTROBV_P(NODE) \
|
||||||
@ -3453,8 +3444,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||||||
(Normally, these entities are registered in the symbol table, but
|
(Normally, these entities are registered in the symbol table, but
|
||||||
not found by lookup.) */
|
not found by lookup.) */
|
||||||
#define LOOKUP_HIDDEN (LOOKUP_CONSTRUCTOR_CALLABLE << 1)
|
#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) \
|
#define LOOKUP_NAMESPACES_ONLY(F) \
|
||||||
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
|
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
|
||||||
@ -3761,21 +3750,13 @@ struct cp_declarator {
|
|||||||
/* The bounds to the array. */
|
/* The bounds to the array. */
|
||||||
tree bounds;
|
tree bounds;
|
||||||
} array;
|
} array;
|
||||||
/* For cdk_pointer and cdk_ptrmem. */
|
/* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
|
||||||
struct {
|
struct {
|
||||||
/* The cv-qualifiers for the pointer. */
|
/* The cv-qualifiers for the pointer. */
|
||||||
cp_cv_quals qualifiers;
|
cp_cv_quals qualifiers;
|
||||||
/* For cdk_ptrmem, the class type containing the member. */
|
/* For cdk_ptrmem, the class type containing the member. */
|
||||||
tree class_type;
|
tree class_type;
|
||||||
} pointer;
|
} pointer;
|
||||||
/* For cdk_reference */
|
|
||||||
struct {
|
|
||||||
/* The cv-qualifiers for the reference. These qualifiers are
|
|
||||||
only used to diagnose ill-formed code. */
|
|
||||||
cp_cv_quals qualifiers;
|
|
||||||
/* Whether this is an rvalue reference */
|
|
||||||
bool rvalue_ref;
|
|
||||||
} reference;
|
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3936,7 +3917,6 @@ extern tree build_ptrmem_type (tree, tree);
|
|||||||
/* the grokdeclarator prototype is in decl.h */
|
/* the grokdeclarator prototype is in decl.h */
|
||||||
extern tree build_this_parm (tree, cp_cv_quals);
|
extern tree build_this_parm (tree, cp_cv_quals);
|
||||||
extern int copy_fn_p (tree);
|
extern int copy_fn_p (tree);
|
||||||
extern bool move_fn_p (tree);
|
|
||||||
extern tree get_scope_of_declarator (const cp_declarator *);
|
extern tree get_scope_of_declarator (const cp_declarator *);
|
||||||
extern void grok_special_member_properties (tree);
|
extern void grok_special_member_properties (tree);
|
||||||
extern int grok_ctor_properties (tree, tree);
|
extern int grok_ctor_properties (tree, tree);
|
||||||
@ -4436,7 +4416,6 @@ extern int is_dummy_object (tree);
|
|||||||
extern const struct attribute_spec cxx_attribute_table[];
|
extern const struct attribute_spec cxx_attribute_table[];
|
||||||
extern tree make_ptrmem_cst (tree, tree);
|
extern tree make_ptrmem_cst (tree, tree);
|
||||||
extern tree cp_build_type_attribute_variant (tree, tree);
|
extern tree cp_build_type_attribute_variant (tree, tree);
|
||||||
extern tree cp_build_reference_type (tree, bool);
|
|
||||||
extern tree cp_build_qualified_type_real (tree, int, tsubst_flags_t);
|
extern tree cp_build_qualified_type_real (tree, int, tsubst_flags_t);
|
||||||
#define cp_build_qualified_type(TYPE, QUALS) \
|
#define cp_build_qualified_type(TYPE, QUALS) \
|
||||||
cp_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
|
cp_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
|
||||||
|
@ -7823,24 +7823,10 @@ grokdeclarator (const cp_declarator *declarator,
|
|||||||
|
|
||||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
if (declarator->kind != cdk_reference)
|
error (declarator->kind == cdk_reference
|
||||||
{
|
? "cannot declare reference to %q#T"
|
||||||
error ("cannot declare pointer to %q#T", type);
|
: "cannot declare pointer to %q#T", type);
|
||||||
type = TREE_TYPE (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))
|
else if (VOID_TYPE_P (type))
|
||||||
{
|
{
|
||||||
@ -7866,39 +7852,8 @@ grokdeclarator (const cp_declarator *declarator,
|
|||||||
|
|
||||||
if (declarator->kind == cdk_reference)
|
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 a typedef TD names a type that is a reference to a type
|
|
||||||
T, an attempt to create the type 'lvalue reference to cv TD'
|
|
||||||
creates the type 'lvalue reference to T,' while an attempt
|
|
||||||
to create the type "rvalue reference to cv TD' creates the
|
|
||||||
type TD."
|
|
||||||
*/
|
|
||||||
if (!VOID_TYPE_P (type))
|
if (!VOID_TYPE_P (type))
|
||||||
type = cp_build_reference_type
|
type = build_reference_type (type);
|
||||||
((TREE_CODE (type) == REFERENCE_TYPE
|
|
||||||
? TREE_TYPE (type) : type),
|
|
||||||
(declarator->u.reference.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)
|
else if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
type = build_ptrmemfunc_type (build_pointer_type (type));
|
type = build_ptrmemfunc_type (build_pointer_type (type));
|
||||||
@ -9123,7 +9078,6 @@ copy_fn_p (tree d)
|
|||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (arg_type) == REFERENCE_TYPE
|
else if (TREE_CODE (arg_type) == REFERENCE_TYPE
|
||||||
&& !TYPE_REF_IS_RVALUE (arg_type)
|
|
||||||
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
|
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
|
||||||
{
|
{
|
||||||
if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
|
if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
|
||||||
@ -9141,57 +9095,6 @@ copy_fn_p (tree d)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* D is a constructor or overloaded `operator='.
|
|
||||||
|
|
||||||
Let T be the class in which D is declared. Then, this function
|
|
||||||
returns true when D is a move constructor or move assignment
|
|
||||||
operator, false otherwise. */
|
|
||||||
|
|
||||||
bool
|
|
||||||
move_fn_p (tree d)
|
|
||||||
{
|
|
||||||
tree args;
|
|
||||||
tree arg_type;
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
gcc_assert (DECL_FUNCTION_MEMBER_P (d));
|
|
||||||
|
|
||||||
if (!flag_cpp0x)
|
|
||||||
/* There are no move constructors if we aren't in C++0x mode. */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (TREE_CODE (d) == TEMPLATE_DECL
|
|
||||||
|| (DECL_TEMPLATE_INFO (d)
|
|
||||||
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
|
|
||||||
/* Instantiations of template member functions are never copy
|
|
||||||
functions. Note that member functions of templated classes are
|
|
||||||
represented as template functions internally, and we must
|
|
||||||
accept those as copy functions. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
args = FUNCTION_FIRST_USER_PARMTYPE (d);
|
|
||||||
if (!args)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
arg_type = TREE_VALUE (args);
|
|
||||||
if (arg_type == error_mark_node)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (TREE_CODE (arg_type) == REFERENCE_TYPE
|
|
||||||
&& TYPE_REF_IS_RVALUE (arg_type)
|
|
||||||
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)),
|
|
||||||
DECL_CONTEXT (d)))
|
|
||||||
result = true;
|
|
||||||
|
|
||||||
args = TREE_CHAIN (args);
|
|
||||||
|
|
||||||
if (args && args != void_list_node && !TREE_PURPOSE (args))
|
|
||||||
/* There are more non-optional args. */
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember any special properties of member function DECL. */
|
/* Remember any special properties of member function DECL. */
|
||||||
|
|
||||||
void grok_special_member_properties (tree decl)
|
void grok_special_member_properties (tree decl)
|
||||||
|
@ -507,15 +507,7 @@ dump_type_prefix (tree t, int flags)
|
|||||||
pp_cxx_whitespace (cxx_pp);
|
pp_cxx_whitespace (cxx_pp);
|
||||||
pp_cxx_left_paren (cxx_pp);
|
pp_cxx_left_paren (cxx_pp);
|
||||||
}
|
}
|
||||||
if (TREE_CODE (t) == POINTER_TYPE)
|
pp_character (cxx_pp, "&*"[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_base (cxx_pp)->padding = pp_before;
|
||||||
pp_cxx_cv_qualifier_seq (cxx_pp, t);
|
pp_cxx_cv_qualifier_seq (cxx_pp, t);
|
||||||
}
|
}
|
||||||
|
@ -709,25 +709,12 @@ build_throw (tree exp)
|
|||||||
/* And initialize the exception object. */
|
/* And initialize the exception object. */
|
||||||
if (CLASS_TYPE_P (temp_type))
|
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 must not have the `volatile' qualifier. */
|
|
||||||
&& !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
|
|
||||||
flags = flags | LOOKUP_PREFER_RVALUE;
|
|
||||||
|
|
||||||
/* Call the copy constructor. */
|
/* Call the copy constructor. */
|
||||||
exp = (build_special_member_call
|
exp = (build_special_member_call
|
||||||
(object, complete_ctor_identifier,
|
(object, complete_ctor_identifier,
|
||||||
build_tree_list (NULL_TREE, exp),
|
build_tree_list (NULL_TREE, exp),
|
||||||
TREE_TYPE (object),
|
TREE_TYPE (object),
|
||||||
flags));
|
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
|
||||||
if (exp == error_mark_node)
|
if (exp == error_mark_node)
|
||||||
{
|
{
|
||||||
error (" in thrown expression");
|
error (" in thrown expression");
|
||||||
|
@ -1541,10 +1541,6 @@ write_local_name (const tree function, const tree local_entity,
|
|||||||
::= G <type> # imaginary (C 2000) [not supported]
|
::= G <type> # imaginary (C 2000) [not supported]
|
||||||
::= U <source-name> <type> # vendor extended type qualifier
|
::= U <source-name> <type> # vendor extended type qualifier
|
||||||
|
|
||||||
C++0x extensions
|
|
||||||
|
|
||||||
<type> ::= RR <type> # rvalue reference-to
|
|
||||||
|
|
||||||
TYPE is a type node. */
|
TYPE is a type node. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1639,8 +1635,6 @@ write_type (tree type)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case REFERENCE_TYPE:
|
case REFERENCE_TYPE:
|
||||||
if (TYPE_REF_IS_RVALUE (type))
|
|
||||||
write_char('R');
|
|
||||||
write_char ('R');
|
write_char ('R');
|
||||||
write_type (TREE_TYPE (type));
|
write_type (TREE_TYPE (type));
|
||||||
break;
|
break;
|
||||||
|
@ -843,7 +843,7 @@ static cp_declarator *make_array_declarator
|
|||||||
static cp_declarator *make_pointer_declarator
|
static cp_declarator *make_pointer_declarator
|
||||||
(cp_cv_quals, cp_declarator *);
|
(cp_cv_quals, cp_declarator *);
|
||||||
static cp_declarator *make_reference_declarator
|
static cp_declarator *make_reference_declarator
|
||||||
(cp_cv_quals, cp_declarator *, bool);
|
(cp_cv_quals, cp_declarator *);
|
||||||
static cp_parameter_declarator *make_parameter_declarator
|
static cp_parameter_declarator *make_parameter_declarator
|
||||||
(cp_decl_specifier_seq *, cp_declarator *, tree);
|
(cp_decl_specifier_seq *, cp_declarator *, tree);
|
||||||
static cp_declarator *make_ptrmem_declarator
|
static cp_declarator *make_ptrmem_declarator
|
||||||
@ -937,15 +937,14 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
|
|||||||
/* Like make_pointer_declarator -- but for references. */
|
/* Like make_pointer_declarator -- but for references. */
|
||||||
|
|
||||||
cp_declarator *
|
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;
|
cp_declarator *declarator;
|
||||||
|
|
||||||
declarator = make_declarator (cdk_reference);
|
declarator = make_declarator (cdk_reference);
|
||||||
declarator->declarator = target;
|
declarator->declarator = target;
|
||||||
declarator->u.reference.qualifiers = cv_qualifiers;
|
declarator->u.pointer.qualifiers = cv_qualifiers;
|
||||||
declarator->u.reference.rvalue_ref = rvalue_ref;
|
declarator->u.pointer.class_type = NULL_TREE;
|
||||||
|
|
||||||
return declarator;
|
return declarator;
|
||||||
}
|
}
|
||||||
@ -1927,8 +1926,6 @@ static bool cp_parser_is_keyword
|
|||||||
(cp_token *, enum rid);
|
(cp_token *, enum rid);
|
||||||
static tree cp_parser_make_typename_type
|
static tree cp_parser_make_typename_type
|
||||||
(cp_parser *, tree, tree);
|
(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. */
|
/* Returns nonzero if we are parsing tentatively. */
|
||||||
|
|
||||||
@ -2602,27 +2599,6 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
|
|||||||
return make_typename_type (scope, id, typename_type, tf_error);
|
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. */
|
/* Create a new C++ parser. */
|
||||||
|
|
||||||
@ -5411,8 +5387,15 @@ cp_parser_new_declarator_opt (cp_parser* parser)
|
|||||||
/* Parse another optional declarator. */
|
/* Parse another optional declarator. */
|
||||||
declarator = cp_parser_new_declarator_opt (parser);
|
declarator = cp_parser_new_declarator_opt (parser);
|
||||||
|
|
||||||
return cp_parser_make_indirect_declarator
|
/* Create the representation of the declarator. */
|
||||||
(code, type, cv_quals, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the next token is a `[', there is a direct-new-declarator. */
|
/* If the next token is a `[', there is a direct-new-declarator. */
|
||||||
@ -8071,8 +8054,16 @@ cp_parser_conversion_declarator_opt (cp_parser* parser)
|
|||||||
/* Parse another optional declarator. */
|
/* Parse another optional declarator. */
|
||||||
declarator = cp_parser_conversion_declarator_opt (parser);
|
declarator = cp_parser_conversion_declarator_opt (parser);
|
||||||
|
|
||||||
return cp_parser_make_indirect_declarator
|
/* Create the representation of the declarator. */
|
||||||
(code, class_type, cv_quals, 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 NULL;
|
return NULL;
|
||||||
@ -11531,8 +11522,15 @@ cp_parser_declarator (cp_parser* parser,
|
|||||||
&& !cp_parser_parse_definitely (parser))
|
&& !cp_parser_parse_definitely (parser))
|
||||||
declarator = NULL;
|
declarator = NULL;
|
||||||
|
|
||||||
declarator = cp_parser_make_indirect_declarator
|
/* Build the representation of the ptr-operator. */
|
||||||
(code, class_type, cv_quals, 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);
|
||||||
}
|
}
|
||||||
/* Everything else is a direct-declarator. */
|
/* Everything else is a direct-declarator. */
|
||||||
else
|
else
|
||||||
@ -11973,15 +11971,12 @@ cp_parser_direct_declarator (cp_parser* parser,
|
|||||||
& cv-qualifier-seq [opt]
|
& cv-qualifier-seq [opt]
|
||||||
|
|
||||||
Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
|
Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
|
||||||
Returns ADDR_EXPR if a reference was used, or NON_LVALUE_EXPR for
|
Returns ADDR_EXPR if a reference was used. In the case of a
|
||||||
an rvalue reference. In the case of a pointer-to-member, *TYPE is
|
pointer-to-member, *TYPE is filled in with the TYPE containing the
|
||||||
filled in with the TYPE containing the member. *CV_QUALS is
|
member. *CV_QUALS is filled in with the cv-qualifier-seq, or
|
||||||
filled in with the cv-qualifier-seq, or TYPE_UNQUALIFIED, if there
|
TYPE_UNQUALIFIED, if there are no cv-qualifiers. Returns
|
||||||
are no cv-qualifiers. Returns ERROR_MARK if an error occurred.
|
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
|
static enum tree_code
|
||||||
cp_parser_ptr_operator (cp_parser* parser,
|
cp_parser_ptr_operator (cp_parser* parser,
|
||||||
tree* type,
|
tree* type,
|
||||||
@ -11997,18 +11992,13 @@ cp_parser_ptr_operator (cp_parser* parser,
|
|||||||
|
|
||||||
/* Peek at the next token. */
|
/* Peek at the next token. */
|
||||||
token = cp_lexer_peek_token (parser->lexer);
|
token = cp_lexer_peek_token (parser->lexer);
|
||||||
|
/* If it's a `*' or `&' we have a pointer or reference. */
|
||||||
/* If it's a `*', `&' or `&&' we have a pointer or reference. */
|
if (token->type == CPP_MULT || token->type == CPP_AND)
|
||||||
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 `&&'. */
|
/* Remember which ptr-operator we were processing. */
|
||||||
|
code = (token->type == CPP_AND ? ADDR_EXPR : INDIRECT_REF);
|
||||||
|
|
||||||
|
/* Consume the `*' or `&'. */
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
|
|
||||||
/* A `*' can be followed by a cv-qualifier-seq, and so can a
|
/* A `*' can be followed by a cv-qualifier-seq, and so can a
|
||||||
|
@ -110,8 +110,7 @@ static void tsubst_enum (tree, tree, tree);
|
|||||||
static tree add_to_template_args (tree, tree);
|
static tree add_to_template_args (tree, tree);
|
||||||
static tree add_outermost_template_args (tree, tree);
|
static tree add_outermost_template_args (tree, tree);
|
||||||
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
|
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,
|
static int type_unification_real (tree, tree, tree, tree,
|
||||||
int, unification_kind_t, int);
|
int, unification_kind_t, int);
|
||||||
static void note_template_header (int);
|
static void note_template_header (int);
|
||||||
@ -7547,13 +7546,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||||||
|
|
||||||
-- Attempting to create a pointer to reference type.
|
-- Attempting to create a pointer to reference type.
|
||||||
-- Attempting to create a reference to a reference type or
|
-- Attempting to create a reference to a reference type or
|
||||||
a reference to void.
|
a reference to void. */
|
||||||
|
if (TREE_CODE (type) == REFERENCE_TYPE
|
||||||
Core issue 106 says that creating a reference to a reference
|
|
||||||
during instantiation is no longer a cause for failure. We
|
|
||||||
only enforce this check in strict C++98 mode. */
|
|
||||||
if ((TREE_CODE (type) == REFERENCE_TYPE
|
|
||||||
&& ((!flag_cpp0x && flag_iso) || code != REFERENCE_TYPE))
|
|
||||||
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
|
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
|
||||||
{
|
{
|
||||||
static location_t last_loc;
|
static location_t last_loc;
|
||||||
@ -7587,22 +7581,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||||||
if (TREE_CODE (type) == METHOD_TYPE)
|
if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
r = build_ptrmemfunc_type (r);
|
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]:
|
|
||||||
|
|
||||||
"If a template-argument for a template-parameter T names a type
|
|
||||||
that is a reference to a type A, an attempt to create the type
|
|
||||||
'lvalue reference to cv T' creates the type 'lvalue reference to
|
|
||||||
A,' while an attempt to create the type type rvalue reference to
|
|
||||||
cv T' creates the type T"
|
|
||||||
*/
|
|
||||||
r = cp_build_reference_type
|
|
||||||
(TREE_TYPE (type),
|
|
||||||
TYPE_REF_IS_RVALUE (t) && TYPE_REF_IS_RVALUE (type));
|
|
||||||
else
|
else
|
||||||
r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
|
r = build_reference_type (type);
|
||||||
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
|
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
|
||||||
|
|
||||||
if (r != error_mark_node)
|
if (r != error_mark_node)
|
||||||
@ -9812,14 +9792,12 @@ fn_type_unification (tree fn,
|
|||||||
sections are symmetric. PARM is the type of a function parameter
|
sections are symmetric. PARM is the type of a function parameter
|
||||||
or the return type of the conversion function. ARG is the type of
|
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
|
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
|
static int
|
||||||
maybe_adjust_types_for_deduction (unification_kind_t strict,
|
maybe_adjust_types_for_deduction (unification_kind_t strict,
|
||||||
tree* parm,
|
tree* parm,
|
||||||
tree* arg,
|
tree* arg)
|
||||||
tree arg_expr)
|
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
@ -9873,16 +9851,6 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
|
|||||||
*arg = TYPE_MAIN_VARIANT (*arg);
|
*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]
|
/* [temp.deduct.call]
|
||||||
|
|
||||||
If P is a cv-qualified type, the top level cv-qualifiers
|
If P is a cv-qualified type, the top level cv-qualifiers
|
||||||
@ -9919,7 +9887,7 @@ type_unification_real (tree tparms,
|
|||||||
unification_kind_t strict,
|
unification_kind_t strict,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
tree parm, arg, arg_expr;
|
tree parm, arg;
|
||||||
int i;
|
int i;
|
||||||
int ntparms = TREE_VEC_LENGTH (tparms);
|
int ntparms = TREE_VEC_LENGTH (tparms);
|
||||||
int sub_strict;
|
int sub_strict;
|
||||||
@ -9961,7 +9929,6 @@ type_unification_real (tree tparms,
|
|||||||
parms = TREE_CHAIN (parms);
|
parms = TREE_CHAIN (parms);
|
||||||
arg = TREE_VALUE (args);
|
arg = TREE_VALUE (args);
|
||||||
args = TREE_CHAIN (args);
|
args = TREE_CHAIN (args);
|
||||||
arg_expr = NULL;
|
|
||||||
|
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
return 1;
|
return 1;
|
||||||
@ -10011,7 +9978,6 @@ type_unification_real (tree tparms,
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
arg_expr = arg;
|
|
||||||
arg = unlowered_expr_type (arg);
|
arg = unlowered_expr_type (arg);
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
return 1;
|
return 1;
|
||||||
@ -10021,8 +9987,7 @@ type_unification_real (tree tparms,
|
|||||||
int arg_strict = sub_strict;
|
int arg_strict = sub_strict;
|
||||||
|
|
||||||
if (!subr)
|
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))
|
if (unify (tparms, targs, parm, arg, arg_strict))
|
||||||
return 1;
|
return 1;
|
||||||
@ -10199,7 +10164,7 @@ try_one_overload (tree tparms,
|
|||||||
else if (addr_p)
|
else if (addr_p)
|
||||||
arg = build_pointer_type (arg);
|
arg = build_pointer_type (arg);
|
||||||
|
|
||||||
sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL);
|
sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
|
||||||
|
|
||||||
/* We don't copy orig_targs for this because if we have already deduced
|
/* 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
|
some template args from previous args, unify would complain when we
|
||||||
|
@ -64,28 +64,8 @@ lvalue_p_1 (tree ref,
|
|||||||
cp_lvalue_kind op1_lvalue_kind = clk_none;
|
cp_lvalue_kind op1_lvalue_kind = clk_none;
|
||||||
cp_lvalue_kind op2_lvalue_kind = clk_none;
|
cp_lvalue_kind op2_lvalue_kind = clk_none;
|
||||||
|
|
||||||
/* Expressions of reference type are sometimes wrapped in
|
|
||||||
INDIRECT_REFs. INDIRECT_REFs are just internal compiler
|
|
||||||
representation, not part of the language, so we have to look
|
|
||||||
through them. */
|
|
||||||
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)
|
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)
|
if (ref == current_class_ptr)
|
||||||
return clk_none;
|
return clk_none;
|
||||||
@ -471,53 +451,6 @@ build_cplus_array_type (tree elt_type, tree index_type)
|
|||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a reference type node referring to TO_TYPE. If RVAL is
|
|
||||||
true, return an rvalue reference type, otherwise return an lvalue
|
|
||||||
reference type. If a type node exists, reuse it, otherwise create
|
|
||||||
a new one. */
|
|
||||||
tree
|
|
||||||
cp_build_reference_type (tree to_type, bool rval)
|
|
||||||
{
|
|
||||||
tree lvalue_ref, t;
|
|
||||||
lvalue_ref = build_reference_type (to_type);
|
|
||||||
if (!rval)
|
|
||||||
return lvalue_ref;
|
|
||||||
|
|
||||||
/* This code to create rvalue reference types is based on and tied
|
|
||||||
to the code creating lvalue reference types in the middle-end
|
|
||||||
functions build_reference_type_for_mode and build_reference_type.
|
|
||||||
|
|
||||||
It works by putting the rvalue reference type nodes after the
|
|
||||||
lvalue reference nodes in the TYPE_NEXT_REF_TO linked list, so
|
|
||||||
they will effectively be ignored by the middle end. */
|
|
||||||
|
|
||||||
for (t = lvalue_ref; (t = TYPE_NEXT_REF_TO (t)); )
|
|
||||||
if (TYPE_REF_IS_RVALUE (t))
|
|
||||||
return t;
|
|
||||||
|
|
||||||
t = copy_node (lvalue_ref);
|
|
||||||
|
|
||||||
TYPE_REF_IS_RVALUE (t) = true;
|
|
||||||
TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
|
|
||||||
TYPE_NEXT_REF_TO (lvalue_ref) = t;
|
|
||||||
TYPE_MAIN_VARIANT (t) = t;
|
|
||||||
|
|
||||||
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
|
|
||||||
SET_TYPE_STRUCTURAL_EQUALITY (t);
|
|
||||||
else if (TYPE_CANONICAL (to_type) != to_type)
|
|
||||||
TYPE_CANONICAL (t)
|
|
||||||
= cp_build_reference_type (TYPE_CANONICAL (to_type), rval);
|
|
||||||
else
|
|
||||||
TYPE_CANONICAL (t) = t;
|
|
||||||
|
|
||||||
layout_type (t);
|
|
||||||
|
|
||||||
return t;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
|
/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
|
||||||
arrays correctly. In particular, if TYPE is an array of T's, and
|
arrays correctly. In particular, if TYPE is an array of T's, and
|
||||||
|
@ -1039,12 +1039,8 @@ comptypes (tree t1, tree t2, int strict)
|
|||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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:
|
case POINTER_TYPE:
|
||||||
|
case REFERENCE_TYPE:
|
||||||
if (TYPE_MODE (t1) != TYPE_MODE (t2)
|
if (TYPE_MODE (t1) != TYPE_MODE (t2)
|
||||||
|| TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)
|
|| TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)
|
||||||
|| !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
|| !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
||||||
@ -6503,7 +6499,6 @@ check_return_expr (tree retval, bool *no_warning)
|
|||||||
promotions. */
|
promotions. */
|
||||||
tree valtype;
|
tree valtype;
|
||||||
int fn_returns_value_p;
|
int fn_returns_value_p;
|
||||||
bool named_return_value_okay_p;
|
|
||||||
|
|
||||||
*no_warning = false;
|
*no_warning = false;
|
||||||
|
|
||||||
@ -6651,26 +6646,21 @@ check_return_expr (tree retval, bool *no_warning)
|
|||||||
|
|
||||||
See finish_function and finalize_nrv for the rest of this optimization. */
|
See finish_function and finalize_nrv for the rest of this optimization. */
|
||||||
|
|
||||||
named_return_value_okay_p =
|
|
||||||
(retval != NULL_TREE
|
|
||||||
/* 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 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))))));
|
|
||||||
|
|
||||||
if (fn_returns_value_p && flag_elide_constructors)
|
if (fn_returns_value_p && flag_elide_constructors)
|
||||||
{
|
{
|
||||||
if (named_return_value_okay_p
|
if (retval != NULL_TREE
|
||||||
&& (current_function_return_value == NULL_TREE
|
&& (current_function_return_value == NULL_TREE
|
||||||
|| current_function_return_value == retval))
|
|| current_function_return_value == retval)
|
||||||
|
&& TREE_CODE (retval) == VAR_DECL
|
||||||
|
&& DECL_CONTEXT (retval) == current_function_decl
|
||||||
|
&& ! TREE_STATIC (retval)
|
||||||
|
&& ! DECL_ANON_UNION_VAR_P (retval)
|
||||||
|
&& (DECL_ALIGN (retval)
|
||||||
|
>= DECL_ALIGN (DECL_RESULT (current_function_decl)))
|
||||||
|
&& same_type_p ((TYPE_MAIN_VARIANT
|
||||||
|
(TREE_TYPE (retval))),
|
||||||
|
(TYPE_MAIN_VARIANT
|
||||||
|
(TREE_TYPE (TREE_TYPE (current_function_decl))))))
|
||||||
current_function_return_value = retval;
|
current_function_return_value = retval;
|
||||||
else
|
else
|
||||||
current_function_return_value = error_mark_node;
|
current_function_return_value = error_mark_node;
|
||||||
@ -6689,29 +6679,18 @@ check_return_expr (tree retval, bool *no_warning)
|
|||||||
{
|
{
|
||||||
/* The type the function is declared to return. */
|
/* The type the function is declared to return. */
|
||||||
tree functype = TREE_TYPE (TREE_TYPE (current_function_decl));
|
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
|
/* The functype's return type will have been set to void, if it
|
||||||
was an incomplete type. Just treat this as 'return;' */
|
was an incomplete type. Just treat this as 'return;' */
|
||||||
if (VOID_TYPE_P (functype))
|
if (VOID_TYPE_P (functype))
|
||||||
return error_mark_node;
|
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 (flag_cpp0x
|
|
||||||
&& named_return_value_okay_p
|
|
||||||
/* The variable must 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))))
|
|
||||||
flags = flags | LOOKUP_PREFER_RVALUE;
|
|
||||||
|
|
||||||
/* First convert the value to the function's return type, then
|
/* First convert the value to the function's return type, then
|
||||||
to the type of return value's location to handle the
|
to the type of return value's location to handle the
|
||||||
case that functype is smaller than the valtype. */
|
case that functype is smaller than the valtype. */
|
||||||
retval = convert_for_initialization
|
retval = convert_for_initialization
|
||||||
(NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0);
|
(NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
|
||||||
|
"return", NULL_TREE, 0);
|
||||||
retval = convert (valtype, retval);
|
retval = convert (valtype, retval);
|
||||||
|
|
||||||
/* If the conversion failed, treat this just like `return;'. */
|
/* If the conversion failed, treat this just like `return;'. */
|
||||||
|
Loading…
Reference in New Issue
Block a user