Commit 7993382e by Mark Mitchell Committed by Mark Mitchell

re PR c++/9878 (error: non-lvalue in unary `&' wrongly issued)

	PR c++/9878
	* call.c (convert_class_to_reference): Correct conversion
	sequences.
	(reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
	(implicit_conversion): Adjust call to reference_binding.
	(add_candidate): Change type of candidates parameter.
	(add_function_candidate): Likewise.
	(add_conv_candidate): Likewise.
	(build_builtin_candidate): Likewise.
	(add_builtin_candidate): Likewise.
	(add_builtin_candidates): Likewise.
	(add_template_candidate_real): Likewise.
	(add_template_candidate): Likewise.
	(add_template_conv_candidate): Likewise.
	(build_user_type_conversion_1): Adjust accordingly.
	(build_object_call): Likewise.
	(build_conditional_expr): Likewise.
	(add_candidates): Likewise.
	(build_new_op): Likewise.
	(convert_like_real): Use USER_CONV_CAND.  Use build_nop.
	(build_new_method_call): Adjust calls to add_function_candidate.
	(make_temporary_var_for_ref_to_temp): New function.
	(initialize_reference): Add decl parameter.
	* class.c (build_rtti_vtbl_entries): Use build_address and
	build_nop.
	* cp-tree.h (initialize_reference): Change prototype.
	(make_temporary_var_for_ref_to_temp): New function.
	(build_type_conversion): Change prototype.
	(build_address): New function.
	(build_nop): Likewise.
	* cvt.c (cp_convert_to_pointer): Adjust call to
	build_type_conversion.  Avoid indicating redundant NOP_EXPRs.
	Use build_nop.
	(convert_to_pointer_force): Use build_nop.
	(build_up_reference): Use make_temporary_var_for_ref_to_temp.
	(convert_to_reference): Adjust call to build_type_conversion.
	(ocp_convert): Likewise.
	(build_type_conversion): Remove for_sure parameter.
	* decl.c (grok_reference_init): Use initialize_reference.
	* typeck.c (build_address): New function.
	(build_nop): Likewise.
	(build_unary_op): Use them.
	(build_ptrmemfunc): Tidy slightly.
	(convert_for_initialization): Adjust call to
	initialize_reference.
	* typeck2.c (store_init_value): Remove #if 0'd code.

	PR c++/9878
	* g++.dg/init/ref1.C: New test.

From-SVN: r63735
parent 03275f81
2003-03-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9878
* call.c (convert_class_to_reference): Correct conversion
sequences.
(reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
(implicit_conversion): Adjust call to reference_binding.
(add_candidate): Change type of candidates parameter.
(add_function_candidate): Likewise.
(add_conv_candidate): Likewise.
(build_builtin_candidate): Likewise.
(add_builtin_candidate): Likewise.
(add_builtin_candidates): Likewise.
(add_template_candidate_real): Likewise.
(add_template_candidate): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Adjust accordingly.
(build_object_call): Likewise.
(build_conditional_expr): Likewise.
(add_candidates): Likewise.
(build_new_op): Likewise.
(convert_like_real): Use USER_CONV_CAND. Use build_nop.
(build_new_method_call): Adjust calls to add_function_candidate.
(make_temporary_var_for_ref_to_temp): New function.
(initialize_reference): Add decl parameter.
* class.c (build_rtti_vtbl_entries): Use build_address and
build_nop.
* cp-tree.h (initialize_reference): Change prototype.
(make_temporary_var_for_ref_to_temp): New function.
(build_type_conversion): Change prototype.
(build_address): New function.
(build_nop): Likewise.
* cvt.c (cp_convert_to_pointer): Adjust call to
build_type_conversion. Avoid indicating redundant NOP_EXPRs.
Use build_nop.
(convert_to_pointer_force): Use build_nop.
(build_up_reference): Use make_temporary_var_for_ref_to_temp.
(convert_to_reference): Adjust call to build_type_conversion.
(ocp_convert): Likewise.
(build_type_conversion): Remove for_sure parameter.
* decl.c (grok_reference_init): Use initialize_reference.
* typeck.c (build_address): New function.
(build_nop): Likewise.
(build_unary_op): Use them.
(build_ptrmemfunc): Tidy slightly.
(convert_for_initialization): Adjust call to
initialize_reference.
* typeck2.c (store_init_value): Remove #if 0'd code.
2003-03-03 Jason Merrill <jason@redhat.com> 2003-03-03 Jason Merrill <jason@redhat.com>
* decl.c (start_function): Clear DECL_NUM_STMTS. * decl.c (start_function): Clear DECL_NUM_STMTS.
......
...@@ -62,37 +62,37 @@ static struct z_candidate *splice_viable (struct z_candidate *); ...@@ -62,37 +62,37 @@ static struct z_candidate *splice_viable (struct z_candidate *);
static bool any_viable (struct z_candidate *); static bool any_viable (struct z_candidate *);
static bool any_strictly_viable (struct z_candidate *); static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate static struct z_candidate *add_template_candidate
(struct z_candidate *, tree, tree, tree, tree, tree, (struct z_candidate **, tree, tree, tree, tree, tree,
tree, tree, int, unification_kind_t); tree, tree, int, unification_kind_t);
static struct z_candidate *add_template_candidate_real static struct z_candidate *add_template_candidate_real
(struct z_candidate *, tree, tree, tree, tree, tree, (struct z_candidate **, tree, tree, tree, tree, tree,
tree, tree, int, tree, unification_kind_t); tree, tree, int, tree, unification_kind_t);
static struct z_candidate *add_template_conv_candidate static struct z_candidate *add_template_conv_candidate
(struct z_candidate *, tree, tree, tree, tree, tree, tree); (struct z_candidate **, tree, tree, tree, tree, tree, tree);
static struct z_candidate *add_builtin_candidates static void add_builtin_candidates
(struct z_candidate *, enum tree_code, enum tree_code, (struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int); tree, tree *, int);
static struct z_candidate *add_builtin_candidate static void add_builtin_candidate
(struct z_candidate *, enum tree_code, enum tree_code, (struct z_candidate **, enum tree_code, enum tree_code,
tree, tree, tree, tree *, tree *, int); tree, tree, tree, tree *, tree *, int);
static bool is_complete (tree); static bool is_complete (tree);
static struct z_candidate *build_builtin_candidate static void build_builtin_candidate
(struct z_candidate *, tree, tree, tree, tree *, tree *, (struct z_candidate **, tree, tree, tree, tree *, tree *,
int); int);
static struct z_candidate *add_conv_candidate static struct z_candidate *add_conv_candidate
(struct z_candidate *, tree, tree, tree, tree, tree); (struct z_candidate **, tree, tree, tree, tree, tree);
static struct z_candidate *add_function_candidate static struct z_candidate *add_function_candidate
(struct z_candidate *, tree, tree, tree, tree, tree, int); (struct z_candidate **, tree, tree, tree, tree, tree, int);
static tree implicit_conversion (tree, tree, tree, int); static tree implicit_conversion (tree, tree, tree, int);
static tree standard_conversion (tree, tree, tree); static tree standard_conversion (tree, tree, tree);
static tree reference_binding (tree, tree, tree, int); static tree reference_binding (tree, tree, tree, int, bool *);
static tree non_reference (tree); static tree non_reference (tree);
static tree build_conv (enum tree_code, tree, tree); static tree build_conv (enum tree_code, tree, tree);
static bool is_subseq (tree, tree); static bool is_subseq (tree, tree);
static tree maybe_handle_ref_bind (tree *); static tree maybe_handle_ref_bind (tree *);
static void maybe_handle_implicit_object (tree *); static void maybe_handle_implicit_object (tree *);
static struct z_candidate *add_candidate static struct z_candidate *add_candidate
(struct z_candidate *, tree, tree, tree, tree, tree, int); (struct z_candidate **, tree, tree, tree, tree, tree, int);
static tree source_type (tree); static tree source_type (tree);
static void add_warning (struct z_candidate *, struct z_candidate *); static void add_warning (struct z_candidate *, struct z_candidate *);
static bool reference_related_p (tree, tree); static bool reference_related_p (tree, tree);
...@@ -104,8 +104,8 @@ static tree conditional_conversion (tree, tree); ...@@ -104,8 +104,8 @@ static tree conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *); static char *name_as_c_string (tree, tree, bool *);
static tree call_builtin_trap (void); static tree call_builtin_trap (void);
static tree prep_operand (tree); static tree prep_operand (tree);
static struct z_candidate *add_candidates (tree, tree, tree, tree, static void add_candidates (tree, tree, tree, tree,
int, struct z_candidate *); int, struct z_candidate **);
tree tree
build_vfield_ref (tree datum, tree type) build_vfield_ref (tree datum, tree type)
...@@ -949,9 +949,14 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -949,9 +949,14 @@ convert_class_to_reference (tree t, tree s, tree expr)
tree conversions; tree conversions;
tree arglist; tree arglist;
tree conv; tree conv;
tree reference_type;
struct z_candidate *candidates; struct z_candidate *candidates;
struct z_candidate *cand; struct z_candidate *cand;
conversions = lookup_conversions (s);
if (!conversions)
return NULL_TREE;
/* [over.match.ref] /* [over.match.ref]
Assuming that "cv1 T" is the underlying type of the reference Assuming that "cv1 T" is the underlying type of the reference
...@@ -977,10 +982,10 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -977,10 +982,10 @@ convert_class_to_reference (tree t, tree s, tree expr)
arglist = build_int_2 (0, 0); arglist = build_int_2 (0, 0);
TREE_TYPE (arglist) = build_pointer_type (s); TREE_TYPE (arglist) = build_pointer_type (s);
arglist = build_tree_list (NULL_TREE, arglist); arglist = build_tree_list (NULL_TREE, arglist);
for (conversions = lookup_conversions (s); reference_type = build_reference_type (t);
conversions;
conversions = TREE_CHAIN (conversions)) while (conversions)
{ {
tree fns = TREE_VALUE (conversions); tree fns = TREE_VALUE (conversions);
...@@ -988,44 +993,58 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -988,44 +993,58 @@ convert_class_to_reference (tree t, tree s, tree expr)
{ {
tree f = OVL_CURRENT (fns); tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f)); tree t2 = TREE_TYPE (TREE_TYPE (f));
struct z_candidate *old_candidates = candidates;
cand = NULL;
/* If this is a template function, try to get an exact /* If this is a template function, try to get an exact
match. */ match. */
if (TREE_CODE (f) == TEMPLATE_DECL) if (TREE_CODE (f) == TEMPLATE_DECL)
{ {
candidates cand = add_template_candidate (&candidates,
= add_template_candidate (candidates, f, s,
f, s, NULL_TREE,
NULL_TREE, arglist,
arglist, reference_type,
build_reference_type (t), TYPE_BINFO (s),
TYPE_BINFO (s), TREE_PURPOSE (conversions),
TREE_PURPOSE (conversions), LOOKUP_NORMAL,
LOOKUP_NORMAL, DEDUCE_CONV);
DEDUCE_CONV);
if (candidates != old_candidates) if (cand)
{ {
/* Now, see if the conversion function really returns /* Now, see if the conversion function really returns
an lvalue of the appropriate type. From the an lvalue of the appropriate type. From the
point of view of unification, simply returning an point of view of unification, simply returning an
rvalue of the right type is good enough. */ rvalue of the right type is good enough. */
f = candidates->fn; f = cand->fn;
t2 = TREE_TYPE (TREE_TYPE (f)); t2 = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (t2) != REFERENCE_TYPE if (TREE_CODE (t2) != REFERENCE_TYPE
|| !reference_compatible_p (t, TREE_TYPE (t2))) || !reference_compatible_p (t, TREE_TYPE (t2)))
candidates = candidates->next; {
candidates = candidates->next;
cand = NULL;
}
} }
} }
else if (TREE_CODE (t2) == REFERENCE_TYPE else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2))) && reference_compatible_p (t, TREE_TYPE (t2)))
candidates cand = add_function_candidate (&candidates, f, s, arglist,
= add_function_candidate (candidates, f, s, arglist, TYPE_BINFO (s),
TYPE_BINFO (s), TREE_PURPOSE (conversions),
TREE_PURPOSE (conversions), LOOKUP_NORMAL);
LOOKUP_NORMAL);
if (cand)
{
conv = build1 (IDENTITY_CONV, s, expr);
conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
conv);
TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
ICS_USER_FLAG (conv) = 1;
cand->second_conv
= direct_reference_binding (reference_type, conv);
}
} }
conversions = TREE_CHAIN (conversions);
} }
/* If none of the conversion functions worked out, let our caller /* If none of the conversion functions worked out, let our caller
...@@ -1044,15 +1063,10 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -1044,15 +1063,10 @@ convert_class_to_reference (tree t, tree s, tree expr)
build_this (expr), build_this (expr),
TREE_CHAIN (cand->args)); TREE_CHAIN (cand->args));
conv = build1 (IDENTITY_CONV, s, expr); conv = cand->second_conv;
conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
conv);
TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
ICS_USER_FLAG (conv) = 1;
if (cand->viable == -1) if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1; ICS_BAD_FLAG (conv) = 1;
cand->second_conv = conv;
return conv; return conv;
} }
...@@ -1097,10 +1111,14 @@ direct_reference_binding (tree type, tree conv) ...@@ -1097,10 +1111,14 @@ direct_reference_binding (tree type, tree conv)
purposes of reference binding. For lvalue binding, either pass a purposes of reference binding. For lvalue binding, either pass a
reference type to FROM or an lvalue expression to EXPR. If the reference type to FROM or an lvalue expression to EXPR. If the
reference will be bound to a temporary, NEED_TEMPORARY_P is set for reference will be bound to a temporary, NEED_TEMPORARY_P is set for
the conversion returned. */ the conversion returned. If non-NULL,
*REF_BOUND_DIRECTLY_TO_RVALUE_P is set to true if and only if the
conversion sequence returned binds the reference directly to an
rvalue. */
static tree static tree
reference_binding (tree rto, tree rfrom, tree expr, int flags) reference_binding (tree rto, tree rfrom, tree expr, int flags,
bool *ref_bound_directly_to_rvalue_p)
{ {
tree conv = NULL_TREE; tree conv = NULL_TREE;
tree to = TREE_TYPE (rto); tree to = TREE_TYPE (rto);
...@@ -1109,6 +1127,10 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) ...@@ -1109,6 +1127,10 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
bool compatible_p; bool compatible_p;
cp_lvalue_kind lvalue_p = clk_none; cp_lvalue_kind lvalue_p = clk_none;
/* Assume that the reference is not bound directly to an rvalue. */
if (ref_bound_directly_to_rvalue_p)
*ref_bound_directly_to_rvalue_p = false;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr)) if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{ {
expr = instantiate_type (to, expr, tf_none); expr = instantiate_type (to, expr, tf_none);
...@@ -1178,7 +1200,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) ...@@ -1178,7 +1200,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
in the second case. */ in the second case. */
conv = convert_class_to_reference (to, from, expr); conv = convert_class_to_reference (to, from, expr);
if (conv) if (conv)
return direct_reference_binding (rto, conv); return conv;
} }
/* From this point on, we conceptually need temporaries, even if we /* From this point on, we conceptually need temporaries, even if we
...@@ -1219,6 +1241,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) ...@@ -1219,6 +1241,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
for direct binding. */ for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p) if (CLASS_TYPE_P (from) && compatible_p)
{ {
if (ref_bound_directly_to_rvalue_p)
*ref_bound_directly_to_rvalue_p = true;
conv = build1 (IDENTITY_CONV, from, expr); conv = build1 (IDENTITY_CONV, from, expr);
return direct_reference_binding (rto, conv); return direct_reference_binding (rto, conv);
} }
...@@ -1254,7 +1278,6 @@ static tree ...@@ -1254,7 +1278,6 @@ static tree
implicit_conversion (tree to, tree from, tree expr, int flags) implicit_conversion (tree to, tree from, tree expr, int flags)
{ {
tree conv; tree conv;
struct z_candidate *cand;
/* Resolve expressions like `A::p' that we thought might become /* Resolve expressions like `A::p' that we thought might become
pointers-to-members. */ pointers-to-members. */
...@@ -1274,7 +1297,8 @@ implicit_conversion (tree to, tree from, tree expr, int flags) ...@@ -1274,7 +1297,8 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
complete_type (to); complete_type (to);
if (TREE_CODE (to) == REFERENCE_TYPE) if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags); conv = reference_binding (to, from, expr, flags,
/*ref_bound_directly_to_rvalue_p=*/NULL);
else else
conv = standard_conversion (to, from, expr); conv = standard_conversion (to, from, expr);
...@@ -1286,6 +1310,8 @@ implicit_conversion (tree to, tree from, tree expr, int flags) ...@@ -1286,6 +1310,8 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
|| IS_AGGR_TYPE (to)) || IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0) && (flags & LOOKUP_NO_CONVERSION) == 0)
{ {
struct z_candidate *cand;
cand = build_user_type_conversion_1 cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING); (to, expr, LOOKUP_ONLYCONVERTING);
if (cand) if (cand)
...@@ -1304,7 +1330,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags) ...@@ -1304,7 +1330,7 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
functions. */ functions. */
static struct z_candidate * static struct z_candidate *
add_candidate (struct z_candidate *candidates, add_candidate (struct z_candidate **candidates,
tree fn, tree args, tree convs, tree access_path, tree fn, tree args, tree convs, tree access_path,
tree conversion_path, int viable) tree conversion_path, int viable)
{ {
...@@ -1317,7 +1343,8 @@ add_candidate (struct z_candidate *candidates, ...@@ -1317,7 +1343,8 @@ add_candidate (struct z_candidate *candidates,
cand->access_path = access_path; cand->access_path = access_path;
cand->conversion_path = conversion_path; cand->conversion_path = conversion_path;
cand->viable = viable; cand->viable = viable;
cand->next = candidates; cand->next = *candidates;
*candidates = cand;
return cand; return cand;
} }
...@@ -1330,7 +1357,7 @@ add_candidate (struct z_candidate *candidates, ...@@ -1330,7 +1357,7 @@ add_candidate (struct z_candidate *candidates,
comes from for purposes of overload resolution. */ comes from for purposes of overload resolution. */
static struct z_candidate * static struct z_candidate *
add_function_candidate (struct z_candidate *candidates, add_function_candidate (struct z_candidate **candidates,
tree fn, tree ctype, tree arglist, tree fn, tree ctype, tree arglist,
tree access_path, tree conversion_path, tree access_path, tree conversion_path,
int flags) int flags)
...@@ -1465,7 +1492,7 @@ add_function_candidate (struct z_candidate *candidates, ...@@ -1465,7 +1492,7 @@ add_function_candidate (struct z_candidate *candidates,
instead of the function. */ instead of the function. */
static struct z_candidate * static struct z_candidate *
add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj, add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
tree arglist, tree access_path, tree conversion_path) tree arglist, tree access_path, tree conversion_path)
{ {
tree totype = TREE_TYPE (TREE_TYPE (fn)); tree totype = TREE_TYPE (TREE_TYPE (fn));
...@@ -1484,8 +1511,8 @@ add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj, ...@@ -1484,8 +1511,8 @@ add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj,
flags = LOOKUP_NORMAL; flags = LOOKUP_NORMAL;
/* Don't bother looking up the same type twice. */ /* Don't bother looking up the same type twice. */
if (candidates && candidates->fn == totype) if (*candidates && (*candidates)->fn == totype)
return candidates; return NULL;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
{ {
...@@ -1530,8 +1557,8 @@ add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj, ...@@ -1530,8 +1557,8 @@ add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj,
conversion_path, viable); conversion_path, viable);
} }
static struct z_candidate * static void
build_builtin_candidate (struct z_candidate *candidates, tree fnname, build_builtin_candidate (struct z_candidate **candidates, tree fnname,
tree type1, tree type2, tree *args, tree *argtypes, tree type1, tree type2, tree *args, tree *argtypes,
int flags) int flags)
{ {
...@@ -1573,10 +1600,10 @@ build_builtin_candidate (struct z_candidate *candidates, tree fnname, ...@@ -1573,10 +1600,10 @@ build_builtin_candidate (struct z_candidate *candidates, tree fnname,
viable = 0; viable = 0;
} }
return add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs, add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs,
/*access_path=*/NULL_TREE, /*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
viable); viable);
} }
static bool static bool
...@@ -1612,8 +1639,8 @@ promoted_arithmetic_type_p (tree type) ...@@ -1612,8 +1639,8 @@ promoted_arithmetic_type_p (tree type)
of which TYPE1 and TYPE2 are, we add both candidates of which TYPE1 and TYPE2 are, we add both candidates
CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */ CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
static struct z_candidate * static void
add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
enum tree_code code2, tree fnname, tree type1, enum tree_code code2, tree fnname, tree type1,
tree type2, tree *args, tree *argtypes, int flags) tree type2, tree *args, tree *argtypes, int flags)
{ {
...@@ -1652,7 +1679,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1652,7 +1679,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case POSTDECREMENT_EXPR: case POSTDECREMENT_EXPR:
case PREDECREMENT_EXPR: case PREDECREMENT_EXPR:
if (TREE_CODE (type1) == BOOLEAN_TYPE) if (TREE_CODE (type1) == BOOLEAN_TYPE)
return candidates; return;
case POSTINCREMENT_EXPR: case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR: case PREINCREMENT_EXPR:
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1)) if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
...@@ -1660,7 +1687,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1660,7 +1687,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
type1 = build_reference_type (type1); type1 = build_reference_type (type1);
break; break;
} }
return candidates; return;
/* 7 For every cv-qualified or cv-unqualified complete object type T, there /* 7 For every cv-qualified or cv-unqualified complete object type T, there
exist candidate operator functions of the form exist candidate operator functions of the form
...@@ -1676,7 +1703,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1676,7 +1703,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
&& (TYPE_PTROB_P (type1) && (TYPE_PTROB_P (type1)
|| TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
break; break;
return candidates; return;
/* 9 For every type T, there exist candidate operator functions of the form /* 9 For every type T, there exist candidate operator functions of the form
T* operator+(T*); T* operator+(T*);
...@@ -1693,7 +1720,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1693,7 +1720,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case NEGATE_EXPR: case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1)) if (ARITHMETIC_TYPE_P (type1))
break; break;
return candidates; return;
/* 11For every promoted integral type T, there exist candidate operator /* 11For every promoted integral type T, there exist candidate operator
functions of the form functions of the form
...@@ -1702,7 +1729,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1702,7 +1729,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type1)) if (INTEGRAL_TYPE_P (type1))
break; break;
return candidates; return;
/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1 /* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1
is the same type as C2 or is a derived class of C2, T is a complete is the same type as C2 or is a derived class of C2, T is a complete
...@@ -1725,7 +1752,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1725,7 +1752,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
|| is_complete (TREE_TYPE (TREE_TYPE (type2))))) || is_complete (TREE_TYPE (TREE_TYPE (type2)))))
break; break;
} }
return candidates; return;
/* 13For every pair of promoted arithmetic types L and R, there exist can- /* 13For every pair of promoted arithmetic types L and R, there exist can-
didate operator functions of the form didate operator functions of the form
...@@ -1781,7 +1808,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1781,7 +1808,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break; break;
return candidates; return;
case EQ_EXPR: case EQ_EXPR:
case NE_EXPR: case NE_EXPR:
...@@ -1823,7 +1850,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1823,7 +1850,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
type1 = type2; type1 = type2;
break; break;
} }
return candidates; return;
case PLUS_EXPR: case PLUS_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
...@@ -1839,7 +1866,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1839,7 +1866,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
type2 = ptrdiff_type_node; type2 = ptrdiff_type_node;
break; break;
} }
return candidates; return;
/* 18For every pair of promoted integral types L and R, there exist candi- /* 18For every pair of promoted integral types L and R, there exist candi-
date operator functions of the form date operator functions of the form
...@@ -1860,7 +1887,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1860,7 +1887,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case RSHIFT_EXPR: case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break; break;
return candidates; return;
/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration /* 19For every triple L, VQ, R), where L is an arithmetic or enumeration
type, VQ is either volatile or empty, and R is a promoted arithmetic type, VQ is either volatile or empty, and R is a promoted arithmetic
...@@ -1912,7 +1939,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1912,7 +1939,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break; break;
return candidates; return;
case TRUNC_MOD_EXPR: case TRUNC_MOD_EXPR:
case BIT_AND_EXPR: case BIT_AND_EXPR:
...@@ -1922,7 +1949,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1922,7 +1949,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
case RSHIFT_EXPR: case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break; break;
return candidates; return;
case NOP_EXPR: case NOP_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
...@@ -1937,7 +1964,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1937,7 +1964,7 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
type2 = type1; type2 = type1;
break; break;
} }
return candidates; return;
default: default:
abort (); abort ();
...@@ -1972,16 +1999,13 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1972,16 +1999,13 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
|| !(TREE_CODE (type2) == POINTER_TYPE || !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2) || TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2))) || TYPE_PTRMEMFUNC_P (type2)))
return candidates; return;
/* We don't check that the two types are the same; the logic /* We don't check that the two types are the same; the logic
below will actually create two candidates; one in which both below will actually create two candidates; one in which both
parameter types are TYPE1, and one in which both parameter parameter types are TYPE1, and one in which both parameter
types are TYPE2. */ types are TYPE2. */
break; break;
/* These arguments do not make for a valid overloaded operator. */
return candidates;
default: default:
abort (); abort ();
...@@ -1998,13 +2022,14 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code, ...@@ -1998,13 +2022,14 @@ add_builtin_candidate (struct z_candidate *candidates, enum tree_code code,
|| IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE)) || TREE_CODE (type1) == ENUMERAL_TYPE))
{ {
candidates = build_builtin_candidate build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags); (candidates, fnname, type1, type1, args, argtypes, flags);
return build_builtin_candidate build_builtin_candidate
(candidates, fnname, type2, type2, args, argtypes, flags); (candidates, fnname, type2, type2, args, argtypes, flags);
return;
} }
return build_builtin_candidate build_builtin_candidate
(candidates, fnname, type1, type2, args, argtypes, flags); (candidates, fnname, type1, type2, args, argtypes, flags);
} }
...@@ -2031,8 +2056,8 @@ type_decays_to (tree type) ...@@ -2031,8 +2056,8 @@ type_decays_to (tree type)
other cases which the standard disallows. add_builtin_candidate will other cases which the standard disallows. add_builtin_candidate will
filter out the invalid set. */ filter out the invalid set. */
static struct z_candidate * static void
add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
enum tree_code code2, tree fnname, tree *args, enum tree_code code2, tree fnname, tree *args,
int flags) int flags)
{ {
...@@ -2074,20 +2099,22 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, ...@@ -2074,20 +2099,22 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code,
bool operator||(bool, bool); */ bool operator||(bool, bool); */
case TRUTH_NOT_EXPR: case TRUTH_NOT_EXPR:
return build_builtin_candidate build_builtin_candidate
(candidates, fnname, boolean_type_node, (candidates, fnname, boolean_type_node,
NULL_TREE, args, argtypes, flags); NULL_TREE, args, argtypes, flags);
return;
case TRUTH_ORIF_EXPR: case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR: case TRUTH_ANDIF_EXPR:
return build_builtin_candidate build_builtin_candidate
(candidates, fnname, boolean_type_node, (candidates, fnname, boolean_type_node,
boolean_type_node, args, argtypes, flags); boolean_type_node, args, argtypes, flags);
return;
case ADDR_EXPR: case ADDR_EXPR:
case COMPOUND_EXPR: case COMPOUND_EXPR:
case COMPONENT_REF: case COMPONENT_REF:
return candidates; return;
case COND_EXPR: case COND_EXPR:
case EQ_EXPR: case EQ_EXPR:
...@@ -2114,7 +2141,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, ...@@ -2114,7 +2141,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code,
tree convs; tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR) if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return candidates; return;
convs = lookup_conversions (argtypes[i]); convs = lookup_conversions (argtypes[i]);
...@@ -2129,7 +2156,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, ...@@ -2129,7 +2156,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code,
} }
else if (! convs) else if (! convs)
return candidates; return;
for (; convs; convs = TREE_CHAIN (convs)) for (; convs; convs = TREE_CHAIN (convs))
{ {
...@@ -2181,16 +2208,16 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, ...@@ -2181,16 +2208,16 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code,
{ {
if (types[1]) if (types[1])
for (type = types[1]; type; type = TREE_CHAIN (type)) for (type = types[1]; type; type = TREE_CHAIN (type))
candidates = add_builtin_candidate add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]), (candidates, code, code2, fnname, TREE_VALUE (types[0]),
TREE_VALUE (type), args, argtypes, flags); TREE_VALUE (type), args, argtypes, flags);
else else
candidates = add_builtin_candidate add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]), (candidates, code, code2, fnname, TREE_VALUE (types[0]),
NULL_TREE, args, argtypes, flags); NULL_TREE, args, argtypes, flags);
} }
return candidates; return;
} }
...@@ -2205,7 +2232,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code, ...@@ -2205,7 +2232,7 @@ add_builtin_candidates (struct z_candidate *candidates, enum tree_code code,
add_conv_candidate. */ add_conv_candidate. */
static struct z_candidate* static struct z_candidate*
add_template_candidate_real (struct z_candidate *candidates, tree tmpl, add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
tree ctype, tree explicit_targs, tree arglist, tree ctype, tree explicit_targs, tree arglist,
tree return_type, tree access_path, tree return_type, tree access_path,
tree conversion_path, int flags, tree obj, tree conversion_path, int flags, tree obj,
...@@ -2233,11 +2260,11 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl, ...@@ -2233,11 +2260,11 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl,
return_type, strict, -1); return_type, strict, -1);
if (i != 0) if (i != 0)
return candidates; return NULL;
fn = instantiate_template (tmpl, targs); fn = instantiate_template (tmpl, targs);
if (fn == error_mark_node) if (fn == error_mark_node)
return candidates; return NULL;
/* In [class.copy]: /* In [class.copy]:
...@@ -2266,7 +2293,7 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl, ...@@ -2266,7 +2293,7 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl,
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn); tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)), if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype)) ctype))
return candidates; return NULL;
} }
if (obj != NULL_TREE) if (obj != NULL_TREE)
...@@ -2304,7 +2331,7 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl, ...@@ -2304,7 +2331,7 @@ add_template_candidate_real (struct z_candidate *candidates, tree tmpl,
static struct z_candidate * static struct z_candidate *
add_template_candidate (struct z_candidate *candidates, tree tmpl, tree ctype, add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
tree explicit_targs, tree arglist, tree return_type, tree explicit_targs, tree arglist, tree return_type,
tree access_path, tree conversion_path, int flags, tree access_path, tree conversion_path, int flags,
unification_kind_t strict) unification_kind_t strict)
...@@ -2318,7 +2345,7 @@ add_template_candidate (struct z_candidate *candidates, tree tmpl, tree ctype, ...@@ -2318,7 +2345,7 @@ add_template_candidate (struct z_candidate *candidates, tree tmpl, tree ctype,
static struct z_candidate * static struct z_candidate *
add_template_conv_candidate (struct z_candidate *candidates, tree tmpl, add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
tree obj, tree arglist, tree return_type, tree obj, tree arglist, tree return_type,
tree access_path, tree conversion_path) tree access_path, tree conversion_path)
{ {
...@@ -2454,21 +2481,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2454,21 +2481,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
continue; continue;
if (TREE_CODE (ctor) == TEMPLATE_DECL) if (TREE_CODE (ctor) == TEMPLATE_DECL)
candidates = cand = add_template_candidate (&candidates, ctor, totype,
add_template_candidate (candidates, ctor, totype, NULL_TREE, args, NULL_TREE,
NULL_TREE, args, NULL_TREE, TYPE_BINFO (totype),
TYPE_BINFO (totype), TYPE_BINFO (totype),
TYPE_BINFO (totype), flags,
flags, DEDUCE_CALL);
DEDUCE_CALL);
else else
candidates = add_function_candidate (candidates, ctor, totype, cand = add_function_candidate (&candidates, ctor, totype,
args, TYPE_BINFO (totype), args, TYPE_BINFO (totype),
TYPE_BINFO (totype), TYPE_BINFO (totype),
flags); flags);
if (candidates) if (cand)
candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); cand->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
} }
if (convs) if (convs)
...@@ -2490,7 +2516,6 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2490,7 +2516,6 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns)) for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
struct z_candidate *old_candidates = candidates;
/* [over.match.funcs] For conversion functions, the function /* [over.match.funcs] For conversion functions, the function
is considered to be a member of the class of the implicit is considered to be a member of the class of the implicit
...@@ -2500,31 +2525,32 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2500,31 +2525,32 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
So we pass fromtype as CTYPE to add_*_candidate. */ So we pass fromtype as CTYPE to add_*_candidate. */
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
candidates = cand = add_template_candidate (&candidates, fn, fromtype,
add_template_candidate (candidates, fn, fromtype, NULL_TREE, NULL_TREE,
args, totype, TYPE_BINFO (fromtype), args, totype,
conversion_path, TYPE_BINFO (fromtype),
flags, conversion_path,
DEDUCE_CONV); flags,
DEDUCE_CONV);
else else
candidates = add_function_candidate (candidates, fn, fromtype, cand = add_function_candidate (&candidates, fn, fromtype,
args, args,
TYPE_BINFO (fromtype), TYPE_BINFO (fromtype),
conversion_path, conversion_path,
flags); flags);
if (candidates != old_candidates) if (cand)
{ {
tree ics = implicit_conversion tree ics = implicit_conversion (totype,
(totype, TREE_TYPE (TREE_TYPE (candidates->fn)), TREE_TYPE (TREE_TYPE (cand->fn)),
0, convflags); 0, convflags);
candidates->second_conv = ics; cand->second_conv = ics;
if (ics == NULL_TREE) if (ics == NULL_TREE)
candidates->viable = 0; cand->viable = 0;
else if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
candidates->viable = -1; cand->viable = -1;
} }
} }
} }
...@@ -2718,14 +2744,14 @@ build_new_function_call (tree fn, tree args) ...@@ -2718,14 +2744,14 @@ build_new_function_call (tree fn, tree args)
my_friendly_assert (!DECL_FUNCTION_MEMBER_P (t), 20020913); my_friendly_assert (!DECL_FUNCTION_MEMBER_P (t), 20020913);
if (TREE_CODE (t) == TEMPLATE_DECL) if (TREE_CODE (t) == TEMPLATE_DECL)
candidates = add_template_candidate add_template_candidate
(candidates, t, NULL_TREE, explicit_targs, args, (&candidates, t, NULL_TREE, explicit_targs, args,
NULL_TREE, /*access_path=*/NULL_TREE, NULL_TREE, /*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL); LOOKUP_NORMAL, DEDUCE_CALL);
else if (! template_only) else if (! template_only)
candidates = add_function_candidate add_function_candidate
(candidates, t, NULL_TREE, args, (&candidates, t, NULL_TREE, args,
/*access_path=*/NULL_TREE, /*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE, LOOKUP_NORMAL); /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
} }
...@@ -2793,15 +2819,14 @@ build_object_call (tree obj, tree args) ...@@ -2793,15 +2819,14 @@ build_object_call (tree obj, tree args)
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
candidates add_template_candidate (&candidates, fn, base, NULL_TREE,
= add_template_candidate (candidates, fn, base, NULL_TREE, mem_args, NULL_TREE,
mem_args, NULL_TREE, TYPE_BINFO (type),
TYPE_BINFO (type), TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL, DEDUCE_CALL);
LOOKUP_NORMAL, DEDUCE_CALL);
else else
candidates = add_function_candidate add_function_candidate
(candidates, fn, base, mem_args, TYPE_BINFO (type), (&candidates, fn, base, mem_args, TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL); TYPE_BINFO (type), LOOKUP_NORMAL);
} }
} }
...@@ -2824,16 +2849,14 @@ build_object_call (tree obj, tree args) ...@@ -2824,16 +2849,14 @@ build_object_call (tree obj, tree args)
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
{ add_template_conv_candidate
candidates = (add_template_conv_candidate (&candidates, fn, obj, args, totype,
(candidates, fn, obj, args, totype, /*access_path=*/NULL_TREE,
/*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE);
/*conversion_path=*/NULL_TREE));
}
else else
candidates = add_conv_candidate (candidates, fn, obj, args, add_conv_candidate (&candidates, fn, obj, args,
/*conversion_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE); /*access_path=*/NULL_TREE);
} }
} }
...@@ -3139,12 +3162,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) ...@@ -3139,12 +3162,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
args[0] = arg2; args[0] = arg2;
args[1] = arg3; args[1] = arg3;
args[2] = arg1; args[2] = arg1;
candidates = add_builtin_candidates (candidates, add_builtin_candidates (&candidates,
COND_EXPR, COND_EXPR,
NOP_EXPR, NOP_EXPR,
ansi_opname (COND_EXPR), ansi_opname (COND_EXPR),
args, args,
LOOKUP_NORMAL); LOOKUP_NORMAL);
/* [expr.cond] /* [expr.cond]
...@@ -3327,11 +3350,11 @@ prep_operand (tree operand) ...@@ -3327,11 +3350,11 @@ prep_operand (tree operand)
without any implicit object parameter. CONVERSION_PATH, without any implicit object parameter. CONVERSION_PATH,
ACCESS_PATH, and FLAGS are as for add_function_candidate. */ ACCESS_PATH, and FLAGS are as for add_function_candidate. */
static struct z_candidate * static void
add_candidates (tree fns, tree args, add_candidates (tree fns, tree args,
tree conversion_path, tree access_path, tree conversion_path, tree access_path,
int flags, int flags,
struct z_candidate *candidates) struct z_candidate **candidates)
{ {
tree ctype; tree ctype;
tree non_static_args; tree non_static_args;
...@@ -3362,28 +3385,26 @@ add_candidates (tree fns, tree args, ...@@ -3362,28 +3385,26 @@ add_candidates (tree fns, tree args,
fn_args = args; fn_args = args;
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
candidates = add_template_candidate (candidates, add_template_candidate (candidates,
fn, fn,
ctype, ctype,
NULL_TREE, NULL_TREE,
fn_args, fn_args,
NULL_TREE, NULL_TREE,
access_path, access_path,
conversion_path, conversion_path,
flags, flags,
DEDUCE_CALL); DEDUCE_CALL);
else else
candidates = add_function_candidate (candidates, add_function_candidate (candidates,
fn, fn,
ctype, ctype,
fn_args, fn_args,
access_path, access_path,
conversion_path, conversion_path,
flags); flags);
fns = OVL_NEXT (fns); fns = OVL_NEXT (fns);
} }
return candidates;
} }
tree tree
...@@ -3456,9 +3477,9 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3) ...@@ -3456,9 +3477,9 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
/* Add namespace-scope operators to the list of functions to /* Add namespace-scope operators to the list of functions to
consider. */ consider. */
candidates = add_candidates (lookup_function_nonclass (fnname, arglist), add_candidates (lookup_function_nonclass (fnname, arglist),
arglist, NULL_TREE, NULL_TREE, arglist, NULL_TREE, NULL_TREE,
flags, candidates); flags, &candidates);
/* Add class-member operators to the candidate set. */ /* Add class-member operators to the candidate set. */
if (CLASS_TYPE_P (TREE_TYPE (arg1))) if (CLASS_TYPE_P (TREE_TYPE (arg1)))
{ {
...@@ -3468,10 +3489,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3) ...@@ -3468,10 +3489,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
if (fns == error_mark_node) if (fns == error_mark_node)
return fns; return fns;
if (fns) if (fns)
candidates = add_candidates (BASELINK_FUNCTIONS (fns), arglist, add_candidates (BASELINK_FUNCTIONS (fns), arglist,
BASELINK_BINFO (fns), BASELINK_BINFO (fns),
TYPE_BINFO (TREE_TYPE (arg1)), TYPE_BINFO (TREE_TYPE (arg1)),
flags, candidates); flags, &candidates);
} }
/* Rearrange the arguments for ?: so that add_builtin_candidate only has /* Rearrange the arguments for ?: so that add_builtin_candidate only has
...@@ -3491,8 +3512,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3) ...@@ -3491,8 +3512,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
args[2] = NULL_TREE; args[2] = NULL_TREE;
} }
candidates = add_builtin_candidates add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
(candidates, code, code2, fnname, args, flags);
switch (code) switch (code)
{ {
...@@ -3899,8 +3919,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner) ...@@ -3899,8 +3919,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
{ {
case USER_CONV: case USER_CONV:
{ {
struct z_candidate *cand struct z_candidate *cand = USER_CONV_CAND (convs);
= WRAPPER_ZC (TREE_OPERAND (convs, 1));
tree convfn = cand->fn; tree convfn = cand->fn;
tree args; tree args;
...@@ -4055,9 +4074,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner) ...@@ -4055,9 +4074,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),
expr); expr);
/* Convert the pointer to the desired reference type. */ /* Convert the pointer to the desired reference type. */
expr = build1 (NOP_EXPR, ref_type, expr); return build_nop (ref_type, expr);
return expr;
} }
case LVALUE_CONV: case LVALUE_CONV:
...@@ -4793,7 +4810,7 @@ build_new_method_call (tree instance, tree fns, tree args, ...@@ -4793,7 +4810,7 @@ build_new_method_call (tree instance, tree fns, tree args,
{ {
tree type = build_pointer_type (basetype); tree type = build_pointer_type (basetype);
if (!same_type_p (type, TREE_TYPE (instance_ptr))) if (!same_type_p (type, TREE_TYPE (instance_ptr)))
instance_ptr = build1 (NOP_EXPR, type, instance_ptr); instance_ptr = build_nop (type, instance_ptr);
} }
class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE); class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
...@@ -4815,25 +4832,22 @@ build_new_method_call (tree instance, tree fns, tree args, ...@@ -4815,25 +4832,22 @@ build_new_method_call (tree instance, tree fns, tree args,
this_arglist = args; this_arglist = args;
if (TREE_CODE (t) == TEMPLATE_DECL) if (TREE_CODE (t) == TEMPLATE_DECL)
{ /* A member template. */
/* A member template. */ add_template_candidate (&candidates, t,
candidates = class_type,
add_template_candidate (candidates, t, explicit_targs,
class_type, this_arglist, optype,
explicit_targs, access_binfo,
this_arglist, optype, conversion_path,
access_binfo, flags,
conversion_path, DEDUCE_CALL);
flags,
DEDUCE_CALL);
}
else if (! template_only) else if (! template_only)
candidates = add_function_candidate (candidates, t, add_function_candidate (&candidates, t,
class_type, class_type,
this_arglist, this_arglist,
access_binfo, access_binfo,
conversion_path, conversion_path,
flags); flags);
} }
if (! any_viable (candidates)) if (! any_viable (candidates))
...@@ -5783,22 +5797,106 @@ perform_implicit_conversion (tree type, tree expr) ...@@ -5783,22 +5797,106 @@ perform_implicit_conversion (tree type, tree expr)
return convert_like (conv, expr); return convert_like (conv, expr);
} }
/* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference
is being bound to a temporary. Create and return a new VAR_DECL
whose type is the underlying type of the reference. */
tree
make_temporary_var_for_ref_to_temp (tree decl)
{
tree type;
tree var;
/* Get the type to which the reference refers. */
type = TREE_TYPE (decl);
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 200302);
type = TREE_TYPE (type);
/* Create the variable. */
var = build_decl (VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (var) = 1;
TREE_USED (var) = 1;
/* Register the variable. */
if (TREE_STATIC (decl))
{
/* Namespace-scope or local static; give it a mangled name. */
tree name;
TREE_STATIC (var) = 1;
name = mangle_ref_init_variable (decl);
DECL_NAME (var) = name;
SET_DECL_ASSEMBLER_NAME (var, name);
var = pushdecl_top_level (var);
}
else
{
/* Create a new cleanup level if necessary. */
maybe_push_cleanup_level (type);
/* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
DECL_CONTEXT (var) = current_function_decl;
}
return var;
}
/* Convert EXPR to the indicated reference TYPE, in a way suitable for /* Convert EXPR to the indicated reference TYPE, in a way suitable for
initializing a variable of that TYPE. Return the converted initializing a variable of that TYPE. If DECL is non-NULL, it is
expression. */ the VAR_DECL being initialized with the EXPR. (In that case, the
type of DECL will be TYPE.)
Return the converted expression. */
tree tree
initialize_reference (tree type, tree expr) initialize_reference (tree type, tree expr, tree decl)
{ {
tree conv; tree conv;
bool ref_bound_directly_to_rvalue_p;
if (type == error_mark_node || error_operand_p (expr))
return error_mark_node;
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL,
&ref_bound_directly_to_rvalue_p);
if (!conv || ICS_BAD_FLAG (conv)) if (!conv || ICS_BAD_FLAG (conv))
{ {
error ("could not convert `%E' to `%T'", expr, type); error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node; return error_mark_node;
} }
/* If DECL is non-NULL, then this special rule applies:
[class.temporary]
The temporary to which the reference is bound or the temporary
that is the complete object to which the temporary is bound
persists for the lifetime of the reference.
The temporaries created during the evaluation of the expression
initializing the reference, except the temporary to which the
reference is bound, are destroyed at the end of the
full-expression in which they are created.
In that case, we store the converted expression into a new
VAR_DECL in a new scope. */
my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
if (decl && (NEED_TEMPORARY_P (conv) || ref_bound_directly_to_rvalue_p))
{
tree var;
/* Process the initializer for the declaration. */
expr = convert_like (TREE_OPERAND (conv, 0), expr);
/* Create the temporary variable. */
var = make_temporary_var_for_ref_to_temp (decl);
DECL_INITIAL (var) = expr;
cp_finish_decl (var, expr, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
/* Use its address to initialize the reference variable. */
return build_nop (type, build_address (var));
}
/* Perform the conversion. */
return convert_like (conv, expr); return convert_like (conv, expr);
} }
......
...@@ -7922,22 +7922,20 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid) ...@@ -7922,22 +7922,20 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
/* The second entry is the address of the typeinfo object. */ /* The second entry is the address of the typeinfo object. */
if (flag_rtti) if (flag_rtti)
decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0); decl = build_address (get_tinfo_decl (t));
else else
decl = integer_zero_node; decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the /* Convert the declaration to a type that can be stored in the
vtable. */ vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl); init = build_nop (vfunc_ptr_type_node, decl);
TREE_CONSTANT (init) = 1;
*vid->last_init = build_tree_list (NULL_TREE, init); *vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init); vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that /* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. Convert the offset to look like a the the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */ function pointer, so that we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); init = build_nop (vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
*vid->last_init = build_tree_list (NULL_TREE, init); *vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init); vid->last_init = &TREE_CHAIN (*vid->last_init);
} }
...@@ -3576,7 +3576,8 @@ extern tree type_passed_as (tree); ...@@ -3576,7 +3576,8 @@ extern tree type_passed_as (tree);
extern tree convert_for_arg_passing (tree, tree); extern tree convert_for_arg_passing (tree, tree);
extern tree cp_convert_parm_for_inlining (tree, tree, tree); extern tree cp_convert_parm_for_inlining (tree, tree, tree);
extern bool is_properly_derived_from (tree, tree); extern bool is_properly_derived_from (tree, tree);
extern tree initialize_reference (tree, tree); extern tree initialize_reference (tree, tree, tree);
extern tree make_temporary_var_for_ref_to_temp (tree);
extern tree strip_top_quals (tree); extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree); extern tree perform_implicit_conversion (tree, tree);
extern tree in_charge_arg_for_name (tree); extern tree in_charge_arg_for_name (tree);
...@@ -3638,7 +3639,7 @@ extern tree ocp_convert (tree, tree, int, int); ...@@ -3638,7 +3639,7 @@ extern tree ocp_convert (tree, tree, int, int);
extern tree cp_convert (tree, tree); extern tree cp_convert (tree, tree);
extern tree convert_to_void (tree, const char */*implicit context*/); extern tree convert_to_void (tree, const char */*implicit context*/);
extern tree convert_force (tree, tree, int); extern tree convert_force (tree, tree, int);
extern tree build_type_conversion (tree, tree, int); extern tree build_type_conversion (tree, tree);
extern tree build_expr_type_conversion (int, tree, bool); extern tree build_expr_type_conversion (int, tree, bool);
extern tree type_promotes_to (tree); extern tree type_promotes_to (tree);
extern tree perform_qualification_conversions (tree, tree); extern tree perform_qualification_conversions (tree, tree);
...@@ -4355,6 +4356,8 @@ extern tree check_return_expr (tree); ...@@ -4355,6 +4356,8 @@ extern tree check_return_expr (tree);
#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true) #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true) #define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
extern tree build_ptrmemfunc_access_expr (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree);
extern tree build_address (tree);
extern tree build_nop (tree, tree);
/* in typeck2.c */ /* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree); extern void require_complete_eh_spec_types (tree, tree);
......
...@@ -90,7 +90,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force) ...@@ -90,7 +90,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return error_mark_node; return error_mark_node;
} }
rval = build_type_conversion (type, expr, true); rval = build_type_conversion (type, expr);
if (rval) if (rval)
{ {
if (rval == error_mark_node) if (rval == error_mark_node)
...@@ -148,31 +148,33 @@ cp_convert_to_pointer (tree type, tree expr, bool force) ...@@ -148,31 +148,33 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
{ {
enum tree_code code = PLUS_EXPR; enum tree_code code = PLUS_EXPR;
tree binfo; tree binfo;
tree intype_class;
tree type_class;
bool same_p;
intype_class = TREE_TYPE (intype);
type_class = TREE_TYPE (type);
same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
TYPE_MAIN_VARIANT (type_class));
binfo = NULL_TREE;
/* Try derived to base conversion. */ /* Try derived to base conversion. */
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type), if (!same_p)
ba_check, NULL); binfo = lookup_base (intype_class, type_class, ba_check, NULL);
if (!binfo) if (!same_p && !binfo)
{ {
/* Try base to derived conversion. */ /* Try base to derived conversion. */
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), binfo = lookup_base (type_class, intype_class, ba_check, NULL);
ba_check, NULL);
code = MINUS_EXPR; code = MINUS_EXPR;
} }
if (binfo == error_mark_node) if (binfo == error_mark_node)
return error_mark_node; return error_mark_node;
if (binfo) if (binfo || same_p)
{ {
expr = build_base_path (code, expr, binfo, 0); if (binfo)
expr = build_base_path (code, expr, binfo, 0);
/* Add any qualifier conversions. */ /* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)), return build_nop (type, expr);
TREE_TYPE (type)))
{
expr = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (expr) =
TREE_CONSTANT (TREE_OPERAND (expr, 0));
}
return expr;
} }
} }
...@@ -225,9 +227,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force) ...@@ -225,9 +227,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return error_mark_node; return error_mark_node;
} }
rval = build1 (NOP_EXPR, type, expr); return build_nop (type, expr);
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
} }
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)) else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
...@@ -326,14 +326,9 @@ convert_to_pointer_force (tree type, tree expr) ...@@ -326,14 +326,9 @@ convert_to_pointer_force (tree type, tree expr)
/* Add any qualifier conversions. */ /* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)), if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type))) TREE_TYPE (type)))
{ expr = build_nop (type, expr);
expr = build1 (NOP_EXPR, type, expr);
TREE_CONSTANT (expr) =
TREE_CONSTANT (TREE_OPERAND (expr, 0));
}
return expr; return expr;
} }
} }
} }
...@@ -354,7 +349,6 @@ build_up_reference (tree type, tree arg, int flags, tree decl) ...@@ -354,7 +349,6 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
tree rval; tree rval;
tree argtype = TREE_TYPE (arg); tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type); tree target_type = TREE_TYPE (type);
tree stmt_expr = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187); my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
...@@ -364,26 +358,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl) ...@@ -364,26 +358,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
here because it needs to live as long as DECL. */ here because it needs to live as long as DECL. */
tree targ = arg; tree targ = arg;
arg = build_decl (VAR_DECL, NULL_TREE, argtype); arg = make_temporary_var_for_ref_to_temp (decl);
DECL_ARTIFICIAL (arg) = 1;
TREE_USED (arg) = 1;
TREE_STATIC (arg) = TREE_STATIC (decl);
if (TREE_STATIC (decl))
{
/* Namespace-scope or local static; give it a mangled name. */
tree name = mangle_ref_init_variable (decl);
DECL_NAME (arg) = name;
SET_DECL_ASSEMBLER_NAME (arg, name);
arg = pushdecl_top_level (arg);
}
else
{
/* Automatic; make sure we handle the cleanup properly. */
maybe_push_cleanup_level (argtype);
/* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
DECL_CONTEXT (arg) = current_function_decl;
}
/* Process the initializer for the declaration. */ /* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ; DECL_INITIAL (arg) = targ;
...@@ -416,16 +391,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl) ...@@ -416,16 +391,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
else else
rval rval
= convert_to_pointer_force (build_pointer_type (target_type), rval); = convert_to_pointer_force (build_pointer_type (target_type), rval);
rval = build1 (NOP_EXPR, type, rval); return build_nop (type, rval);
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
/* If we created and initialized a new temporary variable, add the
representation of that initialization to the RVAL. */
if (stmt_expr)
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), stmt_expr, rval);
/* And return the result. */
return rval;
} }
/* Subroutine of convert_to_reference. REFTYPE is the target reference type. /* Subroutine of convert_to_reference. REFTYPE is the target reference type.
...@@ -500,7 +466,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, ...@@ -500,7 +466,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
/* Look for a user-defined conversion to lvalue that we can use. */ /* Look for a user-defined conversion to lvalue that we can use. */
rval_as_conversion rval_as_conversion
= build_type_conversion (reftype, expr, 1); = build_type_conversion (reftype, expr);
if (rval_as_conversion && rval_as_conversion != error_mark_node if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion)) && real_lvalue_p (rval_as_conversion))
...@@ -705,7 +671,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ...@@ -705,7 +671,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (IS_AGGR_TYPE (intype)) if (IS_AGGR_TYPE (intype))
{ {
tree rval; tree rval;
rval = build_type_conversion (type, e, 1); rval = build_type_conversion (type, e);
if (rval) if (rval)
return rval; return rval;
if (flags & LOOKUP_COMPLAIN) if (flags & LOOKUP_COMPLAIN)
...@@ -741,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ...@@ -741,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (IS_AGGR_TYPE (TREE_TYPE (e))) if (IS_AGGR_TYPE (TREE_TYPE (e)))
{ {
tree rval; tree rval;
rval = build_type_conversion (type, e, 1); rval = build_type_conversion (type, e);
if (rval) if (rval)
return rval; return rval;
else else
...@@ -1015,24 +981,17 @@ convert_force (tree type, tree expr, int convtype) ...@@ -1015,24 +981,17 @@ convert_force (tree type, tree expr, int convtype)
allowed (references private members, etc). allowed (references private members, etc).
If no conversion exists, NULL_TREE is returned. If no conversion exists, NULL_TREE is returned.
If (FOR_SURE & 1) is nonzero, then we allow this type conversion
to take place immediately. Otherwise, we build a SAVE_EXPR
which can be evaluated if the results are ever needed.
Changes to this functions should be mirrored in user_harshness.
FIXME: Ambiguity checking is wrong. Should choose one by the implicit FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite. that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */ (jason 8/9/95) */
tree tree
build_type_conversion (tree xtype, tree expr, int for_sure) build_type_conversion (tree xtype, tree expr)
{ {
/* C++: check to see if we can convert this aggregate type /* C++: check to see if we can convert this aggregate type
into the required type. */ into the required type. */
return build_user_type_conversion return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
(xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
} }
/* Convert the given EXPR to one of a group of types suitable for use in an /* Convert the given EXPR to one of a group of types suitable for use in an
......
...@@ -7288,10 +7288,7 @@ grok_reference_init (tree decl, tree type, tree init) ...@@ -7288,10 +7288,7 @@ grok_reference_init (tree decl, tree type, tree init)
DECL_INITIAL for local references (instead assigning to them DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized explicitly); we need to allow the temporary to be initialized
first. */ first. */
tmp = convert_to_reference tmp = initialize_reference (type, init, decl);
(type, init, CONV_IMPLICIT,
LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
decl);
if (tmp == error_mark_node) if (tmp == error_mark_node)
return NULL_TREE; return NULL_TREE;
......
...@@ -4089,7 +4089,45 @@ condition_conversion (expr) ...@@ -4089,7 +4089,45 @@ condition_conversion (expr)
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t; return t;
} }
/* Return an ADDR_EXPR giving the address of T. This function
attempts no optimizations or simplifications; it is a low-level
primitive. */
tree
build_address (tree t)
{
tree addr;
if (error_operand_p (t) || !cxx_mark_addressable (t))
return error_mark_node;
addr = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (t)),
t);
if (staticp (t))
TREE_CONSTANT (addr) = 1;
return addr;
}
/* Return a NOP_EXPR converting EXPR to TYPE. */
tree
build_nop (tree type, tree expr)
{
tree nop;
if (type == error_mark_node || error_operand_p (expr))
return expr;
nop = build1 (NOP_EXPR, type, expr);
if (TREE_CONSTANT (expr))
TREE_CONSTANT (nop) = 1;
return nop;
}
/* C++: Must handle pointers to members. /* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion Perhaps type instantiation should be extended to handle conversion
...@@ -4479,9 +4517,6 @@ build_unary_op (code, xarg, noconvert) ...@@ -4479,9 +4517,6 @@ build_unary_op (code, xarg, noconvert)
if (argtype != error_mark_node) if (argtype != error_mark_node)
argtype = build_pointer_type (argtype); argtype = build_pointer_type (argtype);
if (!cxx_mark_addressable (arg))
return error_mark_node;
{ {
tree addr; tree addr;
...@@ -4515,12 +4550,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4515,12 +4550,7 @@ build_unary_op (code, xarg, noconvert)
cp_convert (argtype, byte_position (field)))); cp_convert (argtype, byte_position (field))));
} }
else else
addr = build1 (ADDR_EXPR, argtype, arg); addr = build_address (arg);
/* Address of a static or external variable or
function counts as a constant */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
if (TREE_CODE (argtype) == POINTER_TYPE if (TREE_CODE (argtype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
...@@ -5798,11 +5828,17 @@ build_ptrmemfunc (type, pfn, force) ...@@ -5798,11 +5828,17 @@ build_ptrmemfunc (type, pfn, force)
int force; int force;
{ {
tree fn; tree fn;
tree pfn_type = TREE_TYPE (pfn); tree pfn_type;
tree to_type = build_ptrmemfunc_type (type); tree to_type;
if (error_operand_p (pfn))
return error_mark_node;
pfn_type = TREE_TYPE (pfn);
to_type = build_ptrmemfunc_type (type);
/* Handle multiple conversions of pointer to member functions. */ /* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) if (TYPE_PTRMEMFUNC_P (pfn_type))
{ {
tree delta = NULL_TREE; tree delta = NULL_TREE;
tree npfn = NULL_TREE; tree npfn = NULL_TREE;
...@@ -6183,7 +6219,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -6183,7 +6219,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl) if (fndecl)
savew = warningcount, savee = errorcount; savew = warningcount, savee = errorcount;
rhs = initialize_reference (type, rhs); rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
if (fndecl) if (fndecl)
{ {
if (warningcount > savew) if (warningcount > savew)
......
...@@ -388,32 +388,8 @@ store_init_value (decl, init) ...@@ -388,32 +388,8 @@ store_init_value (decl, init)
return value; return value;
else if (TREE_STATIC (decl) else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value) && (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value)) || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
#if 0
/* A STATIC PUBLIC int variable doesn't have to be
run time inited when doing pic. (mrs) */
/* Since ctors and dtors are the only things that can
reference vtables, and they are always written down
the vtable definition, we can leave the
vtables in initialized data space.
However, other initialized data cannot be initialized
this way. Instead a global file-level initializer
must do the job. */
|| (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
#endif
))
return value; return value;
#if 0 /* No, that's C. jason 9/19/94 */
else
{
if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
{
if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions");
}
}
#endif
/* Store the VALUE in DECL_INITIAL. If we're building a /* Store the VALUE in DECL_INITIAL. If we're building a
statement-tree we will actually expand the initialization later statement-tree we will actually expand the initialization later
......
2003-03-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9878
* g++.dg/init/ref1.C: New test.
Mon Mar 3 20:42:04 2003 J"orn Rennecke <joern.rennecke@superh.com> Mon Mar 3 20:42:04 2003 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.dg/sh-relax.c: New SH-only test. * gcc.dg/sh-relax.c: New SH-only test.
......
void f(void)
{
short x = 0;
const int &y = x;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment