86th Cygnus<->FSF quick merge

From-SVN: r12126
This commit is contained in:
Mike Stump 1996-05-30 19:11:58 +00:00
parent 2670328aa5
commit e349ee739e
16 changed files with 767 additions and 318 deletions

View File

@ -3,6 +3,131 @@ Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
* decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
(finish_file): Likewise.
Wed May 29 17:04:33 1996 Mike Stump <mrs@cygnus.com>
* cvt.c (build_up_reference): Redo how and when temporaries are
created.
* decl.c (grok_reference_init): Don't try and be smart about
running cleanups.
Wed May 29 16:02:08 1996 Mike Stump <mrs@cygnus.com>
* cvt.c (build_up_reference): Add NULL_TREE to all calls to build
(TARGET_EXPR...), now that it has 4 arguments.
* tree.c (build_cplus_new): Ditto.
Thu May 23 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* error.c (dump_expr, case CAST_EXPR): Handle T() properly.
* pt.c (instantiate_decl): Don't call push/pop_cp_function_context.
* decl.c (struct saved_scope): Remove named_labels,
{base,member}_init_list.
(maybe_push_to_top_level): Don't set them. Call
push_cp_function_context if appropriate.
(pop_from_top_level): Likewise.
* method.c (do_build_assign_ref): Remove obsolete check of
TYPE_HAS_ASSIGN_REF (basetype).
* decl.c (grokfndecl): Diagnose user definition of
implicitly-declared methods.
Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com>
* method.c (do_build_copy_constructor): Add code to give
meaningful error messages instead of crashing.
(do_build_assign_ref): Don't synthesize assignment operators for
classes containing reference or const members.
* class.c (struct base_info): Remove cant_synth_copy_ctor
and cant_synth_asn_ref.
(finish_base_struct): Remove the code that tries to conditionalize
synthesis of copy constructors & assignment operators based on
access permissions. Instead, let it fail when it tries to
synthesize the copy constructor. This will give meaningful error
messages instead of silently generating code to perform a bitcopy.
Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
* lex.c (real_yylex): Remove old-n-crufty #if 0 code for
determining types for constant values.
* decl.c (struct named_label_list): Use instead of stuffing
random items into a TREE_LIST node.
(named_label_uses): Use the new struct.
(poplevel): Ditto.
(lookup_label): Ditto.
(define_label): Add an error message to tell the user the line
where the goto is located in addition to the destination of the
goto.
(init_decl_processing): Use NULL instead of NULL_TREE to initialize
named_label_uses.
(finish_function): Ditto.
(start_decl): Complain about defining a static data member
in a different type from which it was declared.
Wed May 22 09:33:23 1996 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (build_expr_type_conversion): Adjust.
Tue May 21 11:21:56 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_method_call): Always convert 'this' to the
appropriate type.
* search.c (add_conversions): Put the conversion function in
TREE_VALUE, the type in TREE_PURPOSE.
* cvt.c (build_type_conversion): Adjust.
* call.c (user_harshness): Adjust.
* method.c (emit_thunk): Call temporary_allocation and
permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too.
* tree.c (build_cplus_array_type): Handle tweaking of
TYPE_MAIN_VARIANT here.
* typeck.c (common_type): Not here.
* typeck.c (complete_type): Only try to complete an array type if
it has a domain.
Mon May 20 14:55:59 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokvardecl): Call complete_type.
(grokdeclarator): Call complete_type for PARM_DECLs.
Fri May 17 16:41:17 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (instantiate_class_template): Re-set
CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1.
Fri May 17 14:56:55 1996 Mike Stump <mrs@cygnus.com>
* cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now
smart enough to do it right.
* tree.c (cp_expand_decl_cleanup): Ditto.
* decl.c (cp_finish_decl): Use expand_decl_cleanup instead of
cp_expand_decl_cleanup.
(store_parm_decls): Ditto.
(hack_incomplete_structures): Ditto.
* except.c (push_eh_cleanup): Ditto.
Fri May 17 13:13:51 1996 Mike Stump <mrs@cygnus.com>
* expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++
frontend to the backend where it belongs.
* tree.c (unsave_expr): Ditto.
(unsave_expr_now): Ditto.
* tree.def (UNSAVE_EXPR): Ditto.
* cp-tree.h (unsave_expr): Ditto.
(unsave_expr_now): Ditto.
Fri May 17 11:02:41 1996 Mike Stump <mrs@cygnus.com>
* init.c (emit_base_init): Make sure the partial EH cleanups live
on the function_obstack.
Thu May 16 15:29:33 1996 Bob Manson <manson@charmed.cygnus.com>
* expr.c (do_case): Don't try to dereference null TREE_TYPEs
@ -2369,7 +2494,7 @@ Mon Nov 13 15:45:34 1995 Mike Stump <mrs@cygnus.com>
indirect binding.
* decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast
as they are unused.
(expand_static_init): Diotto.
(expand_static_init): Ditto.
(cplus_expand_expr_stmt): Ditto.
* decl2.c (finish_file): Ditto.
* init.c (perform_member_init): Ditto.

View File

