Commit 27b8d0cd by Mark Mitchell Committed by Mark Mitchell

call.c (NEED_TEMPORARY_P): New macro.

	* call.c (NEED_TEMPORARY_P): New macro.
	(standard_conversion): Set it, for derived-to-base conversions.
	(reference_related_p): New function.
	(reference_compatible_p): Likewise.
	(convert_class_to_reference): Likewise.
	(direct_reference_binding): Likewise.
	(reference_binding): Rework for standards-compliance.
	(convert_like): Adjust accordingly.
	(maybe_handle_ref_bind): Simplify; the right conversion sequences
	are now built up in reference_binding.
	(initialize_reference): New function.
	* cp-tree.h (ICS_USER_FLAG): Document.
	(ICS_THIS_FLAG): Likewise.
	(ICS_BAD_FLAG): Likewise.
	(NEED_TEMPORARY_P): Likewise.
	(cp_lvalue_kind): New type.
	(real_lvalue_p): Return it.
	* error.c (dump_expr): Provide more accurate representation for
	AGGR_INIT_EXPRs.
	* init.c (expand_default_init): Do not try to perform implicit
	conversions for a brace-enclosed initializer.
	* search.c (lookup_conversions): Document.
	* tree.c (lvalue_p_1): Return a cp_lvalue_kind.  Calculate
	appropriately.
	(real_lvalue_p): Adjust accordingly.
	(lvalue_p): Likewise.
	(build_cplus_new): Don't allow the creation of an abstract class.
	* typeck.c (convert_for_initialization): Use initialize_reference.

