Commit 6060a796 by Mike Stump

50th Cygnus<->FSF merge

From-SVN: r8657
parent 27efbf21
......@@ -75,7 +75,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \
$(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
# Build hooks:
......
......@@ -162,8 +162,8 @@ CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
edsel.o except.o init.o method.o search.o tree.o xref.o
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o
OBJDEPS = ../stamp-objlist ../c-common.o
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus
../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
......
......@@ -1802,7 +1802,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
we can manage. */
tree temp = get_temp_name (TREE_TYPE (instance), 0);
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
expand_aggr_init (temp, instance, 0);
expand_aggr_init (temp, instance, 0, flags);
else
{
store_init_value (temp, instance);
......@@ -2144,7 +2144,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
tree type = build_pointer_type
(build_type_variant (basetype, constp, volatilep));
TREE_VALUE (parms) = convert_force (type, instance_ptr);
TREE_VALUE (parms) = convert_force (type, instance_ptr, 0);
}
}
......@@ -2652,8 +2652,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_TYPE (result) = value_type;
TREE_SIDE_EFFECTS (result) = 1;
TREE_RAISES (result)
= TYPE_RAISES_EXCEPTIONS (fntype) || (parms && TREE_RAISES (parms));
TREE_HAS_CONSTRUCTOR (result) = is_constructor;
return result;
}
......
......@@ -2116,7 +2116,7 @@ finish_vtbls (binfo, do_self, t)
&& DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
BINFO_VIRTUALS (binfo));
finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
DECL_CONTEXT (decl) = context;
}
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
......@@ -3161,10 +3161,26 @@ finish_struct (t, list_of_fieldlists, warn_anon)
DECL_INITIAL (x) = NULL;
cp_error_at ("zero width for bit-field `%D'", x);
}
else if ((unsigned)width > TYPE_PRECISION (TREE_TYPE (x)))
else if (width
> TYPE_PRECISION (long_long_unsigned_type_node))
{
/* The backend will dump if you try to use something
too big; avoid that. */
DECL_INITIAL (x) = NULL;
cp_error_at ("width of `%D' exceeds its type", x);
sorry ("bit-fields larger than %d bits",
TYPE_PRECISION (long_long_unsigned_type_node));
cp_error_at (" in declaration of `%D'", x);
}
else if (width > TYPE_PRECISION (TREE_TYPE (x))
&& TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
{
cp_warning_at ("width of `%D' exceeds its type", x);
}
else if (width < TYPE_PRECISION (TREE_TYPE (x))
&& TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE)
{
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
x, TREE_TYPE (x));
}
}
......
......@@ -1787,6 +1787,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
as well as the space of member functions.
LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
in the parameter list.
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
LOOKUP_NO_CONVERSION means that user-defined conversions are not
permitted. Built-in conversions are permitted.
LOOKUP_DESTRUCTOR means explicit call to destructor. */
......@@ -1809,13 +1810,15 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
CONV_STATIC : Perform the explicit conversions for static_cast.
CONV_CONST : Perform the explicit conversions for const_cast.
CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast.
CONV_PRIVATE : Perform upcasts to private bases. */
CONV_PRIVATE : Perform upcasts to private bases.
CONV_NONCONVERTING : Allow non-converting constructors to be used. */
#define CONV_IMPLICIT 1
#define CONV_STATIC 2
#define CONV_CONST 4
#define CONV_REINTERPRET 8
#define CONV_PRIVATE 16
#define CONV_NONCONVERTING 32
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC)
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET)
......@@ -1896,7 +1899,8 @@ extern tree convert_pointer_to PROTO((tree, tree));
extern tree convert_pointer_to_real PROTO((tree, tree));
extern tree convert_pointer_to_vbase PROTO((tree, tree));
extern tree convert PROTO((tree, tree));
extern tree convert_force PROTO((tree, tree));
extern tree cp_convert PROTO((tree, tree, int, int));
extern tree convert_force PROTO((tree, tree, int));
extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
......@@ -1956,7 +1960,7 @@ extern void shadow_tag PROTO((tree));
extern int grok_ctor_properties PROTO((tree, tree));
extern tree groktypename PROTO((tree));
extern tree start_decl PROTO((tree, tree, int, tree));
extern void finish_decl PROTO((tree, tree, tree, int));
extern void finish_decl PROTO((tree, tree, tree, int, int));
extern void expand_static_init PROTO((tree, tree));
extern int complete_array_type PROTO((tree, tree, int));
extern tree build_ptrmemfunc_type PROTO((tree));
......@@ -2018,6 +2022,9 @@ extern tree reparse_decl_as_expr PROTO((tree, tree));
extern tree finish_decl_parsing PROTO((tree));
extern tree lookup_name_nonclass PROTO((tree));
extern tree check_cp_case_value PROTO((tree));
extern tree do_using_decl PROTO((tree));
extern tree current_namespace_id PROTO((tree));
extern tree get_namespace_id PROTO((void));
/* in edsel.c */
......@@ -2066,7 +2073,7 @@ extern void check_base_init PROTO((tree));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int));
extern void expand_aggr_init PROTO((tree, tree, int, int));
extern int is_aggr_typedef PROTO((tree, int));
extern tree get_aggr_from_typedef PROTO((tree, int));
extern tree get_type_value PROTO((tree));
......@@ -2347,7 +2354,7 @@ extern tree build_compound_expr PROTO((tree));
extern tree build_static_cast PROTO((tree, tree));
extern tree build_reinterpret_cast PROTO((tree, tree));
extern tree build_const_cast PROTO((tree, tree));
extern tree build_c_cast PROTO((tree, tree));
extern tree build_c_cast PROTO((tree, tree, int));
extern tree build_modify_expr PROTO((tree, enum tree_code, tree));
extern int language_lvalue_valid PROTO((tree));
extern void warn_for_assignment PROTO((char *, char *, char *, tree, int, int));
......
......@@ -309,6 +309,10 @@ build_up_reference (type, arg, flags, checkconst)
targ = arg;
if (TREE_CODE (targ) == SAVE_EXPR)
targ = TREE_OPERAND (targ, 0);
while (TREE_CODE (targ) == NOP_EXPR
&& (TYPE_MAIN_VARIANT (argtype)
== TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (targ, 0)))))
targ = TREE_OPERAND (targ, 0);
switch (TREE_CODE (targ))
{
......@@ -552,13 +556,16 @@ build_up_reference (type, arg, flags, checkconst)
}
else
{
/* We should never get here for class objects, because they are
always in memory. */
my_friendly_assert (! IS_AGGR_TYPE (argtype), 362);
temp = get_temp_name (argtype, 0);
if (global_bindings_p ())
{
/* Give this new temp some rtl and initialize it. */
DECL_INITIAL (temp) = targ;
TREE_STATIC (temp) = 1;
finish_decl (temp, targ, NULL_TREE, 0);
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;
......@@ -605,8 +612,6 @@ build_up_reference (type, arg, flags, checkconst)
initialized. It can be error_mark_node if we don't know the _DECL but
we know it's an initialization. */
tree cp_convert PROTO((tree, tree, int, int));
tree
convert_to_reference (reftype, expr, convtype, flags, decl)
tree reftype, expr;
......@@ -703,7 +708,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0);
if (rval != error_mark_node)
rval = build1 (NOP_EXPR, reftype, rval);
}
......@@ -1061,7 +1066,6 @@ convert_to_aggr (type, expr, msgp, protect)
NULL_TREE);
TREE_TYPE (result) = TREE_TYPE (fntype);
TREE_SIDE_EFFECTS (result) = 1;
TREE_RAISES (result) = !! TYPE_RAISES_EXCEPTIONS (fntype);
return result;
}
......@@ -1184,10 +1188,8 @@ cp_convert (type, expr, convtype, flags)
register tree e = expr;
register enum tree_code code = TREE_CODE (type);
if (type == TREE_TYPE (e)
|| TREE_CODE (e) == ERROR_MARK)
return e;
if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
if (TREE_CODE (e) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
return error_mark_node;
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
......@@ -1229,7 +1231,8 @@ cp_convert (type, expr, convtype, flags)
/* enum = enum, enum = int, enum = float are all errors. */
if (flag_int_enum_equivalence == 0
&& TREE_CODE (type) == ENUMERAL_TYPE
&& ARITHMETIC_TYPE_P (intype))
&& ARITHMETIC_TYPE_P (intype)
&& ! (convtype & CONV_STATIC))
{
cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type);
......@@ -1309,7 +1312,7 @@ cp_convert (type, expr, convtype, flags)
sig_ptr = get_temp_name (type, 1);
DECL_INITIAL (sig_ptr) = constructor;
CLEAR_SIGNATURE (sig_ty);
finish_decl (sig_ptr, constructor, 0, 0);
finish_decl (sig_ptr, constructor, NULL_TREE, 0, 0);
SET_SIGNATURE (sig_ty);
TREE_READONLY (sig_ptr) = 1;
......@@ -1338,7 +1341,7 @@ cp_convert (type, expr, convtype, flags)
build_tree_list (NULL_TREE, e),
TYPE_BINFO (type),
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY
| LOOKUP_ONLYCONVERTING
| (convtype&CONV_NONCONVERTING ? 0 : LOOKUP_ONLYCONVERTING)
| (conversion ? LOOKUP_NO_CONVERSION : 0));
if (ctor == error_mark_node)
......@@ -1428,9 +1431,10 @@ convert (type, expr)
are not normally allowed due to access restrictions
(such as conversion from sub-type to private super-type). */
tree
convert_force (type, expr)
convert_force (type, expr, convtype)
tree type;
tree expr;
int convtype;
{
register tree e = expr;
register enum tree_code code = TREE_CODE (type);
......@@ -1455,13 +1459,8 @@ convert_force (type, expr)
/* compatible pointer to member functions. */
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
}
{
int old_equiv = flag_int_enum_equivalence;
flag_int_enum_equivalence = 1;
e = convert (type, e);
flag_int_enum_equivalence = old_equiv;
}
return e;
return cp_convert (type, e, CONV_OLD_CONVERT|convtype, 0);
}
/* Subroutine of build_type_conversion. */
......
......@@ -1147,6 +1147,10 @@ check_classfn (ctype, cname, function)
{
if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
return;
/* We have to do more extensive argument checking here, as
the name may have been changed by asm("new_name"). */
if (decls_match (function, fndecl))
return;
fndecl = DECL_CHAIN (fndecl);
}
break; /* loser */
......@@ -1195,6 +1199,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
{
register tree value;
char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
/* Convert () initializers to = initializers. */
if (init == NULL_TREE && declarator != NULL_TREE
......@@ -1206,6 +1211,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
{
init = TREE_OPERAND (declarator, 1);
declarator = TREE_OPERAND (declarator, 0);
flags = 0;
}
if (init
......@@ -1353,17 +1359,22 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
finish_decl (value, init, asmspec_tree, 1);
finish_decl (value, init, asmspec_tree, 1, flags);
pushdecl_class_level (value);
return value;
}
if (TREE_CODE (value) == FIELD_DECL)
{
if (asmspec)
DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
{
/* This must override the asm specifier which was placed
by grokclassfn. Lay this out fresh. */
DECL_RTL (value) = NULL_RTX;
DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
}
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
finish_decl (value, init, asmspec_tree, 1);
finish_decl (value, init, asmspec_tree, 1, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
......@@ -1378,7 +1389,14 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
/* When does this happen? */
my_friendly_assert (init == NULL_TREE, 193);
}
finish_decl (value, init, asmspec_tree, 1);
if (asmspec)
{
/* This must override the asm specifier which was placed
by grokclassfn. Lay this out fresh. */
DECL_RTL (value) = NULL_RTX;
DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
}
finish_decl (value, init, asmspec_tree, 1, flags);
/* Pass friends back this way. */
if (DECL_FRIEND_P (value))
......@@ -1439,7 +1457,7 @@ grokbitfield (declarator, declspecs, width)
cp_error ("static member `%D' cannot be a bitfield", value);
return NULL_TREE;
}
finish_decl (value, NULL_TREE, NULL_TREE, 0);
finish_decl (value, NULL_TREE, NULL_TREE, 0, 0);
if (width != error_mark_node)
{
......@@ -1631,7 +1649,7 @@ groktypefield (declspecs, parmlist)
return void_type_node;
}
finish_decl (decl, NULL_TREE, NULL_TREE, 0);
finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0);
/* If this declaration is common to another declaration
complain about such redundancy, and return NULL_TREE
......@@ -1934,7 +1952,7 @@ setup_vtbl_ptr ()
DECL_INITIAL (current_vtable_decl) = error_mark_node;
/* Have to cast the initializer, since it may have come from a
more base class then we ascribe CURRENT_VTABLE_DECL to be. */
finish_decl (current_vtable_decl, convert_force (TREE_TYPE (current_vtable_decl), vfield), 0, 0);
finish_decl (current_vtable_decl, convert_force (TREE_TYPE (current_vtable_decl), vfield, 0), NULL_TREE, 0, 0);
current_vtable_decl = build_indirect_ref (current_vtable_decl, NULL_PTR);
}
else
......@@ -1947,8 +1965,10 @@ void
mark_inline_for_output (decl)
tree decl;
{
decl = DECL_MAIN_VARIANT (decl);
if (DECL_SAVED_INLINE (decl))
return;
my_friendly_assert (TREE_PERMANENT (decl), 363);
DECL_SAVED_INLINE (decl) = 1;
if (DECL_PENDING_INLINE_INFO (decl) != 0
&& ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
......@@ -2176,7 +2196,7 @@ finish_table (name, type, init, publicp)
DECL_INITIAL (empty_table) = init;
asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
IDENTIFIER_POINTER (DECL_NAME (empty_table)));
finish_decl (empty_table, init, asmspec, 0);
finish_decl (empty_table, init, asmspec, 0, 0);
}
is_empty = 1;
}
......@@ -2214,7 +2234,7 @@ finish_table (name, type, init, publicp)
IDENTIFIER_POINTER (DECL_NAME (empty_table)));
}
finish_decl (decl, init, asmspec, 0);
finish_decl (decl, init, asmspec, 0, 0);
return decl;
}
......@@ -2782,7 +2802,7 @@ finish_file ()
}
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0);
expand_aggr_init (decl, init, 0, 0);
else if (TREE_CODE (init) == TREE_VEC)
{
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
......@@ -2803,7 +2823,7 @@ finish_file ()
/* a `new' expression at top level. */
expand_expr (decl, const0_rtx, VOIDmode, 0);
free_temp_slots ();
expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0);
expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
}
}
else if (decl == error_mark_node)
......@@ -3041,7 +3061,7 @@ reparse_absdcl_as_casts (decl, expr)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
expr = build_c_cast (type, expr);
expr = build_c_cast (type, expr, 0);
}
return expr;
......@@ -3166,3 +3186,77 @@ check_cp_case_value (value)
return value;
}
static tree current_namespace;
/* Get the inner part of a namespace id. It doesn't have any prefix, nor
postfix. Returns 0 if in global namespace. */
tree
get_namespace_id ()
{
tree x = current_namespace;
if (x)
x = TREE_PURPOSE (x);
return x;
}
/* Build up a DECL_ASSEMBLER_NAME for NAME in the current namespace. */
tree
current_namespace_id (name)
tree name;
{
tree old_id = get_namespace_id ();
char *buf;
/* Global names retain old encoding. */
if (! old_id)
return name;
buf = (char *) alloca (8 + IDENTIFIER_LENGTH (old_id)
+ IDENTIFIER_LENGTH (name));
sprintf (buf, "__ns_%s_%s", IDENTIFIER_POINTER (old_id),
IDENTIFIER_POINTER (name));
return get_identifier (buf);
}
/* Push into the scopre of the NAME namespace. */
void
push_namespace (name)
tree name;
{
tree old_id = get_namespace_id ();
char *buf;
current_namespace = tree_cons (NULL_TREE, name, current_namespace);
buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0)
+ IDENTIFIER_LENGTH (name));
sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "",
IDENTIFIER_POINTER (name));
TREE_PURPOSE (current_namespace) = get_identifier (buf);
}
/* Pop from the scope of the current namespace. */
void
pop_namespace ()
{
current_namespace = TREE_CHAIN (current_namespace);
}
void
do_namespace_alias (alias, namespace)
tree alias, namespace;
{
}
tree
do_using_decl (decl)
tree decl;
{
return error_mark_node;
}
void
do_using_directive (namespace)
tree namespace;
{
}
......@@ -1017,8 +1017,7 @@ dump_expr (t, nop)
}
else
{
sorry ("operand of SAVE_EXPR not understood");
goto error;
dump_expr (TREE_OPERAND (t, 0), 0);
}
break;
......
......@@ -43,7 +43,7 @@ tree builtin_return_address_fndecl;
#define TRY_NEW_EH
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa)
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
#define TRY_NEW_EH
#endif
#endif
......@@ -803,6 +803,16 @@ init_exception_processing ()
saved_throw_type = gen_rtx (REG, Pmode, 6);
saved_throw_value = gen_rtx (REG, Pmode, 7);
#endif
#ifdef __mc68000
saved_pc = gen_rtx (REG, Pmode, 10);
saved_throw_type = gen_rtx (REG, Pmode, 11);
saved_throw_value = gen_rtx (REG, Pmode, 12);
#endif
#ifdef __mips
saved_pc = gen_rtx (REG, Pmode, 16);
saved_throw_type = gen_rtx (REG, Pmode, 17);
saved_throw_value = gen_rtx (REG, Pmode, 18);
#endif
new_eh_queue (&ehqueue);
new_eh_queue (&eh_table_output_queue);
new_eh_stack (&ehstack);
......@@ -977,6 +987,13 @@ expand_end_all_catch ()
if (! doing_eh (1))
return;
/* Code to throw out to outer context, if we fall off end of catch
handlers. */
emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
Pmode,
top_label_entry (&caught_return_label_stack)));
emit_jump (throw_label);
/* Find the start of the catch block. */
last = pop_last_insn ();
catchstart = NEXT_INSN (last);
......@@ -1136,7 +1153,7 @@ expand_start_catch_block (declspecs, declarator)
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_bne (false_label_rtx));
finish_decl (decl, init, NULL_TREE, 0);
finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
else
{
......@@ -1165,7 +1182,7 @@ void expand_end_catch_block ()
/* label we jump to if we caught the exception */
emit_jump (top_label_entry (&caught_return_label_stack));
/* Code to throw out to outer context, if we get an throw from within
/* Code to throw out to outer context, if we get a throw from within
our catch handler. */
/* These are saved for the exception table. */
push_rtl_perm ();
......@@ -1240,7 +1257,7 @@ do_unwind (throw_label)
easy_expand_asm ("restore");
emit_barrier ();
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa)
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
extern FILE *asm_out_file;
tree fcall;
tree params;
......@@ -1443,9 +1460,13 @@ expand_throw (exp)
emit_move_insn (saved_throw_type, throw_type_rtx);
exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node);
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), exp, 0);
if (exp == error_mark_node)
error (" in thrown expression");
throw_value_rtx = expand_expr (build_unary_op (ADDR_EXPR, exp, 0), NULL_RTX, VOIDmode, 0);
throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx);
}
}
......
......@@ -155,7 +155,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
TREE_ADDRESSABLE (init) = 1;
flag_access_control = 0;
expand_aggr_init (slot, init, 0);
expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type))
......@@ -195,7 +195,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = build (RTL_EXPR, return_type, 0, call_target);
/* We got back a reference to the type we want. Now initialize
target with that. */
expand_aggr_init (slot, init, 0);
expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
}
if (DECL_RTL (slot) != target)
......
......@@ -1189,24 +1189,21 @@ the object was thrown. This is so that there is always someplace for
the exception object, and nothing can overwrite it, once we start
throwing. The only bad part, is that the stack remains large.
Flaws in g++'s exception handling. The stack pointer is restored from
stack, we want to match rs6000, and propagate the stack pointer from
time of throw, down, to the catch place.
Only exact type matching of throw types works (references work also),
catch variables cannot be used. Only works on a Sun sparc running SunOS
4.1.x. Unwinding to outer catch clauses works. All temps and local
variables are cleaned up in all unwinded scopes. Completed parts of
partially constructed objects are not cleaned up. Don't expect
exception handling to work right if you optimize, in fact the compiler
will probably core dump. If two EH regions are the exact same size, the
backend cannot tell which one is first. It punts by picking the last
one, if they tie. This is usually right. We really should stick in a
nop, if they are the same size.
If we fall off the end of a series of catch blocks, we return to the
flow of control in a normal fasion. But this is wrong, we should
rethrow.
The below points out some flaws in g++'s exception handling, as it now
stands.
Only exact type matching or reference matching of throw types works.
Only works on a SPARC machines (like Suns), and i386 machines. Partial
support is also in for rs6000, hppa, m68k and mips machines, but a stack
unwinder called __unwind_function has to be written, and added to
libgcc2 for them. All completely constructed temps and local variables
are cleaned up in all unwinded scopes. Completed parts of partially
constructed objects are not cleaned up. Don't expect exception handling
to work right if you optimize, in fact the compiler will probably core
dump. If two EH regions are the exact same size, the backend cannot
tell which one is first. It punts by picking the last one, if they tie.
This is usually right. We really should stick in a nop, if they are the
same size.
When we invoke the copy constructor for an exception object because it
is passed by value, and if we take a hit (exception) inside the copy
......@@ -1216,16 +1213,24 @@ exists, but rather to allow the frame to unwind into the next series of
handlers, if any. If this is the wrong way to do it, we will need to
protect the rest of the handler in some fashion. Maybe just changing
the handler's handler to protect the whole series of handlers is the
right way to go.
The EH object is copied like it should be, if it is passed by value,
otherwise we get a reference directly to it.
EH objects make it through unwinding, but are subject to being
overwritten as they are still past the top of stack. Don't throw
automatic objects if this is a problem.
Exceptions in catch handlers now go to outer block.
right way to go. This part is wrong. We should call terminate if an
exception is thrown while doing things like trying to copy the exception
object.
Exception specifications are handled syntax wise, but not semantic wise.
build_exception_variant should sort the incoming list, so that is
implements set compares, not exact list equality. Type smashing should
smash exception specifications using set union.
Thrown objects are allocated on the heap, in the usual way, but they are
never deleted. They should be deleted by the catch clauses.
In stmt.c, expand_end_bindings attempts to eliminate the generation of
destructors for a binding contour if the code would be unreachable (last
insn == BARRIER). In this case, interim_eh_hook is never called for the
end of the lifetimes of auto variables, so the compiler generates
invalid assembler (the end label for the scope is never declared, and
destructor code isn't generated on the exception path).
@node Free Store, Concept Index, Exception Handling, Top
@section Free Store
......
......@@ -185,7 +185,7 @@ perform_member_init (member, name, init, explicit)
array_type_nelts (type), TREE_VALUE (init), 1);
}
else
expand_aggr_init (decl, init, 0);
expand_aggr_init (decl, init, 0, 0);
}
else
{
......@@ -734,7 +734,7 @@ expand_virtual_init (binfo, decl)
return;
/* Have to convert VTBL since array sizes may be different. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl);
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}
......@@ -1071,7 +1071,7 @@ expand_member_init (exp, name, init)
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
parm = build_component_ref (exp, name, 0, 0);
expand_aggr_init (parm, NULL_TREE, 0);
expand_aggr_init (parm, NULL_TREE, 0, 0);
rval = error_mark_node;
}
......@@ -1087,6 +1087,8 @@ expand_member_init (exp, name, init)
INIT comes in two flavors: it is either a value which
is to be stored in EXP, or it is a parameter list
to go to a constructor, which will operate on EXP.
If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of
the initializer, if FLAGS is 0, then it is the (init) form.
If `init' is a CONSTRUCTOR, then we emit a warning message,
explaining that such initializations are illegal.
......@@ -1116,9 +1118,10 @@ expand_member_init (exp, name, init)
*/
void
expand_aggr_init (exp, init, alias_this)
expand_aggr_init (exp, init, alias_this, flags)
tree exp, init;
int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
int was_const = TREE_READONLY (exp);
......@@ -1179,7 +1182,7 @@ expand_aggr_init (exp, init, alias_this)
init = CONSTRUCTOR_ELTS (init);
#endif
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
init, alias_this, LOOKUP_NORMAL);
init, alias_this, LOOKUP_NORMAL|flags);
TREE_READONLY (exp) = was_const;
}
......@@ -1353,9 +1356,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
init = build (CALL_EXPR, init_type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
TREE_SIDE_EFFECTS (init) = 1;
#if 0
TREE_RAISES (init) = ??
#endif
if (init_list)
TREE_VALUE (init_list) = init;
}
......@@ -1425,9 +1425,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
TREE_SIDE_EFFECTS (init) = 1;
#if 0
TREE_RAISES (init) = ??
#endif
TREE_VALUE (TREE_OPERAND (init, 1))
= convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
......@@ -1561,7 +1558,7 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR);
tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);
if (IS_AGGR_TYPE (TREE_TYPE (member)))
expand_aggr_init (member_base, DECL_INITIAL (member), 0);
expand_aggr_init (member_base, DECL_INITIAL (member), 0, 0);
else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE
&& TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))
{
......@@ -1803,7 +1800,7 @@ build_member_call (cname, name, parmlist)
{
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl);
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
}
else
decl = olddecl;
......@@ -3114,7 +3111,7 @@ build_new (placement, decl, init, use_global_new)
/* New 2.0 interpretation: `new int (10)' means
allocate an int, and initialize it with 10. */
init = build_c_cast (type, init);
init = build_c_cast (type, init, 1);
rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
build_modify_expr (build_indirect_ref (rval, NULL_PTR),
NOP_EXPR, init),
......@@ -3151,7 +3148,7 @@ build_new (placement, decl, init, use_global_new)
build_binary_op (MINUS_EXPR, nelts, integer_one_node, 1),
init, 0);
else
expand_aggr_init (build_indirect_ref (rval, NULL_PTR), init, 0);
expand_aggr_init (build_indirect_ref (rval, NULL_PTR), init, 0, 0);
do_pending_stack_adjust ();
......@@ -3179,7 +3176,7 @@ build_new (placement, decl, init, use_global_new)
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
{
/* The type of new int [3][3] is not int *, but int [3] * */
rval = build_c_cast (build_pointer_type (type), rval);
rval = build_c_cast (build_pointer_type (type), rval, 0);
}
if (pending_sizes)
......@@ -3273,7 +3270,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
while (elts)
{
host_i -= 1;
expand_aggr_init (baseref, TREE_VALUE (elts), 0);
expand_aggr_init (baseref, TREE_VALUE (elts), 0, 0);
expand_assignment (base, baseinc, 0, 0);
elts = TREE_CHAIN (elts);
......@@ -3357,7 +3354,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
if (from_array == 2)
expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
else if (TYPE_NEEDS_CONSTRUCTING (type))
expand_aggr_init (to, from, 0);
expand_aggr_init (to, from, 0, 0);
else if (from)
expand_assignment (to, from, 0, 0);
else
......@@ -3371,7 +3368,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
array_type_nelts (type), 0, 0);
}
else
expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
expand_assignment (base,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size),
......@@ -3488,7 +3485,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
addr = save_expr (addr);
/* throw away const and volatile on target type of addr */
addr = convert_force (build_pointer_type (type), addr);
addr = convert_force (build_pointer_type (type), addr, 0);
ref = build_indirect_ref (addr, NULL_PTR);
ptr = 1;
}
......@@ -3514,7 +3511,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CONSTANT (addr))
addr = convert_pointer_to (type, addr);
else
addr = convert_force (build_pointer_type (type), addr);
addr = convert_force (build_pointer_type (type), addr, 0);
if (TREE_CODE (addr) == NOP_EXPR
&& TREE_OPERAND (addr, 0) == current_class_decl)
......@@ -3803,7 +3800,7 @@ build_vbase_delete (type, decl)
while (vbases)
{
tree this_addr = convert_force (TYPE_POINTER_TO (BINFO_TYPE (vbases)),
addr);
addr, 0);
result = tree_cons (NULL_TREE,
build_delete (TREE_TYPE (this_addr), this_addr,
integer_zero_node,
......
......@@ -2587,6 +2587,15 @@ check_newline ()
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
}
}
#ifdef HANDLE_SYSV_PRAGMA
else
return handle_sysv_pragma (finput, c);
#else
#ifdef HANDLE_PRAGMA
else
HANDLE_PRAGMA (finput);
#endif
#endif
}
goto skipline;
}
......@@ -4874,3 +4883,46 @@ yyerror (string)
error (buf, token_buffer);
}
#ifdef HANDLE_SYSV_PRAGMA
/* Handle a #pragma directive. INPUT is the current input stream,
and C is a character to reread. Processes the entire input line
and returns a character for the caller to reread: either \n or EOF. */
/* This function has to be in this file, in order to get at
the token types. */
int
handle_sysv_pragma (input, c)
FILE *input;
int c;
{
for (;;)
{
while (c == ' ' || c == '\t')
c = getc (input);
if (c == '\n' || c == EOF)
{
handle_pragma_token (0, 0);
return c;
}
ungetc (c, input);
switch (yylex ())
{
case IDENTIFIER:
case TYPENAME:
case STRING:
case CONSTANT:
handle_pragma_token (token_buffer, yylval.ttype);
break;
default:
handle_pragma_token (token_buffer, 0);
}
if (nextchar >= 0)
c = nextchar, nextchar = -1;
else
c = getc (input);
}
}
#endif /* HANDLE_SYSV_PRAGMA */
......@@ -2303,8 +2303,9 @@ do_pending_expansions ()
else if (! flag_implicit_templates)
DECIDE (0);
/* OK, it was an implicit instantiation. */
TREE_PUBLIC (t) = 0;
if (i->interface == 1)
/* OK, it was an implicit instantiation. */
TREE_PUBLIC (t) = 0;
/* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file?
......
......@@ -1503,24 +1503,13 @@ build_exception_variant (ctype, type, raises)
|| TYPE_VOLATILE (v) != volatilep)
continue;
t = raises;
t2 = TYPE_RAISES_EXCEPTIONS (v);
while (t && t2)
{
if (TREE_TYPE (t) == TREE_TYPE (t2))
{
t = TREE_CHAIN (t);
t2 = TREE_CHAIN (t2);
}
else break;
}
if (t || t2)
continue;
/* List of exceptions raised matches previously found list.
/* @@ This should do set equality, not exact match. */
if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
/* List of exceptions raised matches previously found list.
@@ Nice to free up storage used in consing up the
@@ list of exceptions raised. */
return v;
@@ Nice to free up storage used in consing up the
@@ list of exceptions raised. */
return v;
}
/* Need to build a new variant. */
......
......@@ -2162,7 +2162,7 @@ build_x_function_call (function, params, decl)
decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
}
else
decl = build_c_cast (ctypeptr, decl);
decl = build_c_cast (ctypeptr, decl, 0);
params = tree_cons (NULL_TREE, decl, params);
}
......@@ -2370,8 +2370,6 @@ build_function_call_real (function, params, require_complete, flags)
function, coerced_params, NULL_TREE);
TREE_SIDE_EFFECTS (result) = 1;
/* Remove this sometime. */
TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype);
if (! require_complete)
return result;
if (value_type == void_type_node)
......@@ -2427,7 +2425,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
register tree typetail, valtail;
register tree result = NULL_TREE;
char *called_thing;
int maybe_raises = 0;
int i = 0;
if (! flag_elide_constructors)
......@@ -2541,8 +2538,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (val == error_mark_node)
continue;
maybe_raises |= TREE_RAISES (val);
if (type != 0)
{
/* Formal parm type is specified by a function prototype. */
......@@ -2648,7 +2643,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
parmval = default_conversion (parmval);
#endif
}
maybe_raises |= TREE_RAISES (parmval);
if (flag_gc
&& type_needs_gc_entry (TREE_TYPE (parmval))
......@@ -2676,8 +2670,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
return error_mark_list;
}
}
if (result)
TREE_RAISES (result) = maybe_raises;
return nreverse (result);
}
......@@ -2733,14 +2725,13 @@ build_binary_op (code, arg1, arg2, convert_p)
type1 = TREE_TYPE (args[0]);
type2 = TREE_TYPE (args[1]);
if (IS_AGGR_TYPE_2 (type1, type2) && ! TYPE_PTRMEMFUNC_P (type1))
if (IS_AGGR_TYPE_2 (type1, type2))
{
/* Try to convert this to something reasonable. */
if (! build_default_binary_type_conversion(code, &args[0], &args[1]))
return error_mark_node;
}
else if ((IS_AGGR_TYPE (type1) && ! TYPE_PTRMEMFUNC_P (type1))
|| (IS_AGGR_TYPE (type2) && ! TYPE_PTRMEMFUNC_P (type2)))
else if (IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type2))
{
int convert_index = IS_AGGR_TYPE (type2);
/* Avoid being tripped up by things like (ARG1 != 0). */
......@@ -3735,7 +3726,7 @@ build_component_addr (arg, argtype, msg)
}
else
/* This conversion is harmless. */
rval = convert_force (argtype, rval);
rval = convert_force (argtype, rval, 0);
if (! integer_zerop (DECL_FIELD_BITPOS (field)))
{
......@@ -4871,27 +4862,31 @@ build_compound_expr (list)
tree build_static_cast (type, expr)
tree type, expr;
{
return build_c_cast (type, expr);
return build_c_cast (type, expr, 0);
}
tree build_reinterpret_cast (type, expr)
tree type, expr;
{
return build_c_cast (type, expr);
return build_c_cast (type, expr, 0);
}
tree build_const_cast (type, expr)
tree type, expr;
{
return build_c_cast (type, expr);
return build_c_cast (type, expr, 0);
}
/* Build an expression representing a cast to type TYPE of expression EXPR. */
/* Build an expression representing a cast to type TYPE of expression EXPR.
ALLOW_NONCONVERTING is true if we should allow non-converting constructors
when doing the cast. */
tree
build_c_cast (type, expr)
build_c_cast (type, expr, allow_nonconverting)
register tree type;
tree expr;
int allow_nonconverting;
{
register tree value = expr;
......@@ -5014,7 +5009,7 @@ build_c_cast (type, expr)
value = decl_constant_value (value);
ovalue = value;
value = convert_force (type, value);
value = convert_force (type, value, allow_nonconverting?CONV_NONCONVERTING:0);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
......@@ -5848,7 +5843,7 @@ build_modify_expr (lhs, modifycode, rhs)
{
newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
NULL_TREE, 0);
newrhs = convert_force (lhstype, newrhs);
newrhs = convert_force (lhstype, newrhs, 0);
}
else
newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
......@@ -6121,7 +6116,7 @@ build_ptrmemfunc (type, pfn, force)
/* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
pfn = build_c_cast (type, integer_zero_node);
pfn = build_c_cast (type, integer_zero_node, 0);
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
tree_cons (NULL_TREE, integer_zero_node,
......@@ -6299,11 +6294,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
/* Conversions involving enums. */
else if ((codel == ENUMERAL_TYPE
&& (coder == ENUMERAL_TYPE || coder == INTEGER_TYPE || coder == REAL_TYPE))
&& (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE))
|| (coder == ENUMERAL_TYPE
&& (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE || codel == REAL_TYPE)))
&& (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE)))
{
return convert (type, rhs);
return cp_convert (type, rhs, CONV_IMPLICIT, 0);
}
/* Conversions among pointers */
else if (codel == POINTER_TYPE
......@@ -7065,7 +7060,7 @@ c_expand_return (retval)
if (TREE_CODE (retval) == WITH_CLEANUP_EXPR
&& TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
retval = TREE_OPERAND (retval, 0);
expand_aggr_init (result, retval, 0);
expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE;
retval = 0;
......
......@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 361. Free: */
/* First used: 0 (reserved), Last used: 363. Free: */
static int abortcount = 0;
......@@ -1430,7 +1430,7 @@ build_functional_cast (exp, parms)
pedwarn ("initializer list being treated as compound expression");
parms = build_compound_expr (parms);
}
return build_c_cast (type, parms);
return build_c_cast (type, parms, 1);
}
if (TYPE_SIZE (type) == NULL_TREE)
......@@ -1440,7 +1440,7 @@ build_functional_cast (exp, parms)
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, parms);
return build_c_cast (type, parms, 1);
expr_as_ctor = build_method_call (NULL_TREE, name, parms,
NULL_TREE, LOOKUP_NORMAL);
......
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