@ -641,10 +641,10 @@ user_harshness (type, parmtype)
{
struct harshness_code tmp;
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
continue;
if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
if (tmp = convert_harshness (type, TREE_PURPOSE (conv), NULL_TREE),
(tmp.code < USER_CODE) && (tmp.distance >= 0))
{
if (winner)
@ -2531,8 +2531,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
basetype = TREE_TYPE (instance);
if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
&& TYPE_USES_COMPLEX_INHERITANCE (basetype))
if (TYPE_METHOD_BASETYPE (TREE_TYPE (function))
!= TYPE_MAIN_VARIANT (basetype))
{
basetype = DECL_CLASS_CONTEXT (function);
instance_ptr = convert_pointer_to (basetype, instance_ptr);

View File

@ -1408,8 +1408,6 @@ struct base_info
tree rtti;
char cant_have_default_ctor;
char cant_have_const_ctor;
char cant_synth_copy_ctor;
char cant_synth_asn_ref;
char no_const_asn_ref;
char base_has_virtual;
};
@ -1465,13 +1463,8 @@ finish_base_struct (t, b, t_binfo)
TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
}
if (TYPE_HAS_INIT_REF (basetype)
&& !TYPE_HAS_CONST_INIT_REF (basetype))
if (! TYPE_HAS_CONST_INIT_REF (basetype))
b->cant_have_const_ctor = 1;
if (! TYPE_HAS_INIT_REF (basetype)
|| (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2
&& ! is_friend_type (t, basetype)))
b->cant_synth_copy_ctor = 1;
if (TYPE_HAS_CONSTRUCTOR (basetype)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
@ -1488,11 +1481,6 @@ finish_base_struct (t, b, t_binfo)
if (TYPE_HAS_ASSIGN_REF (basetype)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
if (! TYPE_HAS_ASSIGN_REF (basetype)
|| TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype)
|| (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2
&& ! is_friend_type (t, basetype)))
b->cant_synth_asn_ref = 1;
b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
@ -1645,8 +1633,6 @@ finish_base_struct (t, b, t_binfo)
{
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
b->cant_synth_asn_ref = 1;
b->cant_synth_copy_ctor = 1;
}
}
{
@ -1660,8 +1646,6 @@ finish_base_struct (t, b, t_binfo)
if (extra_warnings)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
b->cant_synth_asn_ref = 1;
b->cant_synth_copy_ctor = 1;
}
}
}
@ -3016,8 +3000,6 @@ finish_struct_1 (t, attributes, warn_anon)
tree vfields;
int cant_have_default_ctor;
int cant_have_const_ctor;
int cant_synth_copy_ctor;
int cant_synth_asn_ref;
int no_const_asn_ref;
/* The index of the first base class which has virtual
@ -3108,8 +3090,6 @@ finish_struct_1 (t, attributes, warn_anon)
CLASSTYPE_RTTI (t) = base_info.rtti;
cant_have_default_ctor = base_info.cant_have_default_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor;
cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
cant_synth_asn_ref = base_info.cant_synth_asn_ref;
no_const_asn_ref = base_info.no_const_asn_ref;
base_has_virtual = base_info.base_has_virtual;
n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
@ -3126,8 +3106,6 @@ finish_struct_1 (t, attributes, warn_anon)
last_x = NULL_TREE;
cant_have_default_ctor = 0;
cant_have_const_ctor = 0;
cant_synth_copy_ctor = 0;
cant_synth_asn_ref = 0;
no_const_asn_ref = 0;
base_has_virtual = 0;
}
@ -3273,7 +3251,7 @@ finish_struct_1 (t, attributes, warn_anon)
#if 0
if (DECL_NAME (x) == constructor_name (t))
cant_have_default_ctor = cant_synth_copy_ctor = 1;
cant_have_default_ctor = 1;
#endif
if (TREE_TYPE (x) == error_mark_node)
@ -3313,8 +3291,8 @@ finish_struct_1 (t, attributes, warn_anon)
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1;
cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
{
@ -3336,8 +3314,8 @@ finish_struct_1 (t, attributes, warn_anon)
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1;
cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
&& extra_warnings)
@ -3508,18 +3486,10 @@ finish_struct_1 (t, attributes, warn_anon)
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
}
if (! TYPE_HAS_INIT_REF (type)
|| (TYPE_HAS_NONPUBLIC_CTOR (type)
&& ! is_friend (t, type)))
cant_synth_copy_ctor = 1;
else if (!TYPE_HAS_CONST_INIT_REF (type))
if (!TYPE_HAS_CONST_INIT_REF (type))
cant_have_const_ctor = 1;
if (! TYPE_HAS_ASSIGN_REF (type)
|| (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type)
&& ! is_friend (t, type)))
cant_synth_asn_ref = 1;
else if (!TYPE_HAS_CONST_ASSIGN_REF (type))
if (!TYPE_HAS_CONST_ASSIGN_REF (type))
no_const_asn_ref = 1;
if (TYPE_HAS_CONSTRUCTOR (type)
@ -3614,8 +3584,7 @@ finish_struct_1 (t, attributes, warn_anon)
}
/* Create default copy constructor, if needed. */
if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor
&& ! IS_SIGNATURE (t))
if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t))
{
/* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */
@ -3630,8 +3599,7 @@ finish_struct_1 (t, attributes, warn_anon)
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
&& ! IS_SIGNATURE (t))
if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t))
{
tree default_fn = cons_up_default_function (t, name,
5 + no_const_asn_ref);

View File

@ -2403,7 +2403,6 @@ extern void print_lang_statistics PROTO((void));
extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree));
extern tree break_out_target_exprs PROTO((tree));
extern int cp_expand_decl_cleanup PROTO((tree, tree));
extern tree get_type_decl PROTO((tree));
extern tree vec_binfo_member PROTO((tree, tree));
extern tree hack_decl_function_context PROTO((tree));

View File

@ -596,13 +596,24 @@ build_up_reference (type, arg, flags, checkconst)
if (TREE_ADDRESSABLE (targ) == 0)
{
tree temp;
if (! (flags&INDIRECT_BIND)
&& toplevel_bindings_p ())
{
tree temp = get_temp_name (argtype, 0);
/* Give this new temp some rtl and initialize it. */
DECL_INITIAL (temp) = targ;
TREE_STATIC (temp) = 1;
cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
/* Do this after declaring it static. */
rval = build_unary_op (ADDR_EXPR, temp, 0);
TREE_TYPE (rval) = type;
literal_flag = TREE_CONSTANT (rval);
goto done;
}
if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
{
temp = build_cplus_new (argtype, targ);
rval = build1 (ADDR_EXPR, type, temp);
goto done;
arg = build_cplus_new (argtype, targ);
}
else if (flags&INDIRECT_BIND)
{
@ -611,41 +622,41 @@ build_up_reference (type, arg, flags, checkconst)
use INDIRECT_BIND. */
tree slot = build (VAR_DECL, argtype);
layout_decl (slot, 0);
rval = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE);
rval = build1 (ADDR_EXPR, type, rval);
goto done;
arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
}
else
{
temp = get_temp_name (argtype, 0);
if (toplevel_bindings_p ())
{
/* Give this new temp some rtl and initialize it. */
DECL_INITIAL (temp) = targ;
TREE_STATIC (temp) = 1;
cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
/* Do this after declaring it static. */
rval = build_unary_op (ADDR_EXPR, temp, 0);
TREE_TYPE (rval) = type;
literal_flag = TREE_CONSTANT (rval);
goto done;
}
tree temp = get_temp_name (argtype, 0);
rval = build_unary_op (ADDR_EXPR, temp, 0);
if (binfo && !BINFO_OFFSET_ZEROP (binfo))
rval = convert_pointer_to (target_type, rval);
else
{
rval = build_unary_op (ADDR_EXPR, temp, 0);
if (binfo && !BINFO_OFFSET_ZEROP (binfo))
rval = convert_pointer_to (target_type, rval);
else
TREE_TYPE (rval) = type;
TREE_TYPE (rval) = type;
temp = build (MODIFY_EXPR, argtype, temp, arg);
TREE_SIDE_EFFECTS (temp) = 1;
return build (COMPOUND_EXPR, type, temp, rval);
temp = build (MODIFY_EXPR, argtype, temp, arg);
TREE_SIDE_EFFECTS (temp) = 1;
return build (COMPOUND_EXPR, type, temp, rval);
}
}
if (! (flags&INDIRECT_BIND))
{
if (TREE_CODE (arg) == TARGET_EXPR)
{
tree decl = TREE_OPERAND (arg, 0);
tree cleanup;
if (! toplevel_bindings_p ())
{
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
if (cleanup)
expand_decl_cleanup (decl, cleanup);
}
}
}
else
rval = build1 (ADDR_EXPR, type, arg);
rval = build1 (ADDR_EXPR, type, arg);
done:
if (TYPE_USES_COMPLEX_INHERITANCE (argtype)
@ -1498,10 +1509,10 @@ build_type_conversion (code, xtype, expr, for_sure)
/* Nope; try looking for others. */
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
continue;
if (can_convert (xtype, TREE_VALUE (conv)))
if (can_convert (xtype, TREE_PURPOSE (conv)))
{
if (winner)
{
@ -1510,7 +1521,7 @@ build_type_conversion (code, xtype, expr, for_sure)
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
TREE_PURPOSE (winner), TREE_PURPOSE (conv));
}
return NULL_TREE;
}
@ -1521,7 +1532,7 @@ build_type_conversion (code, xtype, expr, for_sure)
if (winner)
return build_type_conversion_1 (xtype, basetype, expr,
TREE_PURPOSE (winner), for_sure);
DECL_NAME (TREE_VALUE (winner)), for_sure);
return NULL_TREE;
}
@ -1580,10 +1591,10 @@ build_expr_type_conversion (desires, expr, complain)
int win = 0;
tree candidate;
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
continue;
candidate = TREE_VALUE (conv);
candidate = TREE_PURPOSE (conv);
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
@ -1609,7 +1620,7 @@ build_expr_type_conversion (desires, expr, complain)
cp_error ("ambiguous default type conversion from `%T'",
basetype);
cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
TREE_PURPOSE (winner), TREE_PURPOSE (conv));
}
return error_mark_node;
}
@ -1620,11 +1631,11 @@ build_expr_type_conversion (desires, expr, complain)
if (winner)
{
tree type = TREE_VALUE (winner);
tree type = TREE_PURPOSE (winner);
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
return build_type_conversion_1 (type, basetype, expr,
TREE_PURPOSE (winner), 1);
DECL_NAME (TREE_VALUE (winner)), 1);
}
return NULL_TREE;
@ -1819,6 +1830,41 @@ null_ptr_cst (t)
return (INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t));
}
tree
build_conv (code, type, from)
enum tree_code code;
tree type, from;
{
tree t = build1 (code, type, from);
int rank = ICS_STD_RANK (from);
switch (code)
{
case PROMO_CONV:
if (rank < PROMO_RANK)
rank = PROMO_RANK;
break;
case PTR_CONV:
case PMEM_CONV:
case BASE_CONV:
case STD_CONV:
if (rank < STD_RANK)
rank = STD_RANK;
break;
case PBOOL_CONV:
if (rank < PBOOL_RANK)
rank = PBOOL_RANK;
break;
default:
break;
}
ICS_STD_RANK (t) = rank;
ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
return t;
}
tree
standard_conversion (to, from, expr)
tree to, from, expr;
@ -1830,25 +1876,27 @@ standard_conversion (to, from, expr)
if (from == to)
return from;
conv = from;
conv = build1 (EXACT_CONV, from, expr);
if (TREE_CODE (expr) == USER_CONV)
ICS_USER_FLAG (conv) = 1;
if (fcode == FUNCTION_TYPE)
{
from = build_pointer_type (from);
fcode = TREE_CODE (from);
conv = build1 (LVALUE_CONV, from, conv);
conv = build_conv (LVALUE_CONV, from, conv);
}
else if (fcode == ARRAY_TYPE)
{
from = build_pointer_type (TREE_TYPE (from));
fcode = TREE_CODE (from);
conv = build1 (LVALUE_CONV, from, conv);
conv = build_conv (LVALUE_CONV, from, conv);
}
if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
&& expr && null_ptr_cst (expr))
{
conv = build1 (CONV_CONV, to, conv);
conv = build_conv (STD_CONV, to, conv);
}
else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
{
@ -1864,7 +1912,7 @@ standard_conversion (to, from, expr)
from = cp_build_type_variant (void_type_node,
TYPE_READONLY (TREE_TYPE (from)),
TYPE_VOLATILE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
conv = build_conv (PTR_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
{
@ -1877,7 +1925,7 @@ standard_conversion (to, from, expr)
1)))
{
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
conv = build_conv (PMEM_CONV, from, conv);
}
else
return 0;
@ -1890,7 +1938,7 @@ standard_conversion (to, from, expr)
from = cp_build_type_variant (TREE_TYPE (to),
TYPE_READONLY (TREE_TYPE (from)),
TYPE_VOLATILE (TREE_TYPE (from)));
conv = build1 (CONV_CONV, from, conv);
conv = build_conv (PTR_CONV, from, conv);
}
else
return 0;
@ -1901,7 +1949,7 @@ standard_conversion (to, from, expr)
if (! comptypes (from, to, 1) && comp_ptr_ttypes (to, from))
{
from = to;
conv = build1 (QUAL_CONV, from, conv);
conv = build_conv (QUAL_CONV, from, conv);
}
}
else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
@ -1923,29 +1971,32 @@ standard_conversion (to, from, expr)
TYPE_VOLATILE (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
conv = build1 (CONV_CONV, from, conv);
conv = build_conv (PMEM_CONV, from, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
if (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
|| fcode == POINTER_TYPE)
return build1 (CONV_CONV, to, conv);
else
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
|| fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
return 0;
if (fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))
conv = build_conv (PBOOL_CONV, to, conv);
else
conv = build_conv (STD_CONV, to, conv);
}
else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
else if (to == type_promotes_to (from))
conv = build1 (PROMO_CONV, to, conv);
conv = build_conv (PROMO_CONV, to, conv);
else
conv = build1 (CONV_CONV, to, conv);
conv = build_conv (STD_CONV, to, conv);
}
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from))
{
conv = build1 (CONV_CONV, to, conv);
conv = build_conv (BASE_CONV, to, conv);
}
else
return 0;
@ -1958,16 +2009,366 @@ implicit_conversion (to, from, expr, flags)
tree to, from, expr;
int flags;
{
tree conv = standard_conversion (to, from, expr);
tree t, conv = standard_conversion (to, from, expr);
struct z_candidate *cand;
if (conv || (flags & LOOKUP_NO_CONVERSION))
return conv;
flags |= LOOKUP_NO_CONVERSION;
/* try constructors */;
/* try conversion ops */;
cand = build_user_type_conversion_1 (to, expr, flags);
if (! cand)
return NULL_TREE;
conv = cand->second_conv;
for (t = conv; TREE_CODE (TREE_OPERAND (t, 0)) != EXACT_MATCH; )
t = TREE_OPERAND (t, 0));
TREE_OPERAND (t, 0) = build (USER_CONV
return conv;
}
struct z_candidate *
add_method_candidate (candidates, method, instance, parms, flags)
struct z_candidate *candidates;
tree method, instance, parms;
int flags;
{
}
struct z_candidate *
build_user_type_conversion_1 (totype, expr, flags)
tree totype, expr;
int flags;
{
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, t;
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
if (IS_AGGR_TYPE (fromtype))
convs = lookup_conversions (fromtype);
if (ctors)
ctors = TREE_VALUE (ctors);
for (; ctors; ctors = DECL_CHAIN (ctors))
{
candidates = add_ctor_candidate (candidates, ctors, expr, flags);
}
for (; convs; convs = TREE_CHAIN (convs))
{
tree fn = TREE_VALUE (convs);
tree ics = standard_conversion (totype, TREE_TYPE (TREE_TYPE (fn)), 0);
if (ics)
{
candidates = add_method_candidate
(candidates, fn, expr, NULL_TREE, flags);
candidates->second_ics = ics;
}
}
if (! any_viable (candidates))
{
if (flags & LOOKUP_COMPLAIN)
cp_error ("no viable candidates");
return 0;
}
candidates = splice_viable (candidates);
cand = tourney (candidates, totype);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
cp_error ("ambiguous user-defined type conversion");
}
return cand;
}
/* Compare two implicit conversion sequences according to the rules set out in
[over.ics.rank]. Return values:
1: ics1 is better than ics2
-1: ics2 is better than ics1
0: ics1 and ics2 are indistinguishable */
int
compare_ics (ics1, ics2)
tree ics1, ics2;
{
tree main1, main2;
if (ICS_RANK (ics1) > ICS_RANK (ics2))
return 1;
else if (ICS_RANK (ics1) < ICS_RANK (ics2))
return -1;
/* User-defined conversion sequence U1 is a better conversion sequence
than another user-defined conversion sequence U2 if they contain the
same user-defined conversion operator or constructor and if the sec-
ond standard conversion sequence of U1 is better than the second
standard conversion sequence of U2. */
if (ICS_RANK (ics1) == USER_RANK)
{
tree t1, t2;
for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
;
for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
;
if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
return 0;
else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return 1;
else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return -1;
/* else fall through */
}
#if 0 /* Handled by ranking */
/* A conversion that is not a conversion of a pointer, or pointer to
member, to bool is better than another conversion that is such a
conversion. */
{
int bool1 = TREE_CODE (ics1) == BOOL_CONV;
int bool2 = TREE_CODE (ics2) == BOOL_CONV;
if (bool1)
{
tree it = TREE_TYPE (TREE_OPERAND (ics1, 0));
if (TREE_CODE (it) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_TYPE (it))
bool1 = 0;
}
if (bool2)
{
tree it = TREE_TYPE (TREE_OPERAND (ics2, 0));
if (TREE_CODE (it) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_TYPE (it))
bool2 = 0;
}
if (bool1 && ! bool2)
return 1;
if (bool2 && ! bool1)
return -1;
}
#endif
if (TREE_CODE (ics1) == QUAL_CONV)
main1 = TREE_OPERAND (ics1, 0);
else
main1 = ics1;
if (TREE_CODE (ics2) == QUAL_CONV)
main2 = TREE_OPERAND (ics2, 0);
else
main2 = ics2;
if (TREE_CODE (main1) != TREE_CODE (main2))
return 0;
if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV
|| TREE_CODE (main1) == REF_BIND)
{
tree to1 = TREE_TYPE (main1);
tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0));
tree to2 = TREE_TYPE (main2);
tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0));
int distf, distt;
/* Standard conversion sequence S1 is a better conversion sequence than
standard conversion sequence S2 if...
S1 and S2 differ only in their qualification conversion and they
yield types identical except for cv-qualifiers and S2 adds all the
qualifiers that S1 adds (and in the same places) and S2 adds yet
more cv-qualifiers than S1, or the similar case with reference
binding15). */
if (from1 == from2 && to1 == to2)
{
to1 = TREE_TYPE (TREE_TYPE (ics1));
to2 = TREE_TYPE (TREE_TYPE (ics2));
if (TYPE_READONLY (to1) >= TYPE_READONLY (to2)
&& TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2))
return 1;
else if (TYPE_READONLY (to1) > TYPE_READONLY (to2)
&& TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
return 1;
else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2)
&& TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2))
return -1;
else if (TYPE_READONLY (to1) < TYPE_READONLY (to2)
&& TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
return -1;
return 0;
}
if (TYPE_PTRMEMFUNC_P (to1))
{
to1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1));
from1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1));
}
else
{
to1 = TREE_TYPE (to1);
from1 = TREE_TYPE (from1);
if (TREE_CODE (to1) == OFFSET_TYPE)
{
to1 = TYPE_OFFSET_BASETYPE (to1);
from1 = TYPE_OFFSET_BASETYPE (from1);
}
}
if (TYPE_PTRMEMFUNC_P (to2))
{
to2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2));
from2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2));
}
else
{
to2 = TREE_TYPE (to2);
from2 = TREE_TYPE (from2);
if (TREE_CODE (to2) == OFFSET_TYPE)
{
to2 = TYPE_OFFSET_BASETYPE (to2);
from2 = TYPE_OFFSET_BASETYPE (from2);
}
}
if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2)))
return 0;
distf = get_base_distance (from1, from2, 0, 0);
if (distf == -1)
distf = -get_base_distance (from2, from1, 0, 0);
if (distf == -1)
return 0;
/* If class B is derived directly or indirectly from class A, conver-
sion of B* to A* is better than conversion of B* to void*, and
conversion of A* to void* is better than conversion of B* to void*. */
if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE)
{
if (distf > 0)
return 1;
else if (distf < 0)
return -1;
}
else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1)
&& get_base_distance (to1, from1, 0, 0) != -1)
return 1;
else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
&& get_base_distance (to2, from2, 0, 0) != -1)
return -1;
if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2)))
return 0;
/* If class B is derived directly or indirectly from class A and class
C is derived directly or indirectly from B */
distt = get_base_distance (to1, to2, 0, 0);
if (distt == -1)
distt = -get_base_distance (to2, to1, 0, 0);
if (distt == -1)
return 0;
/* --conversion of C* to B* is better than conversion of C* to A*, */
if (distf == 0)
{
if (distt > 0)
return -1;
else if (distt < 0)
return 1;
}
/* --conversion of B* to A* is better than conversion of C* to A*, */
else if (distt == 0)
{
if (distf > 0)
return 1;
else if (distf < 0)
return -1;
}
}
return 0;
}
int joust (cand1, cand2)
struct z_candidate *cand1, *cand2;
{
int winner = 0;
int i;
for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i)
{
int comp = compare_ics (TREE_VEC_ELT (cand1->convs, i),
TREE_VEC_ELT (cand2->convs, i));
if (comp != 0)
{
if (winner && comp != winner)
return 0;
winner = comp;
}
}
if (winner == 0 && cand1->second_ics)
winner = compare_ics (cand1->second_ics, cand2->second_ics);
return winner;
}
struct z_candidate *
tourney (candidates)
struct z_candidate *candidates;
{
struct z_candidate *champ = candidates, *challenger;
int fate;
/* This algorithm has a worst case of O(2n) (winner is last) , and a best
case of O(n/2) (no winner); much better than a sorting algorithm. */
for (challenger = champ->next; challenger; )
{
fate = joust (champ, challenger);
if (fate == 1)
challenger = challenger->next;
else
{
if (fate == 0)
{
champ = challenger->next;
if (champ == 0)
return 0;
}
else
champ = challenger;
challenger = champ->next;
}
}
for (challenger = candidates; challenger != champ;
challenger = challenger->next)
{
fate = joust (champ, challenger);
if (fate != 1)
return 0;
}
return champ;
}
#endif

