Commit eb66be0e by Mike Stump

91th Cygnus<->FSF merge

From-SVN: r13971
parent 2ec43107
Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
* init.c (init_decl_processing): Add supoprt for setjmp/longjmp based
exception handling.
* except.c (init_exception_processing): Likewise.
(expand_end_catch_block): Likewise.
(expand_exception_blocks): Likewise.
(expand_throw): Likewise.
* exception.cc (__default_terminate): Likewise.
* init.c (perform_member_init): Use new method of expr level
cleanups, instead of cleanups_this_call and friends.
(emit_base_init): Likewise.
(expand_aggr_vbase_init_1): Likewise.
(expand_vec_init): Likewise.
* decl.c (cp_finish_decl): Likewise.
(expand_static_init): Likewise.
(store_parm_decls): Likewise.
(cplus_expand_expr_stmt): Likewise.
* decl2.c (finish_file): Likewise.
* Make-lang.in (exception.o): Ok to compile with -O now.
* decl.c (maybe_build_cleanup_1): We no longer have to unsave, as
we know it will be done later by the backend.
* decl2.c (lang_f_options): Remove support for short temps.
* lang-options.h: Likewise.
Wed Apr 23 04:12:06 1997 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (varargs_function_p): New fn.
* method.c (emit_thunk): Replace broken generic code with code to
generate a heavyweight thunk function.
Tue Apr 22 02:45:18 1997 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (process_template_parm): pedwarn about floating-point parms.
* decl.c (grokdeclarator): inline no longer implies static.
* spew.c (yylex): Always return the TYPE_DECL if we got a scope.
Mon Apr 21 15:42:27 1997 Jason Merrill <jason@yorick.cygnus.com>
* class.c (check_for_override): The signature of an overriding
function is not changed.
* call.c (build_over_call): Move setting of conv into the loop.
Sun Apr 20 16:24:29 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_user_type_conversion_1): Really ignore rvalue
conversions when looking for a REFERENCE_TYPE.
* cvt.c (build_up_reference): Eviscerate, use build_unary_op.
* cp-tree.h (TREE_REFERENCE_EXPR): #if 0.
* typeck.c (decay_conversion): Don't set TREE_REFERENCE_EXPR.
(build_unary_op): Likewise.
* call.c (build_over_call): See through a CONVERT_EXPR around the
ADDR_EXPR for on a temporary.
* typeck.c (c_expand_return): See through a CONVERT_EXPR around
the ADDR_EXPR for a local variable.
Fri Apr 18 12:11:33 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_user_type_conversion_1): If we're trying to
convert to a REFERENCE_TYPE, only consider lvalue conversions.
(build_new_function_call): Print candidates.
(implicit_conversion): Try a temp binding if the lvalue conv is BAD.
(reference_binding): Binding a temporary of a reference-related type
is BAD.
Thu Apr 17 14:37:22 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
* inc/typeinfo (type_info::before): Add cv-qualifier-seq.
* tinfo2.cc (type_info::before): Likewise.
Mon Apr 14 12:38:17 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (implicit_conversion): Oops.
Fri Apr 11 02:18:30 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (implicit_conversion): Try to find a reference conversion
before binding a const reference to a temporary.
Wed Apr 2 12:51:36 1997 Mike Stump <mrs@cygnus.com>
* exception.cc (__default_unexpected): Call terminate by default,
so that if the user overrides terminate, the correct function will
be called.
Wed Mar 19 14:14:45 1997 Mike Stump <mrs@cygnus.com> Wed Mar 19 14:14:45 1997 Mike Stump <mrs@cygnus.com>
* parse.y (left_curly): Avoid trying to use any fields of * parse.y (left_curly): Avoid trying to use any fields of
......
...@@ -144,7 +144,7 @@ tinfo2.o: cc1plus $(srcdir)/cp/tinfo2.cc ...@@ -144,7 +144,7 @@ tinfo2.o: cc1plus $(srcdir)/cp/tinfo2.cc
-c $(srcdir)/cp/tinfo2.cc -c $(srcdir)/cp/tinfo2.cc
exception.o: cc1plus $(srcdir)/cp/exception.cc exception.o: cc1plus $(srcdir)/cp/exception.cc
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
-c -O0 -fexceptions $(srcdir)/cp/exception.cc -c -fexceptions $(srcdir)/cp/exception.cc
new.o: cc1plus $(srcdir)/cp/new.cc new.o: cc1plus $(srcdir)/cp/new.cc
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new.cc -c $(srcdir)/cp/new.cc
......
...@@ -3187,13 +3187,18 @@ reference_binding (rto, rfrom, expr, flags) ...@@ -3187,13 +3187,18 @@ reference_binding (rto, rfrom, expr, flags)
int lvalue = 1; int lvalue = 1;
tree to = TREE_TYPE (rto); tree to = TREE_TYPE (rto);
tree from = rfrom; tree from = rfrom;
int related;
if (TREE_CODE (from) == REFERENCE_TYPE) if (TREE_CODE (from) == REFERENCE_TYPE)
from = TREE_TYPE (from); from = TREE_TYPE (from);
else if (! expr || ! real_lvalue_p (expr)) else if (! expr || ! real_lvalue_p (expr))
lvalue = 0; lvalue = 0;
if (lvalue related = (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from)
|| (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from)));
if (lvalue && related
&& TYPE_READONLY (to) >= TYPE_READONLY (from) && TYPE_READONLY (to) >= TYPE_READONLY (from)
&& TYPE_VOLATILE (to) >= TYPE_VOLATILE (from)) && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from))
{ {
...@@ -3201,14 +3206,11 @@ reference_binding (rto, rfrom, expr, flags) ...@@ -3201,14 +3206,11 @@ reference_binding (rto, rfrom, expr, flags)
if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from)) if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from))
conv = build_conv (REF_BIND, rto, conv); conv = build_conv (REF_BIND, rto, conv);
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) else
&& DERIVED_FROM_P (to, from))
{ {
conv = build_conv (REF_BIND, rto, conv); conv = build_conv (REF_BIND, rto, conv);
ICS_STD_RANK (conv) = STD_RANK; ICS_STD_RANK (conv) = STD_RANK;
} }
else
conv = NULL_TREE;
} }
else else
conv = NULL_TREE; conv = NULL_TREE;
...@@ -3225,8 +3227,15 @@ reference_binding (rto, rfrom, expr, flags) ...@@ -3225,8 +3227,15 @@ reference_binding (rto, rfrom, expr, flags)
if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV)
TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
} }
if (conv && ! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to) if (conv
&& ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
&& (flags & LOOKUP_NO_TEMP_BIND) == 0)) && (flags & LOOKUP_NO_TEMP_BIND) == 0))
/* If T1 is reference-related to T2, cv1 must be the same
cv-qualification as, or greater cv-qualification than,
cv2; otherwise, the program is ill-formed. */
|| (related
&& (TYPE_READONLY (to) < TYPE_READONLY (from)
|| TYPE_VOLATILE (to) < TYPE_VOLATILE (from)))))
ICS_BAD_FLAG (conv) = 1; ICS_BAD_FLAG (conv) = 1;
} }
...@@ -3265,7 +3274,12 @@ implicit_conversion (to, from, expr, flags) ...@@ -3265,7 +3274,12 @@ implicit_conversion (to, from, expr, flags)
|| IS_AGGR_TYPE (non_reference (to))) || IS_AGGR_TYPE (non_reference (to)))
&& (flags & LOOKUP_NO_CONVERSION) == 0) && (flags & LOOKUP_NO_CONVERSION) == 0)
{ {
if (TREE_CODE (to) == REFERENCE_TYPE cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
if ((! conv || ICS_BAD_FLAG (conv))
&& TREE_CODE (to) == REFERENCE_TYPE
&& TYPE_READONLY (TREE_TYPE (to)) && TYPE_READONLY (TREE_TYPE (to))
&& ! TYPE_VOLATILE (TREE_TYPE (to)) && ! TYPE_VOLATILE (TREE_TYPE (to))
&& (flags & LOOKUP_NO_TEMP_BIND) == 0) && (flags & LOOKUP_NO_TEMP_BIND) == 0)
...@@ -3275,13 +3289,6 @@ implicit_conversion (to, from, expr, flags) ...@@ -3275,13 +3289,6 @@ implicit_conversion (to, from, expr, flags)
if (cand) if (cand)
conv = build_conv (REF_BIND, to, cand->second_conv); conv = build_conv (REF_BIND, to, cand->second_conv);
} }
else
{
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
}
} }
return conv; return conv;
...@@ -4181,7 +4188,10 @@ print_z_candidates (candidates) ...@@ -4181,7 +4188,10 @@ print_z_candidates (candidates)
} }
/* Returns the best overload candidate to perform the requested /* Returns the best overload candidate to perform the requested
conversion. */ conversion. This function is used for three the overloading situations
described in [over.match.copy], [over.match.conv], and [over.match.ref].
If TOTYPE is a REFERENCE_TYPE, we're trying to find an lvalue binding as
per [dcl.init.ref], so we ignore temporary bindings. */
static struct z_candidate * static struct z_candidate *
build_user_type_conversion_1 (totype, expr, flags) build_user_type_conversion_1 (totype, expr, flags)
...@@ -4229,9 +4239,22 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4229,9 +4239,22 @@ build_user_type_conversion_1 (totype, expr, flags)
for (; convs; convs = TREE_CHAIN (convs)) for (; convs; convs = TREE_CHAIN (convs))
{ {
tree fn = TREE_VALUE (convs); tree fn = TREE_VALUE (convs);
tree ics = implicit_conversion int convflags = LOOKUP_NO_CONVERSION;
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, LOOKUP_NO_CONVERSION); tree ics;
if (ics)
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
we don't find an lvalue binding, the caller will try again to
look for a temporary binding. */
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
/* ignore the near match. */;
else if (ics)
for (; fn; fn = DECL_CHAIN (fn)) for (; fn; fn = DECL_CHAIN (fn))
{ {
candidates = add_function_candidate (candidates, fn, args, flags); candidates = add_function_candidate (candidates, fn, args, flags);
...@@ -4348,9 +4371,10 @@ build_new_function_call (fn, args, obj) ...@@ -4348,9 +4371,10 @@ build_new_function_call (fn, args, obj)
{ {
if (candidates && ! candidates->next) if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args); return build_function_call (candidates->fn, args);
else
cp_error ("no matching function for call to `%D (%A)'", cp_error ("no matching function for call to `%D (%A)'",
TREE_PURPOSE (fn), args); TREE_PURPOSE (fn), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node; return error_mark_node;
} }
candidates = splice_viable (candidates); candidates = splice_viable (candidates);
...@@ -5037,11 +5061,12 @@ build_over_call (fn, convs, args, flags) ...@@ -5037,11 +5061,12 @@ build_over_call (fn, convs, args, flags)
is_method = 1; is_method = 1;
} }
for (; conv = TREE_VEC_ELT (convs, i), arg && parm; for (; arg && parm;
parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
{ {
tree type = TREE_VALUE (parm); tree type = TREE_VALUE (parm);
conv = TREE_VEC_ELT (convs, i);
if (ICS_BAD_FLAG (conv)) if (ICS_BAD_FLAG (conv))
{ {
tree t = conv; tree t = conv;
...@@ -5118,17 +5143,24 @@ build_over_call (fn, convs, args, flags) ...@@ -5118,17 +5143,24 @@ build_over_call (fn, convs, args, flags)
&& TREE_VEC_LENGTH (convs) == 1 && TREE_VEC_LENGTH (convs) == 1
&& copy_args_p (fn)) && copy_args_p (fn))
{ {
tree targ = NULL_TREE; tree targ;
arg = TREE_VALUE (TREE_CHAIN (converted_args)); arg = TREE_VALUE (TREE_CHAIN (converted_args));
/* Pull out the real argument, disregarding const-correctness. */ /* Pull out the real argument, disregarding const-correctness. */
if (TREE_CODE (arg) == ADDR_EXPR) targ = arg;
{ while (TREE_CODE (targ) == NOP_EXPR
targ = TREE_OPERAND (arg, 0); || TREE_CODE (targ) == NON_LVALUE_EXPR
|| TREE_CODE (targ) == CONVERT_EXPR)
targ = TREE_OPERAND (targ, 0);
if (TREE_CODE (targ) == ADDR_EXPR)
{
targ = TREE_OPERAND (targ, 0);
if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))), if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1)) TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1))
targ = NULL_TREE; targ = NULL_TREE;
} }
else
targ = NULL_TREE;
if (targ) if (targ)
arg = targ; arg = targ;
......
...@@ -2809,6 +2809,7 @@ check_for_override (decl, ctype) ...@@ -2809,6 +2809,7 @@ check_for_override (decl, ctype)
} }
virtualp = 1; virtualp = 1;
#if 0 /* The signature of an overriding function is not changed. */
{ {
/* The argument types may have changed... */ /* The argument types may have changed... */
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
...@@ -2823,9 +2824,10 @@ check_for_override (decl, ctype) ...@@ -2823,9 +2824,10 @@ check_for_override (decl, ctype)
if (raises) if (raises)
type = build_exception_variant (type, raises); type = build_exception_variant (type, raises);
TREE_TYPE (decl) = type; TREE_TYPE (decl) = type;
}
#endif
DECL_VINDEX (decl) DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
}
break; break;
} }
} }
......
...@@ -1195,10 +1195,12 @@ extern int flag_new_for_scope; ...@@ -1195,10 +1195,12 @@ extern int flag_new_for_scope;
#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ #define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
&& CONSTRUCTOR_ELTS (NODE) == NULL_TREE) && CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
#if 0
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference. /* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
Used to generate more helpful error message in case somebody Used to generate more helpful error message in case somebody
tries to take its address. */ tries to take its address. */
#define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE)) #define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE))
#endif
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */ /* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE)) #define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
......
...@@ -371,232 +371,24 @@ convert_to_pointer_force (type, expr) ...@@ -371,232 +371,24 @@ convert_to_pointer_force (type, expr)
value we have to begin with is in ARG. value we have to begin with is in ARG.
FLAGS controls how we manage access checking. FLAGS controls how we manage access checking.
DIRECT_BIND in FLAGS controls how any temporarys are generated. DIRECT_BIND in FLAGS controls how any temporaries are generated. */
CHECKCONST controls if we report error messages on const subversion. */
static tree static tree
build_up_reference (type, arg, flags, checkconst) build_up_reference (type, arg, flags, checkconst)
tree type, arg; tree type, arg;
int flags, checkconst; int flags, checkconst;
{ {
tree rval, targ; tree rval;
int literal_flag = 0;
tree argtype = TREE_TYPE (arg); tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type); tree target_type = TREE_TYPE (type);
tree binfo = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187); my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
&& IS_AGGR_TYPE (argtype)
&& IS_AGGR_TYPE (target_type))
{
binfo = get_binfo (target_type, argtype, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype);
}
/* Pass along const and volatile down into the type. */
if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
target_type = cp_build_type_variant (target_type, TYPE_READONLY (type),
TYPE_VOLATILE (type));
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))
{
case INDIRECT_REF:
/* This is a call to a constructor which did not know what it was
initializing until now: it needs to initialize a temporary. */
if (TREE_HAS_CONSTRUCTOR (targ))
{
tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0));
TREE_HAS_CONSTRUCTOR (targ) = 0;
return build_up_reference (type, temp, flags, 1);
}
/* Let &* cancel out to simplify resulting code.
Also, throw away intervening NOP_EXPRs. */
arg = TREE_OPERAND (targ, 0);
if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR
|| (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg)))
arg = TREE_OPERAND (arg, 0);
/* in doing a &*, we have to get rid of the const'ness on the pointer
value. Haven't thought about volatile here. Pointers come to mind
here. */
if (TREE_READONLY (arg))
{
arg = copy_node (arg);
TREE_READONLY (arg) = 0;
}
rval = build1 (CONVERT_EXPR, type, arg);
TREE_REFERENCE_EXPR (rval) = 1;
/* propagate the const flag on something like:
class Base {
public:
int foo;
};
class Derived : public Base {
public:
int bar;
};
void func(Base&);
void func2(const Derived& d) {
func(d);
}
on the d parameter. The below could have been avoided, if the flags
were down in the tree, not sure why they are not. (mrs) */
/* The below code may have to be propagated to other parts of this
switch. */
if (TREE_READONLY (targ) && !TREE_READONLY (arg)
&& (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL)
&& TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
&& (TYPE_READONLY (target_type) && checkconst))
{
arg = copy_node (arg);
TREE_READONLY (arg) = TREE_READONLY (targ);
}
literal_flag = TREE_CONSTANT (arg);
goto done;
/* Get this out of a register if we happened to be in one by accident.
Also, build up references to non-lvalues it we must. */
/* For &x[y], return (&) x+y */
case ARRAY_REF:
if (mark_addressable (TREE_OPERAND (targ, 0)) == 0)
return error_mark_node;
rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0),
TREE_OPERAND (targ, 1), 1);
TREE_TYPE (rval) = type;
if (TREE_CONSTANT (TREE_OPERAND (targ, 1))
&& staticp (TREE_OPERAND (targ, 0)))
TREE_CONSTANT (rval) = 1;
goto done;
case SCOPE_REF:
/* Could be a reference to a static member. */
{
tree field = TREE_OPERAND (targ, 1);
if (TREE_STATIC (field))
{
rval = build1 (ADDR_EXPR, type, field);
literal_flag = 1;
goto done;
}
}
/* We should have farmed out member pointers above. */
my_friendly_abort (188);
case COMPONENT_REF:
rval = build_component_addr (targ, build_pointer_type (argtype),
"attempt to make a reference to bit-field structure member `%s'");
TREE_TYPE (rval) = type;
literal_flag = staticp (TREE_OPERAND (targ, 0));
goto done;
/* Anything not already handled and not a true memory reference
needs to have a reference built up. Do so silently for
things like integers and return values from function,
but complain if we need a reference to something declared
as `register'. */
case PARM_DECL:
/* 'this' is not an lvalue. */
if (targ == current_class_ptr && ! flag_this_is_variable)
break;
case RESULT_DECL:
case VAR_DECL:
case CONST_DECL:
if (staticp (targ))
literal_flag = 1;
/* Fall through. */ if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
case TARGET_EXPR:
mark_addressable (targ);
break;
case COMPOUND_EXPR:
{
tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1),
flags, checkconst);
rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference);
TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1));
return rval;
}
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case MODIFY_EXPR:
case INIT_EXPR:
{
tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0),
flags, checkconst);
rval = build (COMPOUND_EXPR, type, arg, real_reference);
TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0));
return rval;
}
case COND_EXPR:
return build (COND_EXPR, type,
TREE_OPERAND (targ, 0),
build_up_reference (type, TREE_OPERAND (targ, 1),
flags, checkconst),
build_up_reference (type, TREE_OPERAND (targ, 2),
flags, checkconst));
/* Undo the folding... */
case MIN_EXPR:
case MAX_EXPR:
return build (COND_EXPR, type,
build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR,
boolean_type_node, TREE_OPERAND (targ, 0),
TREE_OPERAND (targ, 1)),
build_up_reference (type, TREE_OPERAND (targ, 0),
flags, checkconst),
build_up_reference (type, TREE_OPERAND (targ, 1),
flags, checkconst));
case BIND_EXPR:
arg = TREE_OPERAND (targ, 1);
if (arg == NULL_TREE)
{
compiler_error ("({ ... }) expression not expanded when needed for reference");
return error_mark_node;
}
rval = build1 (ADDR_EXPR, type, arg);
TREE_REFERENCE_EXPR (rval) = 1;
return rval;
default:
break;
}
if ((flags & DIRECT_BIND)
&& ! real_lvalue_p (targ))
{ {
tree targ = arg;
if (toplevel_bindings_p ()) if (toplevel_bindings_p ())
{
arg = get_temp_name (argtype, 1); arg = get_temp_name (argtype, 1);
literal_flag = 1;
}
else else
{ {
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
...@@ -605,7 +397,7 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -605,7 +397,7 @@ build_up_reference (type, arg, flags, checkconst)
DECL_INITIAL (arg) = targ; DECL_INITIAL (arg) = targ;
cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
} }
else if (TREE_ADDRESSABLE (targ) == 0 && !(flags & DIRECT_BIND)) else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{ {
tree slot = build_decl (VAR_DECL, NULL_TREE, argtype); tree slot = build_decl (VAR_DECL, NULL_TREE, argtype);
arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE); arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
...@@ -614,25 +406,14 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -614,25 +406,14 @@ build_up_reference (type, arg, flags, checkconst)
/* If we had a way to wrap this up, and say, if we ever needed it's /* If we had a way to wrap this up, and say, if we ever needed it's
address, transform all occurrences of the register, into a memory address, transform all occurrences of the register, into a memory
reference we could win better. */ reference we could win better. */
mark_addressable (arg); rval = build_unary_op (ADDR_EXPR, arg, 1);
rval = build1 (ADDR_EXPR, type, arg);
done:
if (TYPE_USES_COMPLEX_INHERITANCE (argtype)
|| TYPE_USES_COMPLEX_INHERITANCE (target_type))
{
TREE_TYPE (rval) = build_pointer_type (argtype);
if (flags & LOOKUP_PROTECT) if (flags & LOOKUP_PROTECT)
rval = convert_pointer_to (target_type, rval); rval = convert_pointer_to (target_type, rval);
else else
rval rval
= convert_to_pointer_force (build_pointer_type (target_type), rval); = convert_to_pointer_force (build_pointer_type (target_type), rval);
TREE_TYPE (rval) = type; rval = build1 (CONVERT_EXPR, type, rval);
if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR) TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
TREE_TYPE (TREE_OPERAND (rval, 0))
= TREE_TYPE (TREE_OPERAND (rval, 1)) = type;
}
TREE_CONSTANT (rval) = literal_flag;
return rval; return rval;
} }
......
...@@ -49,8 +49,6 @@ extern struct obstack permanent_obstack; ...@@ -49,8 +49,6 @@ extern struct obstack permanent_obstack;
extern int current_class_depth; extern int current_class_depth;
extern tree cleanups_this_call;
extern tree static_ctors, static_dtors; extern tree static_ctors, static_dtors;
/* Stack of places to restore the search obstack back to. */ /* Stack of places to restore the search obstack back to. */
...@@ -5012,6 +5010,18 @@ init_decl_processing () ...@@ -5012,6 +5010,18 @@ init_decl_processing ()
BUILT_IN_NEXT_ARG, NULL_PTR); BUILT_IN_NEXT_ARG, NULL_PTR);
builtin_function ("__builtin_args_info", int_ftype_int, builtin_function ("__builtin_args_info", int_ftype_int,
BUILT_IN_ARGS_INFO, NULL_PTR); BUILT_IN_ARGS_INFO, NULL_PTR);
builtin_function ("__builtin_setjmp",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, ptr_type_node,
endlink)),
BUILT_IN_SETJMP, NULL_PTR);
builtin_function ("__builtin_longjmp",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
integer_type_node,
endlink))),
BUILT_IN_LONGJMP, NULL_PTR);
/* Untyped call and return. */ /* Untyped call and return. */
builtin_function ("__builtin_apply_args", ptr_ftype, builtin_function ("__builtin_apply_args", ptr_ftype,
...@@ -6569,11 +6579,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6569,11 +6579,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
} }
else if (! toplev) else if (! toplev)
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
/* This is a declared decl which must live until the /* This is a declared decl which must live until the
end of the binding contour. It may need a cleanup. */ end of the binding contour. It may need a cleanup. */
...@@ -6654,9 +6659,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6654,9 +6659,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
} }
} }
push_temp_slots (); expand_start_target_temps ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (DECL_SIZE (decl) && type != error_mark_node) if (DECL_SIZE (decl) && type != error_mark_node)
{ {
...@@ -6679,11 +6682,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6679,11 +6682,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
&& DECL_NAME (decl)) && DECL_NAME (decl))
TREE_USED (decl) = 0; TREE_USED (decl) = 0;
} }
/* Cleanup any temporaries needed for the initial value. */ /* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups); expand_end_target_temps ();
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
if (DECL_SIZE (decl) && type != error_mark_node) if (DECL_SIZE (decl) && type != error_mark_node)
{ {
...@@ -6777,11 +6778,6 @@ expand_static_init (decl, init) ...@@ -6777,11 +6778,6 @@ expand_static_init (decl, init)
/* Emit code to perform this initialization but once. */ /* Emit code to perform this initialization but once. */
tree temp; tree temp;
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups;
int old_temp_level;
/* Remember this information until end of file. */ /* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack); push_obstacks (&permanent_obstack, &permanent_obstack);
...@@ -6790,11 +6786,7 @@ expand_static_init (decl, init) ...@@ -6790,11 +6786,7 @@ expand_static_init (decl, init)
rest_of_decl_compilation (temp, NULL_PTR, 0, 0); rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
expand_start_cond (build_binary_op (EQ_EXPR, temp, expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node, 1), 0); integer_zero_node, 1), 0);
old_cleanups = cleanups_this_call; expand_start_target_temps ();
old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
expand_assignment (temp, integer_one_node, 0, 0); expand_assignment (temp, integer_one_node, 0, 0);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
...@@ -6807,10 +6799,7 @@ expand_static_init (decl, init) ...@@ -6807,10 +6799,7 @@ expand_static_init (decl, init)
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */ /* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups); expand_end_target_temps ();
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{ {
...@@ -9195,9 +9184,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9195,9 +9184,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
} }
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (! friendp publicp = (! friendp || ! staticp);
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| ! (funcdef_flag < 0 || inlinep));
decl = grokfndecl (ctype, type, declarator, decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, raises, attrlist, virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, publicp, inlinep, friendp ? -1 : 0, publicp, inlinep,
...@@ -9395,11 +9382,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9395,11 +9382,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type)); TREE_TYPE (type), TYPE_ARG_TYPES (type));
/* Record presence of `static'. In C++, `inline' implies `static'. */ /* Record presence of `static'. */
publicp = (ctype != NULL_TREE publicp = (ctype != NULL_TREE
|| RIDBIT_SETP (RID_EXTERN, specbits) || RIDBIT_SETP (RID_EXTERN, specbits)
|| (!RIDBIT_SETP (RID_STATIC, specbits) || !RIDBIT_SETP (RID_STATIC, specbits));
&& !RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name, decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals, raises, attrlist, virtualp, flags, quals, raises, attrlist,
...@@ -11281,6 +11267,7 @@ store_parm_decls () ...@@ -11281,6 +11267,7 @@ store_parm_decls ()
register tree fndecl = current_function_decl; register tree fndecl = current_function_decl;
register tree parm; register tree parm;
int parms_have_cleanups = 0; int parms_have_cleanups = 0;
tree cleanups = NULL_TREE;
/* This is either a chain of PARM_DECLs (when a prototype is used). */ /* This is either a chain of PARM_DECLs (when a prototype is used). */
tree specparms = current_function_parms; tree specparms = current_function_parms;
...@@ -11355,10 +11342,10 @@ store_parm_decls () ...@@ -11355,10 +11342,10 @@ store_parm_decls ()
&& (cleanup = maybe_build_cleanup (parm), cleanup)) && (cleanup = maybe_build_cleanup (parm), cleanup))
{ {
expand_decl (parm); expand_decl (parm);
if (! expand_decl_cleanup (parm, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
parm);
parms_have_cleanups = 1; parms_have_cleanups = 1;
/* Keep track of the cleanups. */
cleanups = tree_cons (parm, cleanup, cleanups);
} }
} }
else else
...@@ -11392,6 +11379,20 @@ store_parm_decls () ...@@ -11392,6 +11379,20 @@ store_parm_decls ()
if (! processing_template_decl) if (! processing_template_decl)
expand_function_start (fndecl, parms_have_cleanups); expand_function_start (fndecl, parms_have_cleanups);
/* Now that we have initialized the parms, we can start their
cleanups. We cannot do this before, since expand_decl_cleanup
should not be called before the parm can be used. */
if (parms_have_cleanups
&& ! processing_template_decl)
{
for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
{
if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups)))
cp_error ("parser lost in parsing declaration of `%D'",
TREE_PURPOSE (cleanups));
}
}
/* Create a binding contour which can be used to catch /* Create a binding contour which can be used to catch
cleanup-generated temporaries. Also, if the return value needs or cleanup-generated temporaries. Also, if the return value needs or
has initialization, deal with that now. */ has initialization, deal with that now. */
...@@ -12329,9 +12330,6 @@ maybe_build_cleanup_1 (decl, auto_delete) ...@@ -12329,9 +12330,6 @@ maybe_build_cleanup_1 (decl, auto_delete)
rval = build_compound_expr (tree_cons (NULL_TREE, rval, rval = build_compound_expr (tree_cons (NULL_TREE, rval,
build_tree_list (NULL_TREE, build_vbase_delete (type, decl)))); build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
/* Since this is a cleanup, UNSAVE it now. */
rval = unsave_expr (rval);
if (TREE_CODE (decl) != PARM_DECL) if (TREE_CODE (decl) != PARM_DECL)
resume_momentary (temp); resume_momentary (temp);
...@@ -12372,20 +12370,15 @@ void ...@@ -12372,20 +12370,15 @@ void
cplus_expand_expr_stmt (exp) cplus_expand_expr_stmt (exp)
tree exp; tree exp;
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (processing_template_decl) if (processing_template_decl)
{ {
add_tree (build_min_nt (EXPR_STMT, exp)); add_tree (build_min_nt (EXPR_STMT, exp));
return; return;
} }
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
if (TREE_TYPE (exp) == unknown_type_node) if (TREE_TYPE (exp) == unknown_type_node)
{ {
if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST) if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
...@@ -12415,16 +12408,7 @@ cplus_expand_expr_stmt (exp) ...@@ -12415,16 +12408,7 @@ cplus_expand_expr_stmt (exp)
/* Clean up any pending cleanups. This happens when a function call /* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */ returns a cleanup-needing value that nobody uses. */
expand_cleanups_to (old_cleanups); expand_end_target_temps ();
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots ();
} }
/* When a stmt has been parsed, this function is called. /* When a stmt has been parsed, this function is called.
......
...@@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h" #include "output.h"
extern tree get_file_function_name (); extern tree get_file_function_name ();
extern tree cleanups_this_call;
static void grok_function_init PROTO((tree, tree)); static void grok_function_init PROTO((tree, tree));
void import_export_decl (); void import_export_decl ();
extern int current_class_depth; extern int current_class_depth;
...@@ -420,7 +419,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -420,7 +419,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"huge-objects", &flag_huge_objects, 1}, {"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1}, {"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1}, {"vtable-thunks", &flag_vtable_thunks, 1},
{"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1}, {"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0}, {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0}, {"gnu-keywords", &flag_no_gnu_keywords, 0},
...@@ -2919,15 +2917,8 @@ finish_file () ...@@ -2919,15 +2917,8 @@ finish_file ()
while (vars) while (vars)
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
tree init = TREE_PURPOSE (vars); tree init = TREE_PURPOSE (vars);
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
/* If this was a static attribute within some function's scope, /* If this was a static attribute within some function's scope,
then don't initialize it here. Also, don't bother then don't initialize it here. Also, don't bother
...@@ -2964,6 +2955,8 @@ finish_file () ...@@ -2964,6 +2955,8 @@ finish_file ()
expand_start_cond (sentry, 0); expand_start_cond (sentry, 0);
} }
expand_start_target_temps ();
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0); expand_aggr_init (decl, init, 0, 0);
...@@ -2977,6 +2970,9 @@ finish_file () ...@@ -2977,6 +2970,9 @@ finish_file ()
else else
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */
expand_end_target_temps ();
if (protect) if (protect)
expand_end_cond (); expand_end_cond ();
...@@ -2987,13 +2983,7 @@ finish_file () ...@@ -2987,13 +2983,7 @@ finish_file ()
; ;
else my_friendly_abort (22); else my_friendly_abort (22);
/* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups);
next_mess: next_mess:
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
vars = TREE_CHAIN (vars); vars = TREE_CHAIN (vars);
} }
......
...@@ -35,12 +35,12 @@ Boston, MA 02111-1307, USA. */ ...@@ -35,12 +35,12 @@ Boston, MA 02111-1307, USA. */
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx)); rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
/* holds the fndecl for __builtin_return_address () */ /* Holds the fndecl for __builtin_return_address. */
tree builtin_return_address_fndecl; tree builtin_return_address_fndecl;
/* A couple of backend routines from m88k.c */ /* A couple of backend routines from m88k.c */
/* used to cache a call to __builtin_return_address () */ /* Used to cache a call to __builtin_return_address. */
static tree BuiltinReturnAddress; static tree BuiltinReturnAddress;
...@@ -163,18 +163,17 @@ extern rtx gen_nop PROTO(()); ...@@ -163,18 +163,17 @@ extern rtx gen_nop PROTO(());
/* local globals for function calls /* local globals for function calls
====================================================================== */ ====================================================================== */
/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and /* Used to cache "terminate", "unexpected", "set_terminate", and
"set_unexpected ()" after default_conversion. (lib-except.c) */ "set_unexpected" after default_conversion. (lib-except.c) */
static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch; static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
/* used to cache __find_first_exception_table_match () /* Used to cache __find_first_exception_table_match for throw. */
for throw (lib-except.c) */
static tree FirstExceptionMatch; static tree FirstExceptionMatch;
/* used to cache a call to __unwind_function () (lib-except.c) */ /* Used to cache a call to __unwind_function. */
static tree Unwind; static tree Unwind;
/* holds a ready to emit call to "terminate ()". */ /* Holds a ready to emit call to "terminate". */
static tree TerminateFunctionCall; static tree TerminateFunctionCall;
static tree empty_fndecl; static tree empty_fndecl;
...@@ -245,8 +244,8 @@ init_exception_processing () ...@@ -245,8 +244,8 @@ init_exception_processing ()
tree PFV = build_pointer_type (build_function_type tree PFV = build_pointer_type (build_function_type
(void_type_node, void_list_node)); (void_type_node, void_list_node));
/* arg list for the build_function_type call for set_terminate () and /* Arg list for the build_function_type call for set_terminate and
set_unexpected () */ set_unexpected. */
tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
/* void (*pfvtype (void (*) ()))() */ /* void (*pfvtype (void (*) ()))() */
...@@ -343,6 +342,10 @@ init_exception_processing () ...@@ -343,6 +342,10 @@ init_exception_processing ()
DECL_COMMON (d) = 1; DECL_COMMON (d) = 1;
cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0); saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0);
/* If we use setjmp/longjmp EH, arrange for all cleanup actions to
be protected with __terminate. */
protect_cleanup_actions_with_terminate = 1;
} }
/* Build a type value for use at runtime for a type that is matched /* Build a type value for use at runtime for a type that is matched
...@@ -448,6 +451,8 @@ expand_start_catch_block (declspecs, declarator) ...@@ -448,6 +451,8 @@ expand_start_catch_block (declspecs, declarator)
false_label_rtx = gen_label_rtx (); false_label_rtx = gen_label_rtx ();
push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE); push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
emit_line_note (input_filename, lineno);
if (declspecs) if (declspecs)
{ {
tree exp; tree exp;
...@@ -460,8 +465,11 @@ expand_start_catch_block (declspecs, declarator) ...@@ -460,8 +465,11 @@ expand_start_catch_block (declspecs, declarator)
{ {
error ("invalid catch parameter"); error ("invalid catch parameter");
/* This is cheap, but we want to maintain the data structures. */ /* This is cheap, but we want to maintain the data
structures. */
expand_eh_region_start (); expand_eh_region_start ();
return; return;
} }
...@@ -513,11 +521,17 @@ expand_start_catch_block (declspecs, declarator) ...@@ -513,11 +521,17 @@ expand_start_catch_block (declspecs, declarator)
emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx); emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
/* Because we are reordered out of line, we arrange /* If we are not doing setjmp/longjmp EH, because we are reordered
to rethrow in the outer context, should we encounter out of line, we arrange to rethrow in the outer context so as to
an exception in the catch handler. skip through the terminate region we are nested in, should we
encounter an exception in the catch handler.
Matches the end in expand_end_catch_block (). */ If we are doing setjmp/longjmp EH, we need to skip through the EH
object cleanup region. This isn't quite right, as we really need
to clean the object up, but we cannot do that until we track
multiple EH objects.
Matches the end in expand_end_catch_block. */
expand_eh_region_start (); expand_eh_region_start ();
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
...@@ -539,23 +553,42 @@ expand_end_catch_block () ...@@ -539,23 +553,42 @@ expand_end_catch_block ()
if (! doing_eh (1)) if (! doing_eh (1))
return; return;
/* Fall to outside the try statement when done executing handler and
we fall off end of handler. This is jump Lresume in the
documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
t = make_node (RTL_EXPR); t = make_node (RTL_EXPR);
TREE_TYPE (t) = void_type_node; TREE_TYPE (t) = void_type_node;
RTL_EXPR_RTL (t) = const0_rtx; RTL_EXPR_RTL (t) = const0_rtx;
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
start_sequence_for_rtl_expr (t); start_sequence_for_rtl_expr (t);
if (exceptions_via_longjmp)
{
/* If we are doing setjmp/longjmp EH, we need to skip through
the EH object cleanup region. This isn't quite right, as we
really need to clean the object up, but we cannot do that
until we track multiple EH objects. */
emit_library_call (sjpopnthrow_libfunc, 0, VOIDmode, 0);
emit_barrier ();
}
else
{
/* If we are not doing setjmp/longjmp EH, we need an extra
region around the whole catch block to skip through the
terminate region we are nested in. */
expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack))); expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
}
RTL_EXPR_SEQUENCE (t) = get_insns (); RTL_EXPR_SEQUENCE (t) = get_insns ();
end_sequence (); end_sequence ();
/* Matches the start in expand_start_catch_block (). */ /* Matches the start in expand_start_catch_block. */
expand_eh_region_end (t); expand_eh_region_end (t);
/* Fall to outside the try statement when done executing handler and
we fall off end of handler. This is jump Lresume in the
documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
expand_leftover_cleanups (); expand_leftover_cleanups ();
/* Cleanup the EH parameter. */ /* Cleanup the EH parameter. */
...@@ -580,7 +613,7 @@ do_unwind (inner_throw_label) ...@@ -580,7 +613,7 @@ do_unwind (inner_throw_label)
rtx return_val_rtx; rtx return_val_rtx;
rtx temp; rtx temp;
/* call to __builtin_return_address () */ /* Call to __builtin_return_address. */
params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params); fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
...@@ -633,7 +666,7 @@ do_unwind (inner_throw_label) ...@@ -633,7 +666,7 @@ do_unwind (inner_throw_label)
#if 0 #if 0
/* I would like to do this here, but the move below doesn't seem to work. */ /* I would like to do this here, but the move below doesn't seem to work. */
/* call to __builtin_return_address () */ /* Call to __builtin_return_address. */
params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params); fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
...@@ -651,7 +684,7 @@ do_unwind (inner_throw_label) ...@@ -651,7 +684,7 @@ do_unwind (inner_throw_label)
} }
/* is called from expand_exception_blocks () to generate the code in a function /* Is called from expand_exception_blocks to generate the code in a function
to "throw" if anything in the function needs to perform a throw. to "throw" if anything in the function needs to perform a throw.
expands "throw" as the following pseudo code: expands "throw" as the following pseudo code:
...@@ -731,7 +764,7 @@ expand_builtin_throw () ...@@ -731,7 +764,7 @@ expand_builtin_throw ()
/* code to deal with unwinding and looking for it again */ /* code to deal with unwinding and looking for it again */
emit_label (gotta_rethrow_it); emit_label (gotta_rethrow_it);
/* call to __builtin_return_address () */ /* Call to __builtin_return_address. */
#if defined (ARM_FRAME_RTX) /* was __arm */ #if defined (ARM_FRAME_RTX) /* was __arm */
/* This should be moved into arm.h:RETURN_ADDR_RTX */ /* This should be moved into arm.h:RETURN_ADDR_RTX */
/* This replaces a 'call' to __builtin_return_address */ /* This replaces a 'call' to __builtin_return_address */
...@@ -743,7 +776,7 @@ expand_builtin_throw () ...@@ -743,7 +776,7 @@ expand_builtin_throw ()
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
#endif #endif
/* did __builtin_return_address () return a valid address? */ /* Did __builtin_return_address return a valid address? */
emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX, emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
GET_MODE (return_val_rtx), 0, 0); GET_MODE (return_val_rtx), 0, 0);
...@@ -837,6 +870,7 @@ expand_end_eh_spec (raises) ...@@ -837,6 +870,7 @@ expand_end_eh_spec (raises)
do_function_call (Unexpected, NULL_TREE, NULL_TREE); do_function_call (Unexpected, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Unexpected, 0)); assemble_external (TREE_OPERAND (Unexpected, 0));
emit_barrier (); emit_barrier ();
expand_eh_region_end (second_try); expand_eh_region_end (second_try);
emit_label (check); emit_label (check);
...@@ -890,7 +924,6 @@ expand_exception_blocks () ...@@ -890,7 +924,6 @@ expand_exception_blocks ()
funcend = gen_label_rtx (); funcend = gen_label_rtx ();
emit_jump (funcend); emit_jump (funcend);
/* expand_null_return (); */
start_sequence (); start_sequence ();
...@@ -931,12 +964,22 @@ expand_exception_blocks () ...@@ -931,12 +964,22 @@ expand_exception_blocks ()
if (insns) if (insns)
{ {
/* We cannot protect n regions this way if we must flow into the
EH region through the top of the region, as we have to with
the setjmp/longjmp approach. */
if (exceptions_via_longjmp == 0)
{
/* Is this necessary? */ /* Is this necessary? */
assemble_external (TREE_OPERAND (Terminate, 0)); assemble_external (TREE_OPERAND (Terminate, 0));
expand_eh_region_start (); expand_eh_region_start ();
}
emit_insns (insns); emit_insns (insns);
if (exceptions_via_longjmp == 0)
expand_eh_region_end (TerminateFunctionCall); expand_eh_region_end (TerminateFunctionCall);
expand_leftover_cleanups (); expand_leftover_cleanups ();
} }
...@@ -1125,6 +1168,10 @@ expand_throw (exp) ...@@ -1125,6 +1168,10 @@ expand_throw (exp)
/* This part is easy, as we don't have to do anything else. */ /* This part is easy, as we don't have to do anything else. */
} }
if (exceptions_via_longjmp)
emit_throw ();
else
{
/* This is the label that represents where in the code we were, when /* This is the label that represents where in the code we were, when
we got an exception. This needs to be updated when we rethrow an we got an exception. This needs to be updated when we rethrow an
exception, so that the matching routine knows to search out. */ exception, so that the matching routine knows to search out. */
...@@ -1132,6 +1179,7 @@ expand_throw (exp) ...@@ -1132,6 +1179,7 @@ expand_throw (exp)
emit_label (label); emit_label (label);
expand_internal_throw (label); expand_internal_throw (label);
}
} }
/* Build a throw expression. */ /* Build a throw expression. */
......
...@@ -30,22 +30,23 @@ ...@@ -30,22 +30,23 @@
#include "typeinfo" #include "typeinfo"
#include "exception" #include "exception"
/* terminate (), unexpected (), set_terminate (), set_unexpected () as /* Define terminate, unexpected, set_terminate, set_unexpected as
well as the default terminate func and default unexpected func */ well as the default terminate func and default unexpected func. */
extern terminate_handler __terminate_func;
void void
__default_terminate () terminate ()
{ {
abort (); __terminate_func ();
} }
void void
__default_unexpected () __default_unexpected ()
{ {
__default_terminate (); terminate ();
} }
static terminate_handler __terminate_func = __default_terminate;
static unexpected_handler __unexpected_func = __default_unexpected; static unexpected_handler __unexpected_func = __default_unexpected;
terminate_handler terminate_handler
...@@ -67,12 +68,6 @@ set_unexpected (unexpected_handler func) ...@@ -67,12 +68,6 @@ set_unexpected (unexpected_handler func)
} }
void void
terminate ()
{
__terminate_func ();
}
void
unexpected () unexpected ()
{ {
__unexpected_func (); __unexpected_func ();
......
...@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h" #include "cp-tree.h"
#include "flags.h" #include "flags.h"
#include "output.h" #include "output.h"
#include "except.h"
/* In C++, structures with well-defined constructors are initialized by /* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST those constructors, unasked. CURRENT_BASE_INIT_LIST
...@@ -39,8 +40,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -39,8 +40,6 @@ Boston, MA 02111-1307, USA. */
line. Perhaps this was not intended. */ line. Perhaps this was not intended. */
tree current_base_init_list, current_member_init_list; tree current_base_init_list, current_member_init_list;
extern tree cleanups_this_call;
void emit_base_init (); void emit_base_init ();
void check_base_init (); void check_base_init ();
static void expand_aggr_vbase_init (); static void expand_aggr_vbase_init ();
...@@ -153,13 +152,8 @@ perform_member_init (member, name, init, explicit) ...@@ -153,13 +152,8 @@ perform_member_init (member, name, init, explicit)
{ {
tree decl; tree decl;
tree type = TREE_TYPE (member); tree type = TREE_TYPE (member);
extern int temp_slot_level;
extern int target_temp_slot_level; expand_start_target_temps ();
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (TYPE_NEEDS_CONSTRUCTING (type) if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type))) || (init && TYPE_HAS_CONSTRUCTOR (type)))
...@@ -219,15 +213,8 @@ perform_member_init (member, name, init, explicit) ...@@ -219,15 +213,8 @@ perform_member_init (member, name, init, explicit)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
} }
expand_cleanups_to (old_cleanups);
pop_temp_slots (); expand_end_target_temps ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots (); free_temp_slots ();
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
...@@ -589,27 +576,14 @@ emit_base_init (t, immediately) ...@@ -589,27 +576,14 @@ emit_base_init (t, immediately)
if (init != void_list_node) if (init != void_list_node)
{ {
extern int temp_slot_level; expand_start_target_temps ();
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
member = convert_pointer_to_real (base_binfo, current_class_ptr); member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE, expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL); BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
expand_cleanups_to (old_cleanups);
pop_temp_slots (); expand_end_target_temps ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots (); free_temp_slots ();
} }
...@@ -796,28 +770,14 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) ...@@ -796,28 +770,14 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree init = purpose_member (binfo, init_list); tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR); tree ref = build_indirect_ref (addr, NULL_PTR);
extern int temp_slot_level; expand_start_target_temps ();
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (init) if (init)
init = TREE_VALUE (init); init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN); expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (old_cleanups); expand_end_target_temps ();
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots (); free_temp_slots ();
} }
...@@ -3109,20 +3069,22 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -3109,20 +3069,22 @@ expand_vec_init (decl, base, maxindex, init, from_array)
push_obstacks_nochange (); push_obstacks_nochange ();
resume_temporary_allocation (); resume_temporary_allocation ();
{ {
tree e1, e2 = make_node (RTL_EXPR); tree e1, cleanup = make_node (RTL_EXPR);
TREE_TYPE (e2) = void_type_node; TREE_TYPE (cleanup) = void_type_node;
RTL_EXPR_RTL (e2) = const0_rtx; RTL_EXPR_RTL (cleanup) = const0_rtx;
TREE_SIDE_EFFECTS (e2) = 1; TREE_SIDE_EFFECTS (cleanup) = 1;
start_sequence_for_rtl_expr (e2); start_sequence_for_rtl_expr (cleanup);
e1 = build_array_eh_cleanup e1 = build_array_eh_cleanup
(rval, (rval,
build_binary_op (MINUS_EXPR, maxindex, iterator, 1), build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
type); type);
expand_expr (e1, const0_rtx, VOIDmode, 0); expand_expr (e1, const0_rtx, VOIDmode, 0);
RTL_EXPR_SEQUENCE (e2) = get_insns (); RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
end_sequence (); end_sequence ();
expand_eh_region_end (e2);
cleanup = protect_with_terminate (cleanup);
expand_eh_region_end (cleanup);
} }
pop_obstacks (); pop_obstacks ();
} }
......
...@@ -70,8 +70,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -70,8 +70,6 @@ Boston, MA 02111-1307, USA. */
"-fno-repo", "-fno-repo",
"-fsave-memoized", "-fsave-memoized",
"-fno-save-memoized", "-fno-save-memoized",
"-fshort-temps",
"-fno-short-temps",
"-fstats", "-fstats",
"-fno-stats", "-fno-stats",
"-fstrict-prototype", "-fstrict-prototype",
......
...@@ -1698,7 +1698,7 @@ make_thunk (function, delta) ...@@ -1698,7 +1698,7 @@ make_thunk (function, delta)
} }
if (thunk == NULL_TREE) if (thunk == NULL_TREE)
{ {
thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); thunk = build_lang_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk) DECL_RESULT (thunk)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type))); = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type)); TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
...@@ -1719,27 +1719,9 @@ void ...@@ -1719,27 +1719,9 @@ void
emit_thunk (thunk_fndecl) emit_thunk (thunk_fndecl)
tree thunk_fndecl; tree thunk_fndecl;
{ {
rtx insns;
char buffer[250];
tree argp;
struct args_size stack_args_size;
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
int delta = THUNK_DELTA (thunk_fndecl); int delta = THUNK_DELTA (thunk_fndecl);
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
int tem;
int failure = 0;
int save_ofp;
/* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER];
int need_use_count = 0;
/* rtx for the 'this' parameter. */
rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
char *(*save_decl_printable_name) () = decl_printable_name;
/* Data on reg parms scanned so far. */
CUMULATIVE_ARGS args_so_far;
if (TREE_ASM_WRITTEN (thunk_fndecl)) if (TREE_ASM_WRITTEN (thunk_fndecl))
return; return;
...@@ -1749,203 +1731,58 @@ emit_thunk (thunk_fndecl) ...@@ -1749,203 +1731,58 @@ emit_thunk (thunk_fndecl)
TREE_ADDRESSABLE (function) = 1; TREE_ADDRESSABLE (function) = 1;
mark_used (function); mark_used (function);
decl_printable_name = thunk_printable_name;
if (current_function_decl) if (current_function_decl)
abort (); abort ();
current_function_decl = thunk_fndecl;
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL); TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
#ifdef ASM_OUTPUT_MI_THUNK #ifdef ASM_OUTPUT_MI_THUNK
current_function_decl = thunk_fndecl;
temporary_allocation (); temporary_allocation ();
assemble_start_function (thunk_fndecl, fnname); assemble_start_function (thunk_fndecl, fnname);
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname); assemble_end_function (thunk_fndecl, fnname);
permanent_allocation (1); permanent_allocation (1);
#else current_function_decl = 0;
save_ofp = flag_omit_frame_pointer; #else /* ASM_OUTPUT_MI_THUNK */
flag_omit_frame_pointer = 1; if (varargs_function_p (function))
init_function_start (thunk_fndecl, input_filename, lineno); cp_error ("generic thunk code does not work for variadic function `%#D'",
pushlevel (0); function);
expand_start_bindings (1);
temporary_allocation ();
/* Start updating where the next arg would go. */
INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX, 0);
stack_args_size.constant = 0;
stack_args_size.var = 0;
/* SETUP for possible structure return address FIXME */
/* Now look through all the parameters, make sure that we
don't clobber any registers used for parameters.
Also, pick up an rtx for the first "this" parameter. */
for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
argp != NULL_TREE;
argp = TREE_CHAIN (argp))
{ {
tree passed_type = TREE_VALUE (argp); tree a, t;
register rtx entry_parm;
int named = 1; /* FIXME */
struct args_size stack_offset;
struct args_size arg_size;
if (passed_type == void_type_node)
break;
if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
&& contains_placeholder_p (TYPE_SIZE (passed_type)))
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
|| FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far,
TYPE_MODE (passed_type),
passed_type, named)
#endif
)
passed_type = build_pointer_type (passed_type);
entry_parm = FUNCTION_ARG (args_so_far,
TYPE_MODE (passed_type),
passed_type,
named);
if (entry_parm != 0)
need_use[need_use_count++] = entry_parm;
locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
#else
entry_parm != 0,
#endif
thunk_fndecl,
&stack_args_size, &stack_offset, &arg_size);
/* REGNO (entry_parm);*/ /* Set up clone argument trees for the thunk. */
if (this_rtx == 0) t = NULL_TREE;
for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
{ {
this_reg_rtx = entry_parm; tree x = copy_node (a);
if (!entry_parm) TREE_CHAIN (x) = t;
{ DECL_CONTEXT (x) = thunk_fndecl;
rtx offset_rtx = ARGS_SIZE_RTX (stack_offset); t = x;
rtx internal_arg_pointer, stack_parm;
if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
|| ! (fixed_regs[ARG_POINTER_REGNUM]
|| ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
else
internal_arg_pointer = virtual_incoming_args_rtx;
if (offset_rtx == const0_rtx)
entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
internal_arg_pointer);
else
entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
gen_rtx (PLUS, Pmode,
internal_arg_pointer,
offset_rtx));
} }
a = nreverse (t);
DECL_ARGUMENTS (thunk_fndecl) = a;
DECL_RESULT (thunk_fndecl) = NULL_TREE;
this_rtx = entry_parm; start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1);
} store_parm_decls ();
FUNCTION_ARG_ADVANCE (args_so_far,
TYPE_MODE (passed_type),
passed_type,
named);
}
fixed_this_rtx = plus_constant (this_rtx, delta);
if (this_rtx != fixed_this_rtx)
emit_move_insn (this_rtx, fixed_this_rtx);
if (this_reg_rtx)
emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx));
emit_indirect_jump (XEXP (DECL_RTL (function), 0));
while (need_use_count > 0)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 1);
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
The call to resume_temporary_allocation near the end of this function
goes back to the usual state of affairs. */
rtl_in_current_obstack ();
insns = get_insns ();
/* Copy any shared structure that should not be shared. */
unshare_all_rtl (insns);
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;
/* Now we choose between stupid (pcc-like) register allocation
(if we got the -noreg switch and not -opt)
and smart register allocation. */
if (optimize > 0) /* Stupid allocation probably won't work */
obey_regdecls = 0; /* if optimizations being done. */
regclass_init ();
regclass (insns, max_reg_num ()); /* Build up the call to the real function. */
if (obey_regdecls) t = build_int_2 (delta, -1 * (delta < 0));
{ TREE_TYPE (t) = signed_type (sizetype);
stupid_life_analysis (insns, max_reg_num (), NULL); t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
failure = reload (insns, 0, NULL); t = tree_cons (NULL_TREE, t, NULL_TREE);
} for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
else t = tree_cons (NULL_TREE, a, t);
{ t = nreverse (t);
/* Do control and data flow analysis, t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
and write some of the results to dump file. */ c_expand_return (t);
flow_analysis (insns, max_reg_num (), NULL); finish_function (lineno, 0, 0);
local_alloc ();
failure = global_alloc (NULL);
} }
reload_completed = 1;
#ifdef LEAF_REGISTERS
leaf_function = 0;
if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
leaf_function = 1;
#endif
/* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG
MACHINE_DEPENDENT_REORG (insns);
#endif
/* Now turn the rtl into assembler code. */
assemble_start_function (thunk_fndecl, fnname);
final (insns, asm_out_file, optimize, 0);
assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
/* Cancel the effect of rtl_in_current_obstack. */
permanent_allocation (1);
flag_omit_frame_pointer = save_ofp;
#endif /* ASM_OUTPUT_MI_THUNK */ #endif /* ASM_OUTPUT_MI_THUNK */
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
decl_printable_name = save_decl_printable_name; TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
current_function_decl = 0;
} }
/* Code for synthesizing methods which have default semantics defined. */ /* Code for synthesizing methods which have default semantics defined. */
......
...@@ -132,6 +132,9 @@ process_template_parm (list, next) ...@@ -132,6 +132,9 @@ process_template_parm (list, next)
error (" a template type parameter must begin with `class' or `typename'"); error (" a template type parameter must begin with `class' or `typename'");
TREE_TYPE (parm) = void_type_node; TREE_TYPE (parm) = void_type_node;
} }
else if (pedantic && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)
cp_pedwarn ("`%T' is not a valid type for a template constant parameter",
TREE_TYPE (parm));
tinfo = make_node (TEMPLATE_CONST_PARM); tinfo = make_node (TEMPLATE_CONST_PARM);
my_friendly_assert (TREE_PERMANENT (tinfo), 260.5); my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);
if (TREE_PERMANENT (parm) == 0) if (TREE_PERMANENT (parm) == 0)
......
...@@ -299,11 +299,9 @@ yylex () ...@@ -299,11 +299,9 @@ yylex ()
case SELFNAME: case SELFNAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype); lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
if (lastiddecl != trrr) if (lastiddecl != trrr)
{
lastiddecl = trrr; lastiddecl = trrr;
if (got_scope) if (got_scope)
tmp_token.yylval.ttype = trrr; tmp_token.yylval.ttype = trrr;
}
break; break;
case IDENTIFIER: case IDENTIFIER:
lastiddecl = trrr; lastiddecl = trrr;
......
...@@ -43,7 +43,7 @@ fast_compare (const char *n1, const char *n2) { ...@@ -43,7 +43,7 @@ fast_compare (const char *n1, const char *n2) {
}; };
bool bool
type_info::before (const type_info &arg) type_info::before (const type_info &arg) const
{ {
return fast_compare (name (), arg.name ()) < 0; return fast_compare (name (), arg.name ()) < 0;
} }
......
...@@ -108,6 +108,8 @@ real_lvalue_p (ref) ...@@ -108,6 +108,8 @@ real_lvalue_p (ref)
return 0; return 0;
} }
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
int int
lvalue_p (ref) lvalue_p (ref)
tree ref; tree ref;
...@@ -2102,3 +2104,16 @@ error_type (arg) ...@@ -2102,3 +2104,16 @@ error_type (arg)
return type; return type;
} }
/* Does FUNCTION use a variable-length argument list? */
int
varargs_function_p (function)
tree function;
{
tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
for (; parm; parm = TREE_CHAIN (parm))
if (TREE_VALUE (parm) == void_type_node)
return 0;
return 1;
}
...@@ -1507,7 +1507,7 @@ decay_conversion (exp) ...@@ -1507,7 +1507,7 @@ decay_conversion (exp)
inner = build1 (CONVERT_EXPR, inner = build1 (CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (inner))), build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
inner); inner);
TREE_REFERENCE_EXPR (inner) = 1; TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
} }
return convert (build_pointer_type (TREE_TYPE (type)), inner); return convert (build_pointer_type (TREE_TYPE (type)), inner);
} }
...@@ -4261,8 +4261,10 @@ build_unary_op (code, xarg, noconvert) ...@@ -4261,8 +4261,10 @@ build_unary_op (code, xarg, noconvert)
argtype = TREE_TYPE (arg); argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE) if (TREE_CODE (argtype) == REFERENCE_TYPE)
{ {
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); arg = build1
TREE_REFERENCE_EXPR (arg) = 1; (CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg; return arg;
} }
else if (pedantic else if (pedantic
...@@ -4283,16 +4285,12 @@ build_unary_op (code, xarg, noconvert) ...@@ -4283,16 +4285,12 @@ build_unary_op (code, xarg, noconvert)
if (arg == current_class_ref) if (arg == current_class_ref)
return current_class_ptr; return current_class_ptr;
/* Keep `default_conversion' from converting if
ARG is of REFERENCE_TYPE. */
arg = TREE_OPERAND (arg, 0); arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{ {
if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg) arg = build1
&& !TREE_SIDE_EFFECTS (DECL_INITIAL (arg))) (CONVERT_EXPR,
arg = DECL_INITIAL (arg); build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1;
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0)); TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
} }
else if (lvalue_p (arg)) else if (lvalue_p (arg))
...@@ -7148,6 +7146,8 @@ c_expand_return (retval) ...@@ -7148,6 +7146,8 @@ c_expand_return (retval)
if (TREE_CODE (whats_returned) == ADDR_EXPR) if (TREE_CODE (whats_returned) == ADDR_EXPR)
whats_returned = TREE_OPERAND (whats_returned, 0); whats_returned = TREE_OPERAND (whats_returned, 0);
} }
if (TREE_CODE (whats_returned) == CONVERT_EXPR)
whats_returned = TREE_OPERAND (whats_returned, 0);
if (TREE_CODE (whats_returned) == ADDR_EXPR) if (TREE_CODE (whats_returned) == ADDR_EXPR)
{ {
whats_returned = TREE_OPERAND (whats_returned, 0); whats_returned = TREE_OPERAND (whats_returned, 0);
......
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