From-SVN: r28221
parent ac1d97ce
1999-07-22 Mark Mitchell <mark@codesourcery.com>
* call.c (NEED_TEMPORARY_P): New macro.
(standard_conversion): Set it, for derived-to-base conversions.
(reference_related_p): New function.
(reference_compatible_p): Likewise.
(convert_class_to_reference): Likewise.
(direct_reference_binding): Likewise.
(reference_binding): Rework for standards-compliance.
(convert_like): Adjust accordingly.
(maybe_handle_ref_bind): Simplify; the right conversion sequences
are now built up in reference_binding.
(initialize_reference): New function.
* cp-tree.h (ICS_USER_FLAG): Document.
(ICS_THIS_FLAG): Likewise.
(ICS_BAD_FLAG): Likewise.
(NEED_TEMPORARY_P): Likewise.
(cp_lvalue_kind): New type.
(real_lvalue_p): Return it.
* error.c (dump_expr): Provide more accurate representation for
AGGR_INIT_EXPRs.
* init.c (expand_default_init): Do not try to perform implicit
conversions for a brace-enclosed initializer.
* search.c (lookup_conversions): Document.
* tree.c (lvalue_p_1): Return a cp_lvalue_kind. Calculate
appropriately.
(real_lvalue_p): Adjust accordingly.
(lvalue_p): Likewise.
(build_cplus_new): Don't allow the creation of an abstract class.
* typeck.c (convert_for_initialization): Use initialize_reference.
1999-07-21 Gavin Romig-Koch <gavin@cygnus.com> 1999-07-21 Gavin Romig-Koch <gavin@cygnus.com>
* lex.c (real_yylex) : Correct the test for overflow when lexing * lex.c (real_yylex) : Correct the test for overflow when lexing
......
...@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
TREE_INDIRECT_USING (in NAMESPACE_DECL). TREE_INDIRECT_USING (in NAMESPACE_DECL).
IDENTIFIER_MARKED (used by search routines). IDENTIFIER_MARKED (used by search routines).
LOCAL_BINDING_P (in CPLUS_BINDING) LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV)
1: IDENTIFIER_VIRTUAL_P. 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -43,17 +44,21 @@ Boston, MA 02111-1307, USA. */ ...@@ -43,17 +44,21 @@ Boston, MA 02111-1307, USA. */
C_DECLARED_LABEL_FLAG. C_DECLARED_LABEL_FLAG.
INHERITED_VALUE_BINDING_P (in CPLUS_BINDING) INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
BASELINK_P (in TREE_LIST) BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
2: IDENTIFIER_OPNAME_P. 2: IDENTIFIER_OPNAME_P.
BINFO_VBASE_MARKED. BINFO_VBASE_MARKED.
BINFO_FIELDS_MARKED. BINFO_FIELDS_MARKED.
TYPE_VIRTUAL_P. TYPE_VIRTUAL_P.
ICS_THIS_FLAG (in _CONV)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED. BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED. BINFO_PUSHDECLS_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
4: BINFO_NEW_VTABLE_MARKED. 4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
5: Not used. 5: Not used.
6: Not used. 6: Not used.
...@@ -2140,6 +2145,14 @@ extern int flag_new_for_scope; ...@@ -2140,6 +2145,14 @@ extern int flag_new_for_scope;
enum tag_types { record_type, class_type, union_type, enum_type, enum tag_types { record_type, class_type, union_type, enum_type,
signature_type }; signature_type };
/* The various kinds of lvalues we distinguish. */
typedef enum cp_lvalue_kind {
clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */
clk_class = 2, /* An rvalue of class-type. */
clk_bitfield = 4, /* An lvalue for a bit-field. */
} cp_lvalue_kind;
/* Zero means prototype weakly, as in ANSI C (no args means nothing). /* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */ Each language context defines how this variable should be set. */
extern int strict_prototype; extern int strict_prototype;
...@@ -2753,6 +2766,7 @@ extern int enforce_access PROTO((tree, tree)); ...@@ -2753,6 +2766,7 @@ extern int enforce_access PROTO((tree, tree));
extern tree convert_default_arg PROTO((tree, tree, tree)); extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree)); extern tree convert_arg_to_ellipsis PROTO((tree));
extern int is_properly_derived_from PROTO((tree, tree)); extern int is_properly_derived_from PROTO((tree, tree));
extern tree initialize_reference PROTO((tree, tree));
/* in class.c */ /* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
...@@ -3363,7 +3377,7 @@ extern tree arbitrate_lookup PROTO((tree, tree, tree)); ...@@ -3363,7 +3377,7 @@ extern tree arbitrate_lookup PROTO((tree, tree, tree));
extern int pod_type_p PROTO((tree)); extern int pod_type_p PROTO((tree));
extern void unshare_base_binfos PROTO((tree)); extern void unshare_base_binfos PROTO((tree));
extern int member_p PROTO((tree)); extern int member_p PROTO((tree));
extern int real_lvalue_p PROTO((tree)); extern cp_lvalue_kind real_lvalue_p PROTO((tree));
extern tree build_min PVPROTO((enum tree_code, tree, ...)); extern tree build_min PVPROTO((enum tree_code, tree, ...));
extern tree build_min_nt PVPROTO((enum tree_code, ...)); extern tree build_min_nt PVPROTO((enum tree_code, ...));
extern tree min_tree_cons PROTO((tree, tree, tree)); extern tree min_tree_cons PROTO((tree, tree, tree));
......
...@@ -1409,7 +1409,22 @@ dump_expr (t, nop) ...@@ -1409,7 +1409,22 @@ dump_expr (t, nop)
break; break;
case AGGR_INIT_EXPR: case AGGR_INIT_EXPR:
OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t))); {
tree fn = NULL_TREE;
if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
if (fn && TREE_CODE (fn) == FUNCTION_DECL)
{
if (DECL_CONSTRUCTOR_P (fn))
OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
else
dump_decl (fn, 0);
}
else
dump_expr (TREE_OPERAND (t, 0), 0);
}
OB_PUTC ('('); OB_PUTC ('(');
if (TREE_OPERAND (t, 1)) if (TREE_OPERAND (t, 1))
dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
......
...@@ -1177,6 +1177,10 @@ expand_default_init (binfo, true_exp, exp, init, flags) ...@@ -1177,6 +1177,10 @@ expand_default_init (binfo, true_exp, exp, init, flags)
to run a new constructor; and catching an exception, where we to run a new constructor; and catching an exception, where we
have already built up the constructor call so we could wrap it have already built up the constructor call so we could wrap it
in an exception region. */; in an exception region. */;
else if (TREE_CODE (init) == CONSTRUCTOR)
/* A brace-enclosed initializer has whatever type is
required. There's no need to convert it. */
;
else else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
......
...@@ -3150,6 +3150,12 @@ add_conversions (binfo, data) ...@@ -3150,6 +3150,12 @@ add_conversions (binfo, data)
return NULL_TREE; return NULL_TREE;
} }
/* Return a TREE_LIST containing all the non-hidden user-defined
conversion functions for TYPE (and its base-classes). The
TREE_VALUE of each node is a FUNCTION_DECL or an OVERLOAD
containing the conversion functions. The TREE_PURPOSE is the BINFO
from which the conversion functions in this node were selected. */
tree tree
lookup_conversions (type) lookup_conversions (type)
tree type; tree type;
......
...@@ -36,27 +36,30 @@ static int list_hash PROTO((tree, tree, tree)); ...@@ -36,27 +36,30 @@ static int list_hash PROTO((tree, tree, tree));
static tree list_hash_lookup PROTO((int, tree, tree, tree)); static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree)); static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree)); static int avoid_overlap PROTO((tree, tree));
static int lvalue_p_1 PROTO((tree, int)); static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree)); static int equal_functions PROTO((tree, tree));
static tree no_linkage_helper PROTO((tree)); static tree no_linkage_helper PROTO((tree));
static tree build_srcloc PROTO((char *, int)); static tree build_srcloc PROTO((char *, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y)) #define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Returns non-zero if REF is an lvalue. If /* If REF is an lvalue, returns the kind of lvalue that REF is.
TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
are considered lvalues. */ non-zero, rvalues of class type are considered lvalues. */
static int static cp_lvalue_kind
lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref; tree ref;
int treat_class_rvalues_as_lvalues; int treat_class_rvalues_as_lvalues;
{ {
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1; return clk_ordinary;
if (ref == current_class_ptr && flag_this_is_variable <= 0) if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0; return clk_none;
switch (TREE_CODE (ref)) switch (TREE_CODE (ref))
{ {
...@@ -64,7 +67,6 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -64,7 +67,6 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
what they refer to are valid lvals. */ what they refer to are valid lvals. */
case PREINCREMENT_EXPR: case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR: case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR: case SAVE_EXPR:
case UNSAVE_EXPR: case UNSAVE_EXPR:
case TRY_CATCH_EXPR: case TRY_CATCH_EXPR:
...@@ -75,20 +77,37 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -75,20 +77,37 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
return lvalue_p_1 (TREE_OPERAND (ref, 0), return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues); treat_class_rvalues_as_lvalues);
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
&& TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
&& DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
rvalue we want to preserve that information. */
op1_lvalue_kind &= ~clk_ordinary;
/* The lvalue is for a btifield. */
op1_lvalue_kind |= clk_bitfield;
}
return op1_lvalue_kind;
case STRING_CST: case STRING_CST:
return 1; return clk_ordinary;
case VAR_DECL: case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref) if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref) && DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref)) && DECL_IN_AGGR_P (ref))
return 0; return clk_none;
case INDIRECT_REF: case INDIRECT_REF:
case ARRAY_REF: case ARRAY_REF:
case PARM_DECL: case PARM_DECL:
case RESULT_DECL: case RESULT_DECL:
if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1; return clk_ordinary;
break; break;
/* A currently unresolved scope ref. */ /* A currently unresolved scope ref. */
...@@ -96,72 +115,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -96,72 +115,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
my_friendly_abort (103); my_friendly_abort (103);
case OFFSET_REF: case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1; return clk_ordinary;
return (lvalue_p_1 (TREE_OPERAND (ref, 0), /* Fall through. */
treat_class_rvalues_as_lvalues) case MAX_EXPR:
&& lvalue_p_1 (TREE_OPERAND (ref, 1), case MIN_EXPR:
treat_class_rvalues_as_lvalues)); op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
break; break;
case COND_EXPR: case COND_EXPR:
return (lvalue_p_1 (TREE_OPERAND (ref, 1), op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues) treat_class_rvalues_as_lvalues);
&& lvalue_p_1 (TREE_OPERAND (ref, 2), op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues)); treat_class_rvalues_as_lvalues);
break;
case MODIFY_EXPR: case MODIFY_EXPR:
return 1; return clk_ordinary;
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1), return lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues); treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
return (lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues)
&& lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues));
case TARGET_EXPR: case TARGET_EXPR:
return treat_class_rvalues_as_lvalues; return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
case CALL_EXPR: case CALL_EXPR:
return (treat_class_rvalues_as_lvalues return ((treat_class_rvalues_as_lvalues
&& IS_AGGR_TYPE (TREE_TYPE (ref))); && IS_AGGR_TYPE (TREE_TYPE (ref)))
? clk_class : clk_none);
case FUNCTION_DECL: case FUNCTION_DECL:
/* All functions (except non-static-member functions) are /* All functions (except non-static-member functions) are
lvalues. */ lvalues. */
return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref); return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : clk_ordinary);
default: default:
break; break;
} }
return 0; /* If one operand is not an lvalue at all, then this expression is
not an lvalue. */
if (!op1_lvalue_kind || !op2_lvalue_kind)
return clk_none;
/* Otherwise, it's an lvalue, and it has all the odd properties
contributed by either operand. */
op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
/* It's not an ordinary lvalue if it involves either a bit-field or
a class rvalue. */
if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
op1_lvalue_kind &= ~clk_ordinary;
return op1_lvalue_kind;
} }
/* Return nonzero if REF is an lvalue valid for this language. /* If REF is an lvalue, returns the kind of lvalue that REF is.
Lvalues can be assigned, unless they have TREE_READONLY, or unless Otherwise, returns clk_none. Lvalues can be assigned, unless they
they are FUNCTION_DECLs. Lvalues can have their address taken, have TREE_READONLY, or unless they are FUNCTION_DECLs. Lvalues can
unless they have DECL_REGISTER. */ have their address taken, unless they have DECL_REGISTER. */
int cp_lvalue_kind
real_lvalue_p (ref) real_lvalue_p (ref)
tree ref; tree ref;
{ {
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0); return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
} }
/* This differs from real_lvalue_p in that class rvalues are considered /* This differs from real_lvalue_p in that class rvalues are
lvalues. */ considered lvalues. */
int int
lvalue_p (ref) lvalue_p (ref)
tree ref; tree ref;
{ {
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1); return
(lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
} }
/* Return nonzero if REF is an lvalue valid for this language; /* Return nonzero if REF is an lvalue valid for this language;
...@@ -193,6 +224,11 @@ build_cplus_new (type, init) ...@@ -193,6 +224,11 @@ build_cplus_new (type, init)
tree slot; tree slot;
tree rval; tree rval;
/* Make sure that we're not trying to create an instance of an
abstract class. */
if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
abstract_virtuals_error (NULL_TREE, type);
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR) if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init); return convert (type, init);
......
...@@ -7122,8 +7122,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -7122,8 +7122,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl) if (fndecl)
savew = warningcount, savee = errorcount; savew = warningcount, savee = errorcount;
rhs = convert_to_reference (type, rhs, CONV_IMPLICIT, flags, rhs = initialize_reference (type, rhs);
exp ? exp : error_mark_node);
if (fndecl) if (fndecl)
{ {
if (warningcount > savew) if (warningcount > savew)
......
// Build don't link: // Build don't link:
// Based on a bug report by Stephen Vavasis <vavasis@CS.Cornell.EDU> // Based on a bug report by Stephen Vavasis <vavasis@CS.Cornell.EDU>
// excess errors test - XFAIL *-*-*
// declares template operator!= // declares template operator!=
#include <utility> #include <utility>
......
//Build don't link: //Build don't link:
// the template operator!= interferes. It should be in a namespace. // the template operator!= interferes. It should be in a namespace.
// excess errors test - XFAIL *-*-*
#include <utility> #include <utility>
......
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