View File

@ -300,6 +300,16 @@ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
tree pfn_or_delta2_identifier, tag_identifier;
tree vt_off_identifier;
struct named_label_list
{
struct binding_level *binding_level;
tree names_in_scope;
tree label_decl;
char *filename_o_goto;
int lineno_o_goto;
struct named_label_list *next;
};
/* A list (chain of TREE_LIST nodes) of named label uses.
The TREE_PURPOSE field is the list of variables defined
the the label's scope defined at the point of use.
@ -307,11 +317,17 @@ tree vt_off_identifier;
The TREE_TYPE field holds `current_binding_level' at the
point of the label's use.
BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken.
Look at the pretty struct named_label_list. See the pretty struct
with the pretty named fields that describe what they do. See the
pretty lack of gratuitous casts. Notice the code got a lot cleaner.
Used only for jumps to as-yet undefined labels, since
jumps to defined labels can have their validity checked
by stmt.c. */
static tree named_label_uses;
static struct named_label_list *named_label_uses = NULL;
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
@ -1199,12 +1215,12 @@ poplevel (keep, reverse, functionbody)
level_chain = current_binding_level->level_chain;
if (level_chain)
{
tree labels;
for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels))
if (TREE_TYPE (labels) == (tree)current_binding_level)
struct named_label_list *labels;
for (labels = named_label_uses; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
TREE_TYPE (labels) = (tree)level_chain;
TREE_PURPOSE (labels) = level_chain->names;
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
}
}
@ -1739,11 +1755,9 @@ struct saved_scope {
tree old_bindings;
struct saved_scope *prev;
tree class_name, class_type, function_decl;
tree base_init_list, member_init_list;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
tree named_labels;
int minimal_parse_mode;
tree last_function_parms;
tree template_parms;
@ -1803,6 +1817,9 @@ maybe_push_to_top_level (pseudo)
struct binding_level *b = inner_binding_level;
tree old_bindings = NULL_TREE;
if (current_function_decl)
push_cp_function_context (NULL_TREE);
if (previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
@ -1832,19 +1849,17 @@ maybe_push_to_top_level (pseudo)
s->class_name = current_class_name;
s->class_type = current_class_type;
s->function_decl = current_function_decl;
s->base_init_list = current_base_init_list;
s->member_init_list = current_member_init_list;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
s->lang_base = current_lang_base;
s->lang_stacksize = current_lang_stacksize;
s->lang_name = current_lang_name;
s->named_labels = named_labels;
s->minimal_parse_mode = minimal_parse_mode;
s->last_function_parms = last_function_parms;
s->template_parms = current_template_parms;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
@ -1902,8 +1917,6 @@ pop_from_top_level ()
}
current_class_name = s->class_name;
current_class_type = s->class_type;
current_base_init_list = s->base_init_list;
current_member_init_list = s->member_init_list;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
@ -1915,7 +1928,6 @@ pop_from_top_level ()
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
named_labels = s->named_labels;
minimal_parse_mode = s->minimal_parse_mode;
last_function_parms = s->last_function_parms;
current_template_parms = s->template_parms;
@ -1923,6 +1935,9 @@ pop_from_top_level ()
previous_class_values = s->previous_class_values;
free (s);
if (current_function_decl)
pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@ -3717,13 +3732,20 @@ lookup_label (id)
if ((decl == NULL_TREE
|| DECL_SOURCE_LINE (decl) == 0)
&& (named_label_uses == NULL_TREE
|| TREE_PURPOSE (named_label_uses) != current_binding_level->names
|| TREE_VALUE (named_label_uses) != decl))
&& (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl))
{
named_label_uses
= tree_cons (current_binding_level->names, decl, named_label_uses);
TREE_TYPE (named_label_uses) = (tree)current_binding_level;
struct named_label_list *new_ent;
new_ent
= (struct named_label_list*)oballoc (sizeof (struct named_label_list));
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
new_ent->lineno_o_goto = lineno;
new_ent->filename_o_goto = input_filename;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
/* Use a label already defined or ref'd with this name. */
@ -3754,7 +3776,7 @@ lookup_label (id)
SET_IDENTIFIER_LABEL_VALUE (id, decl);
named_labels = tree_cons (NULL_TREE, decl, named_labels);
TREE_VALUE (named_label_uses) = decl;
named_label_uses->label_decl = decl;
return decl;
}
@ -3830,7 +3852,7 @@ define_label (filename, line, name)
}
else
{
tree uses, prev;
struct named_label_list *uses, *prev;
int identified = 0;
/* Mark label as having been defined. */
@ -3839,17 +3861,17 @@ define_label (filename, line, name)
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
for (prev = NULL_TREE, uses = named_label_uses;
uses;
prev = uses, uses = TREE_CHAIN (uses))
if (TREE_VALUE (uses) == decl)
prev = NULL;
uses = named_label_uses;
while (uses != NULL)
if (uses->label_decl == decl)
{
struct binding_level *b = current_binding_level;
while (b)
{
tree new_decls = b->names;
tree old_decls = ((tree)b == TREE_TYPE (uses)
? TREE_PURPOSE (uses) : NULL_TREE);
tree old_decls = (b == uses->binding_level)
? uses->names_in_scope : NULL_TREE;
while (new_decls != old_decls)
{
if (TREE_CODE (new_decls) == VAR_DECL
@ -3862,23 +3884,35 @@ define_label (filename, line, name)
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
if (! identified)
cp_error ("jump to label `%D'", decl);
identified = 1;
if (! identified)
{
cp_error ("jump to label `%D'", decl);
error_with_file_and_line (uses->filename_o_goto,
uses->lineno_o_goto,
" from here");
identified = 1;
}
cp_error_at (" crosses initialization of `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
if ((tree)b == TREE_TYPE (uses))
if (b == uses->binding_level)
break;
b = b->level_chain;
}
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (uses);
if (prev != NULL)
prev->next = uses->next;
else
named_label_uses = TREE_CHAIN (uses);
named_label_uses = uses->next;
uses = uses->next;
}
else
{
prev = uses;
uses = uses->next;
}
current_function_return_value = NULL_TREE;
return decl;
@ -4665,7 +4699,7 @@ init_decl_processing ()
current_function_decl = NULL_TREE;
named_labels = NULL_TREE;
named_label_uses = NULL_TREE;
named_label_uses = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
@ -5797,8 +5831,13 @@ start_decl (declarator, declspecs, initialized, raises)
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
cp_error ("`%#D' is not a static member of `%#T'", decl, context);
else if (duplicate_decls (decl, field))
decl = field;
else
{
if (DECL_CONTEXT (field) != context)
cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl));
if (duplicate_decls (decl, field))
decl = field;
}
}
else
{
@ -6034,25 +6073,7 @@ grok_reference_init (decl, type, init, cleanupp)
goto fail;
else if (tmp != NULL_TREE)
{
tree subtype = TREE_TYPE (type);
init = tmp;
/* Associate the cleanup with the reference so that we
don't get burned by "aggressive" cleanup policy. */
if (TYPE_NEEDS_DESTRUCTOR (subtype))
{
if (TREE_CODE (tmp) == ADDR_EXPR)
tmp = TREE_OPERAND (tmp, 0);
if (TREE_CODE (tmp) == TARGET_EXPR)
{
*cleanupp = build_delete
(build_pointer_type (subtype),
build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
TREE_OPERAND (tmp, 2) = error_mark_node;
}
}
DECL_INITIAL (decl) = save_expr (init);
}
else
@ -6620,7 +6641,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
/* XXX: Why don't we use decl here? */
/* Ans: Because it was already expanded? */
if (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
if (! expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
/* Cleanup used up here. */
@ -6710,7 +6731,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Store the cleanup, if there was one. */
if (cleanup)
{
if (! cp_expand_decl_cleanup (decl, cleanup))
if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
@ -7113,6 +7134,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check)
{
tmp = check_classfn (ctype, decl);
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
return tmp;
}
@ -7159,6 +7182,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
revert_static_member_fn (&decl, NULL, NULL);
last_function_parms = TREE_CHAIN (last_function_parms);
}
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
return tmp;
}
@ -7224,7 +7249,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
decl = build_decl (VAR_DECL, declarator, type);
decl = build_decl (VAR_DECL, declarator, complete_type (type));
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
@ -9118,7 +9143,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
return NULL_TREE;
}
decl = build_decl (PARM_DECL, declarator, type);
decl = build_decl (PARM_DECL, declarator, complete_type (type));
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@ -11279,7 +11304,7 @@ store_parm_decls ()
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
if (! cp_expand_decl_cleanup (parm, cleanup))
if (! expand_decl_cleanup (parm, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
parm);
parms_have_cleanups = 1;
@ -11973,7 +11998,7 @@ finish_function (lineno, call_poplevel, nested)
current_function_decl = NULL_TREE;
}
named_label_uses = NULL_TREE;
named_label_uses = NULL;
current_class_ptr = NULL_TREE;
current_class_ref = NULL_TREE;
}
@ -12200,7 +12225,7 @@ hack_incomplete_structures (type)
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
if (! cp_expand_decl_cleanup (decl, cleanup))
if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}

