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:
Pedro F. Giffuni 2013-12-20 18:09:34 +00:00
parent ba981145d6
commit cc1a345c65
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=259660
11 changed files with 105 additions and 498 deletions

View File

@ -35,65 +35,6 @@
* 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)
* mangle.c (write_real_cst): Use 'unsigned long' for %lx.

View File

@ -95,10 +95,6 @@ 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 rvaluedness_matches_p: 1;
/* The type of the expression resulting from the conversion. */
tree type;
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 *build_conv (conversion_kind, tree, 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 struct z_candidate *add_candidate
(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]. */
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 arglist;
conversion *conv;
tree t;
tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
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_tree_list (NULL_TREE, arglist);
t = TREE_TYPE (reference_type);
reference_type = build_reference_type (t);
while (conversions)
{
@ -1001,9 +997,6 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
cand->second_conv
= (direct_reference_binding
(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;
}
}
@ -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));
compatible_p = reference_compatible_p (to, from);
/* 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))))
if (lvalue_p && compatible_p)
{
/* [dcl.init.ref]
@ -1152,15 +1136,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
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->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
|| ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
/* 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
in the second case. */
conv = convert_class_to_reference (rto, from, expr);
conv = convert_class_to_reference (to, from, expr);
if (conv)
return conv;
}
@ -1216,10 +1191,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
/* [dcl.init.ref]
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))
Otherwise, the reference shall be to a non-volatile const type. */
if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
return NULL;
/* [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 = direct_reference_binding (rto, conv);
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
conv->u.next->check_copy_constructor_p = true;
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
creation of a temporary. */
conv->need_temporary_p = true;
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
return conv;
}
@ -1309,7 +1280,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
conv = cand->second_conv;
/* 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. */
return conv;
}
@ -4438,22 +4409,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
tree ref_type = totype;
/* If necessary, create a temporary.
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)
/* If necessary, create a temporary. */
if (convs->need_temporary_p || !lvalue_p (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))
&& !TYPE_REF_IS_RVALUE (ref_type))
if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
{
/* If the reference is volatile or non-const, we
cannot create a temporary. */
@ -4976,9 +4938,7 @@ build_over_call (struct z_candidate *cand, int flags)
if (! flag_elide_constructors)
/* Do things the hard way. */;
else if (cand->num_convs == 1
&& (DECL_COPY_CONSTRUCTOR_P (fn)
|| DECL_MOVE_CONSTRUCTOR_P (fn)))
else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn))
{
tree targ;
arg = skip_artificial_parms_for (fn, converted_args);
@ -5716,28 +5676,28 @@ maybe_handle_implicit_object (conversion **ics)
t = t->u.next;
t = build_identity_conv (TREE_TYPE (t->type), NULL_TREE);
t = direct_reference_binding (reference_type, t);
t->rvaluedness_matches_p = 1;
*ics = t;
}
}
/* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
and return the initial reference binding conversion. Otherwise,
leave *ICS unchanged and return NULL. */
and return the type to which the reference refers. Otherwise,
leave *ICS unchanged and return NULL_TREE. */
static conversion *
static tree
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 old_ics;
return type;
}
return NULL;
return NULL_TREE;
}
/* 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;
/* REF_BINDING is nonzero if the result of the conversion sequence
is a reference type. In that case REF_CONV is the reference
binding conversion. */
conversion *ref_conv1;
conversion *ref_conv2;
is a reference type. In that case TARGET_TYPE is the
type referred to by the reference. */
tree target_type1;
tree target_type2;
/* Handle implicit object parameters. */
maybe_handle_implicit_object (&ics1);
maybe_handle_implicit_object (&ics2);
/* Handle reference parameters. */
ref_conv1 = maybe_handle_ref_bind (&ics1);
ref_conv2 = maybe_handle_ref_bind (&ics2);
target_type1 = maybe_handle_ref_bind (&ics1);
target_type2 = maybe_handle_ref_bind (&ics2);
/* [over.ics.rank]
@ -6063,31 +6023,15 @@ compare_ics (conversion *ics1, conversion *ics2)
/* [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 (ref_conv1 && ref_conv2
if (target_type1 && target_type2
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
{
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));
}
return comp_cv_qualification (target_type2, target_type1);
/* Neither conversion sequence is better than the other. */
return 0;

View File

@ -56,7 +56,6 @@ struct diagnostic_context;
OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@ -1667,10 +1666,6 @@ struct lang_decl GTY(())
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
(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. */
#define DECL_DESTRUCTOR_P(NODE) \
(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) \
(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
void. Keep these checks in ascending tree code order. */
#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
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))
@ -3761,21 +3750,13 @@ struct cp_declarator {
/* The bounds to the array. */
tree bounds;
} array;
/* For cdk_pointer and cdk_ptrmem. */
/* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
struct {
/* The cv-qualifiers for the pointer. */
cp_cv_quals qualifiers;
/* For cdk_ptrmem, the class type containing the member. */
tree class_type;
} 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;
};
@ -3936,7 +3917,6 @@ extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */
extern tree build_this_parm (tree, cp_cv_quals);
extern int copy_fn_p (tree);
extern bool move_fn_p (tree);
extern tree get_scope_of_declarator (const cp_declarator *);
extern void grok_special_member_properties (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 tree make_ptrmem_cst (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);
#define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)

View File

@ -7823,24 +7823,10 @@ grokdeclarator (const cp_declarator *declarator,
if (TREE_CODE (type) == REFERENCE_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);
}
error (declarator->kind == cdk_reference
? "cannot declare reference to %q#T"
: "cannot declare pointer to %q#T", type);
type = TREE_TYPE (type);
}
else if (VOID_TYPE_P (type))
{
@ -7866,39 +7852,8 @@ grokdeclarator (const cp_declarator *declarator,
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))
type = cp_build_reference_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);
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
@ -9123,7 +9078,6 @@ 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)))
@ -9141,57 +9095,6 @@ copy_fn_p (tree d)
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. */
void grok_special_member_properties (tree decl)

View File

@ -507,15 +507,7 @@ dump_type_prefix (tree t, int flags)
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
}
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_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]);
pp_base (cxx_pp)->padding = pp_before;
pp_cxx_cv_qualifier_seq (cxx_pp, t);
}

View File

@ -709,25 +709,12 @@ 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 must 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),
flags));
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
if (exp == error_mark_node)
{
error (" in thrown expression");

View File

@ -1541,10 +1541,6 @@ write_local_name (const tree function, const tree local_entity,
::= G <type> # imaginary (C 2000) [not supported]
::= U <source-name> <type> # vendor extended type qualifier
C++0x extensions
<type> ::= RR <type> # rvalue reference-to
TYPE is a type node. */
static void
@ -1639,8 +1635,6 @@ write_type (tree type)
break;
case REFERENCE_TYPE:
if (TYPE_REF_IS_RVALUE (type))
write_char('R');
write_char ('R');
write_type (TREE_TYPE (type));
break;

View File

@ -843,7 +843,7 @@ static cp_declarator *make_array_declarator
static cp_declarator *make_pointer_declarator
(cp_cv_quals, cp_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
(cp_decl_specifier_seq *, cp_declarator *, tree);
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. */
cp_declarator *
make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
bool rvalue_ref)
make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_reference);
declarator->declarator = target;
declarator->u.reference.qualifiers = cv_qualifiers;
declarator->u.reference.rvalue_ref = rvalue_ref;
declarator->u.pointer.qualifiers = cv_qualifiers;
declarator->u.pointer.class_type = NULL_TREE;
return declarator;
}
@ -1927,8 +1926,6 @@ 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. */
@ -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);
}
/* 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. */
@ -5411,8 +5387,15 @@ cp_parser_new_declarator_opt (cp_parser* parser)
/* Parse another optional declarator. */
declarator = cp_parser_new_declarator_opt (parser);
return cp_parser_make_indirect_declarator
(code, type, cv_quals, declarator);
/* 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;
}
/* 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. */
declarator = cp_parser_conversion_declarator_opt (parser);
return cp_parser_make_indirect_declarator
(code, class_type, cv_quals, declarator);
/* 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 NULL;
@ -11531,8 +11522,15 @@ cp_parser_declarator (cp_parser* parser,
&& !cp_parser_parse_definitely (parser))
declarator = NULL;
declarator = cp_parser_make_indirect_declarator
(code, class_type, cv_quals, declarator);
/* 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);
}
/* Everything else is a direct-declarator. */
else
@ -11973,15 +11971,12 @@ cp_parser_direct_declarator (cp_parser* 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, 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. */
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. */
static enum tree_code
cp_parser_ptr_operator (cp_parser* parser,
tree* type,
@ -11997,18 +11992,13 @@ cp_parser_ptr_operator (cp_parser* parser,
/* 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)
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)
/* If it's a `*' or `&' we have a pointer or reference. */
if (token->type == CPP_MULT || token->type == CPP_AND)
{
/* 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);
/* A `*' can be followed by a cv-qualifier-seq, and so can a

View File

@ -110,8 +110,7 @@ static void tsubst_enum (tree, tree, tree);
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*,
tree);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
static int type_unification_real (tree, tree, tree, tree,
int, unification_kind_t, 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 reference to a reference type or
a reference to void.
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))
a reference to void. */
if (TREE_CODE (type) == REFERENCE_TYPE
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{
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)
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
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);
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
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.
ARG_EXPR is the original argument expression, which may be null. */
initialized with the result of the conversion function. */
static int
maybe_adjust_types_for_deduction (unification_kind_t strict,
tree* parm,
tree* arg,
tree arg_expr)
tree* arg)
{
int result = 0;
@ -9873,16 +9851,6 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
*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
@ -9919,7 +9887,7 @@ type_unification_real (tree tparms,
unification_kind_t strict,
int flags)
{
tree parm, arg, arg_expr;
tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
@ -9961,7 +9929,6 @@ 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;
@ -10011,7 +9978,6 @@ type_unification_real (tree tparms,
return 1;
}
arg_expr = arg;
arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
return 1;
@ -10021,8 +9987,7 @@ type_unification_real (tree tparms,
int arg_strict = sub_strict;
if (!subr)
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
arg_expr);
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
if (unify (tparms, targs, parm, arg, arg_strict))
return 1;
@ -10199,7 +10164,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, 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
some template args from previous args, unify would complain when we

View File

@ -64,28 +64,8 @@ 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. 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)
{
/* 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;
}
return clk_ordinary;
if (ref == current_class_ptr)
return clk_none;
@ -471,53 +451,6 @@ build_cplus_array_type (tree elt_type, tree index_type)
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
arrays correctly. In particular, if TYPE is an array of T's, and

View File

@ -1039,12 +1039,8 @@ comptypes (tree t1, tree t2, int strict)
return false;
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 REFERENCE_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)))
@ -6503,7 +6499,6 @@ check_return_expr (tree retval, bool *no_warning)
promotions. */
tree valtype;
int fn_returns_value_p;
bool named_return_value_okay_p;
*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. */
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 (named_return_value_okay_p
&& (current_function_return_value == NULL_TREE
|| current_function_return_value == retval))
if (retval != NULL_TREE
&& (current_function_return_value == NULL_TREE
|| 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;
else
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. */
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 (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
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, flags, "return", NULL_TREE, 0);
(NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
"return", NULL_TREE, 0);
retval = convert (valtype, retval);
/* If the conversion failed, treat this just like `return;'. */