View File

@ -1285,7 +1285,8 @@ dump_expr (t, nop)
break;
case CAST_EXPR:
if (TREE_CHAIN (TREE_OPERAND (t, 0)))
if (TREE_OPERAND (t, 0) == NULL_TREE
|| TREE_CHAIN (TREE_OPERAND (t, 0)))
{
dump_type (TREE_TYPE (t), 0);
OB_PUTC ('(');

View File

@ -962,7 +962,7 @@ push_eh_cleanup ()
cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
build_modify_expr (saved_in_catch, NOP_EXPR,
build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
cp_expand_decl_cleanup (NULL_TREE, cleanup);
expand_decl_cleanup (NULL_TREE, cleanup);
resume_momentary (yes);
}

View File

@ -9,7 +9,7 @@
@chapter Internal Architecture of the Compiler
This is meant to describe the C++ front-end for gcc in detail.
Questions and comments to mrs@@cygnus.com.
Questions and comments to Mike Stump @code{<mrs@@cygnus.com>}.
@menu
* Limitations of g++::
@ -310,9 +310,7 @@ vtables. See also vtable and vfield.
This section describes some of the macros used on trees. The list
should be alphabetical. Eventually all macros should be documented
here. There are some postscript drawings that can be used to better
understand from of the more complex data structures, contact Mike Stump
(@code{mrs@@cygnus.com}) for information about them.
here.
@table @code
@item BINFO_BASETYPES

View File

@ -615,9 +615,14 @@ emit_base_init (t, immediately)
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
start_protect ();
/* All cleanups must be on the function_obstack. */
push_obstacks_nochange ();
resume_temporary_allocation ();
protect_list = tree_cons (NULL_TREE,
build_partial_cleanup_for (base_binfo),
protect_list);
pop_obstacks ();
}
rbase_init_list = TREE_CHAIN (rbase_init_list);

View File

@ -2750,24 +2750,6 @@ identifier_typedecl_value (node)
return NULL_TREE;
}
struct try_type
{
tree *node_var;
char unsigned_flag;
char long_flag;
char long_long_flag;
};
struct try_type type_sequence[] =
{
{ &integer_type_node, 0, 0, 0},
{ &unsigned_type_node, 1, 0, 0},
{ &long_integer_type_node, 0, 1, 0},
{ &long_unsigned_type_node, 1, 1, 0},
{ &long_long_integer_type_node, 0, 1, 1},
{ &long_long_unsigned_type_node, 1, 1, 1}
};
int
real_yylex ()
{
@ -3528,83 +3510,10 @@ real_yylex ()
yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
#if 0
/* Find the first allowable type that the value fits in. */
type = 0;
for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
i++)
if (!(spec_long && !type_sequence[i].long_flag)
&& !(spec_long_long && !type_sequence[i].long_long_flag)
&& !(spec_unsigned && !type_sequence[i].unsigned_flag)
/* A hex or octal constant traditionally is unsigned. */
&& !(base != 10 && flag_traditional
&& !type_sequence[i].unsigned_flag)
/* A decimal constant can't be unsigned int
unless explicitly specified. */
&& !(base == 10 && !spec_unsigned
&& *type_sequence[i].node_var == unsigned_type_node))
if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
{
type = *type_sequence[i].node_var;
break;
}
if (flag_traditional && type == long_unsigned_type_node
&& !spec_unsigned)
type = long_integer_type_node;
if (type == 0)
{
type = long_long_integer_type_node;
warning ("integer constant out of range");
}
/* Warn about some cases where the type of a given constant
changes from traditional C to ANSI C. */
if (warn_traditional)
{
tree other_type = 0;
/* This computation is the same as the previous one
except that flag_traditional is used backwards. */
for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
i++)
if (!(spec_long && !type_sequence[i].long_flag)
&& !(spec_long_long && !type_sequence[i].long_long_flag)
&& !(spec_unsigned && !type_sequence[i].unsigned_flag)
/* A hex or octal constant traditionally is unsigned. */
&& !(base != 10 && !flag_traditional
&& !type_sequence[i].unsigned_flag)
/* A decimal constant can't be unsigned int
unless explicitly specified. */
&& !(base == 10 && !spec_unsigned
&& *type_sequence[i].node_var == unsigned_type_node))
if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
{
other_type = *type_sequence[i].node_var;
break;
}
if (!flag_traditional && type == long_unsigned_type_node
&& !spec_unsigned)
type = long_integer_type_node;
if (other_type != 0 && other_type != type)
{
if (flag_traditional)
warning ("type of integer constant would be different without -traditional");
else
warning ("type of integer constant would be different with -traditional");
}
}
#else /* 1 */
if (!spec_long && !spec_unsigned
&& !(flag_traditional && base != 10)
&& int_fits_type_p (yylval.ttype, integer_type_node))
{
#if 0
if (warn_traditional && base != 10)
warning ("small nondecimal constant becomes signed in ANSI C++");
#endif
type = integer_type_node;
}
else if (!spec_long && (base != 10 || spec_unsigned)
@ -3622,10 +3531,6 @@ real_yylex ()
&& int_fits_type_p (yylval.ttype,
long_unsigned_type_node))
{
#if 0
if (warn_traditional && !spec_unsigned)
warning ("large integer constant becomes unsigned in ANSI C++");
#endif
if (flag_traditional && !spec_unsigned)
type = long_integer_type_node;
else
@ -3642,11 +3547,6 @@ real_yylex ()
else if (int_fits_type_p (yylval.ttype,
long_long_unsigned_type_node))
{
#if 0
if (warn_traditional && !spec_unsigned)
warning ("large nondecimal constant is unsigned in ANSI C++");
#endif
if (flag_traditional && !spec_unsigned)
type = long_long_integer_type_node;
else
@ -3661,7 +3561,6 @@ real_yylex ()
if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
warning ("decimal integer constant is so large that it is unsigned");
}
#endif
TREE_TYPE (yylval.ttype) = type;
*p = 0;

View File

@ -1751,9 +1751,11 @@ emit_thunk (thunk_fndecl)
abort ();
current_function_decl = thunk_fndecl;
#ifdef ASM_OUTPUT_MI_THUNK
temporary_allocation ();
assemble_start_function (thunk_fndecl, fnname);
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname);
permanent_allocation (1);
#else
save_ofp = flag_omit_frame_pointer;
flag_omit_frame_pointer = 1;
@ -1995,8 +1997,12 @@ do_build_copy_constructor (fndecl)
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
current_base_init_list = tree_cons (basetype,
p, current_base_init_list);
if (p == error_mark_node)
cp_error ("in default copy constructor");
else
current_base_init_list = tree_cons (basetype,
p, current_base_init_list);
}
for (i = 0; i < n_bases; ++i)
@ -2009,9 +2015,15 @@ do_build_copy_constructor (fndecl)
p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
current_base_init_list = tree_cons (basetype,
p, current_base_init_list);
if (p == error_mark_node)
cp_error ("in default copy constructor");
else
{
p = convert_from_reference (p);
current_base_init_list = tree_cons (basetype,
p, current_base_init_list);
}
}
for (; fields; fields = TREE_CHAIN (fields))
{
@ -2080,16 +2092,13 @@ do_build_assign_ref (fndecl)
for (i = 0; i < n_bases; ++i)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (TYPE_HAS_ASSIGN_REF (basetype))
{
tree p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
build_tree_list (NULL_TREE, p));
expand_expr_stmt (p);
}
tree p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
build_tree_list (NULL_TREE, p));
expand_expr_stmt (p);
}
for (; fields; fields = TREE_CHAIN (fields))
{
@ -2098,6 +2107,24 @@ do_build_assign_ref (fndecl)
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (TREE_READONLY (field))
{
if (DECL_NAME (field))
cp_error ("non-static const member `%#D', can't use default assignment operator", field);
else
cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type);
continue;
}
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
{
if (DECL_NAME (field))
cp_error ("non-static reference member `%#D', can't use default assignment operator", field);
else
cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type);
continue;
}
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))

View File

@ -1187,6 +1187,7 @@ instantiate_class_template (type)
/* XXX handle attributes */
type = finish_struct_1 (type, NULL_TREE, 0);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
else
{
@ -2968,8 +2969,6 @@ instantiate_decl (d)
if (! push_tinst_level (d))
return d;
if (TREE_CODE (d) == FUNCTION_DECL && nested)
push_cp_function_context (NULL_TREE);
push_to_top_level ();
/* Trick tsubst into giving us a new decl in case the template changed. */
@ -3044,8 +3043,6 @@ instantiate_decl (d)
}
pop_from_top_level ();
if (TREE_CODE (d) == FUNCTION_DECL && nested)
pop_cp_function_context (NULL_TREE);
pop_tinst_level ();
return d;

View File

@ -3508,7 +3508,7 @@ add_conversions (binfo)
tree tmp = TREE_VEC_ELT (method_vec, i);
if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
break;
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
conversions = tree_cons (TREE_TYPE (TREE_TYPE (tmp)), tmp,
conversions);
}
}

View File

@ -220,7 +220,7 @@ build_cplus_new (type, init)
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1;
rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE);
rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1;
@ -399,7 +399,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
}
tree
build_cplus_array_type (elt_type, index_type)
build_cplus_array_type_1 (elt_type, index_type)
tree elt_type;
tree index_type;
{
@ -433,6 +433,24 @@ build_cplus_array_type (elt_type, index_type)
saveable_obstack = ambient_saveable_obstack;
return t;
}
tree
build_cplus_array_type (elt_type, index_type)
tree elt_type;
tree index_type;
{
tree t;
int constp = TYPE_READONLY (elt_type);
int volatilep = TYPE_VOLATILE (elt_type);
elt_type = TYPE_MAIN_VARIANT (elt_type);
t = build_cplus_array_type_1 (elt_type, index_type);
if (constp || volatilep)
t = cp_build_type_variant (t, constp, volatilep);
return t;
}
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
@ -451,9 +469,9 @@ cp_build_type_variant (type, constp, volatilep)
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
constp, volatilep),
TYPE_DOMAIN (type));
type = build_cplus_array_type_1 (cp_build_type_variant
(TREE_TYPE (type), constp, volatilep),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
@ -467,6 +485,7 @@ cp_build_type_variant (type, constp, volatilep)
TYPE_MAIN_VARIANT (type) = real_main_variant;
pop_obstacks ();
return type;
}
return build_type_variant (type, constp, volatilep);
}
@ -1753,16 +1772,6 @@ break_out_target_exprs (t)
return mapcar (t, bot_manip);
}
/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
by itself. */
int
cp_expand_decl_cleanup (decl, cleanup)
tree decl, cleanup;
{
return expand_decl_cleanup (decl, unsave_expr (cleanup));
}
/* Obstack used for allocating nodes in template function and variable
definitions. */

View File

@ -129,7 +129,7 @@ complete_type (type)
{
if (TYPE_SIZE (type) != NULL_TREE)
;
else if (TREE_CODE (type) == ARRAY_TYPE)
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
tree t = complete_type (TREE_TYPE (type));
if (TYPE_SIZE (t) != NULL_TREE)
@ -437,10 +437,6 @@ common_type (t1, t2)
case ARRAY_TYPE:
{
int constp
= TYPE_READONLY (t1) || TYPE_READONLY (t2);
int volatilep
= TYPE_VOLATILE (t1) || TYPE_VOLATILE (t2);
tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
@ -448,9 +444,8 @@ common_type (t1, t2)
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
t1 = build_cplus_array_type (TYPE_MAIN_VARIANT (elt), TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
if (constp || volatilep)
t1 = cp_build_type_variant (t1, constp, volatilep);
t1 = build_cplus_array_type
(elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
return build_type_attribute_variant (t1, attributes);
}