91th Cygnus<->FSF merge

From-SVN: r13971
This commit is contained in:
Mike Stump 1997-04-23 22:39:53 +00:00
parent 2ec43107c9
commit eb66be0e6c
18 changed files with 740 additions and 1000 deletions

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@ tinfo2.o: cc1plus $(srcdir)/cp/tinfo2.cc
-c $(srcdir)/cp/tinfo2.cc
exception.o: cc1plus $(srcdir)/cp/exception.cc
$(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
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new.cc

View File

@ -3187,13 +3187,18 @@ reference_binding (rto, rfrom, expr, flags)
int lvalue = 1;
tree to = TREE_TYPE (rto);
tree from = rfrom;
int related;
if (TREE_CODE (from) == REFERENCE_TYPE)
from = TREE_TYPE (from);
else if (! expr || ! real_lvalue_p (expr))
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_VOLATILE (to) >= TYPE_VOLATILE (from))
{
@ -3201,14 +3206,11 @@ reference_binding (rto, rfrom, expr, flags)
if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from))
conv = build_conv (REF_BIND, rto, conv);
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from))
else
{
conv = build_conv (REF_BIND, rto, conv);
ICS_STD_RANK (conv) = STD_RANK;
}
else
conv = NULL_TREE;
}
else
conv = NULL_TREE;
@ -3225,8 +3227,15 @@ reference_binding (rto, rfrom, expr, flags)
if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV)
TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
}
if (conv && ! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
&& (flags & LOOKUP_NO_TEMP_BIND) == 0))
if (conv
&& ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
&& (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;
}
@ -3265,7 +3274,12 @@ implicit_conversion (to, from, expr, flags)
|| IS_AGGR_TYPE (non_reference (to)))
&& (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_VOLATILE (TREE_TYPE (to))
&& (flags & LOOKUP_NO_TEMP_BIND) == 0)
@ -3275,13 +3289,6 @@ implicit_conversion (to, from, expr, flags)
if (cand)
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;
@ -4181,7 +4188,10 @@ print_z_candidates (candidates)
}
/* 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 *
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))
{
tree fn = TREE_VALUE (convs);
tree ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (fn)), 0, LOOKUP_NO_CONVERSION);
if (ics)
int convflags = LOOKUP_NO_CONVERSION;
tree 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))
{
candidates = add_function_candidate (candidates, fn, args, flags);
@ -4348,9 +4371,10 @@ build_new_function_call (fn, args, obj)
{
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
else
cp_error ("no matching function for call to `%D (%A)'",
TREE_PURPOSE (fn), args);
cp_error ("no matching function for call to `%D (%A)'",
TREE_PURPOSE (fn), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
@ -5037,11 +5061,12 @@ build_over_call (fn, convs, args, flags)
is_method = 1;
}
for (; conv = TREE_VEC_ELT (convs, i), arg && parm;
for (; arg && parm;
parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
{
tree type = TREE_VALUE (parm);
conv = TREE_VEC_ELT (convs, i);
if (ICS_BAD_FLAG (conv))
{
tree t = conv;
@ -5118,17 +5143,24 @@ build_over_call (fn, convs, args, flags)
&& TREE_VEC_LENGTH (convs) == 1
&& copy_args_p (fn))
{
tree targ = NULL_TREE;
tree targ;
arg = TREE_VALUE (TREE_CHAIN (converted_args));
/* Pull out the real argument, disregarding const-correctness. */
if (TREE_CODE (arg) == ADDR_EXPR)
targ = arg;
while (TREE_CODE (targ) == NOP_EXPR
|| 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 (arg, 0);
targ = TREE_OPERAND (targ, 0);
if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1))
targ = NULL_TREE;
}
else
targ = NULL_TREE;
if (targ)
arg = targ;

View File

@ -2809,6 +2809,7 @@ check_for_override (decl, ctype)
}
virtualp = 1;
#if 0 /* The signature of an overriding function is not changed. */
{
/* The argument types may have changed... */
tree type = TREE_TYPE (decl);
@ -2823,9 +2824,10 @@ check_for_override (decl, ctype)
if (raises)
type = build_exception_variant (type, raises);
TREE_TYPE (decl) = type;
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
}
#endif
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
break;
}
}

View File

@ -1195,10 +1195,12 @@ extern int flag_new_for_scope;
#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
&& CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
#if 0
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
Used to generate more helpful error message in case somebody
tries to take its address. */
#define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE))
#endif
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))

View File

@ -371,232 +371,24 @@ convert_to_pointer_force (type, expr)
value we have to begin with is in ARG.
FLAGS controls how we manage access checking.
DIRECT_BIND in FLAGS controls how any temporarys are generated.
CHECKCONST controls if we report error messages on const subversion. */
DIRECT_BIND in FLAGS controls how any temporaries are generated. */
static tree
build_up_reference (type, arg, flags, checkconst)
tree type, arg;
int flags, checkconst;
{
tree rval, targ;
int literal_flag = 0;
tree rval;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
tree binfo = NULL_TREE;
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. */
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))
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
tree targ = arg;
if (toplevel_bindings_p ())
{
arg = get_temp_name (argtype, 1);
literal_flag = 1;
}
arg = get_temp_name (argtype, 1);
else
{
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
@ -605,7 +397,7 @@ build_up_reference (type, arg, flags, checkconst)
DECL_INITIAL (arg) = targ;
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);
arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
@ -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
address, transform all occurrences of the register, into a memory
reference we could win better. */
mark_addressable (arg);
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)
rval = convert_pointer_to (target_type, rval);
else
rval
= convert_to_pointer_force (build_pointer_type (target_type), rval);
TREE_TYPE (rval) = type;
if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR)
TREE_TYPE (TREE_OPERAND (rval, 0))
= TREE_TYPE (TREE_OPERAND (rval, 1)) = type;
}
TREE_CONSTANT (rval) = literal_flag;
rval = build_unary_op (ADDR_EXPR, arg, 1);
if (flags & LOOKUP_PROTECT)
rval = convert_pointer_to (target_type, rval);
else
rval
= convert_to_pointer_force (build_pointer_type (target_type), rval);
rval = build1 (CONVERT_EXPR, type, rval);
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
return rval;
}

View File

@ -49,8 +49,6 @@ extern struct obstack permanent_obstack;
extern int current_class_depth;
extern tree cleanups_this_call;
extern tree static_ctors, static_dtors;
/* Stack of places to restore the search obstack back to. */
@ -5012,6 +5010,18 @@ init_decl_processing ()
BUILT_IN_NEXT_ARG, NULL_PTR);
builtin_function ("__builtin_args_info", int_ftype_int,
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. */
builtin_function ("__builtin_apply_args", ptr_ftype,
@ -6569,11 +6579,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
}
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
end of the binding contour. It may need a cleanup. */
@ -6654,9 +6659,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
}
}
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
expand_start_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node)
{
@ -6679,11 +6682,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
}
/* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
expand_end_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node)
{
@ -6777,11 +6778,6 @@ expand_static_init (decl, init)
/* Emit code to perform this initialization but once. */
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. */
push_obstacks (&permanent_obstack, &permanent_obstack);
@ -6790,11 +6786,7 @@ expand_static_init (decl, init)
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node, 1), 0);
old_cleanups = cleanups_this_call;
old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
expand_start_target_temps ();
expand_assignment (temp, integer_one_node, 0, 0);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
@ -6807,10 +6799,7 @@ expand_static_init (decl, init)
expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
expand_end_target_temps ();
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
@ -9195,9 +9184,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (! friendp
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| ! (funcdef_flag < 0 || inlinep));
publicp = (! friendp || ! staticp);
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, publicp, inlinep,
@ -9395,11 +9382,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type));
/* Record presence of `static'. In C++, `inline' implies `static'. */
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| (!RIDBIT_SETP (RID_STATIC, specbits)
&& !RIDBIT_SETP (RID_INLINE, specbits)));
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals, raises, attrlist,
@ -11281,6 +11267,7 @@ store_parm_decls ()
register tree fndecl = current_function_decl;
register tree parm;
int parms_have_cleanups = 0;
tree cleanups = NULL_TREE;
/* This is either a chain of PARM_DECLs (when a prototype is used). */
tree specparms = current_function_parms;
@ -11355,10 +11342,10 @@ store_parm_decls ()
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
if (! expand_decl_cleanup (parm, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
parm);
parms_have_cleanups = 1;
/* Keep track of the cleanups. */
cleanups = tree_cons (parm, cleanup, cleanups);
}
}
else
@ -11392,6 +11379,20 @@ store_parm_decls ()
if (! processing_template_decl)
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
cleanup-generated temporaries. Also, if the return value needs or
has initialization, deal with that now. */
@ -12329,9 +12330,6 @@ maybe_build_cleanup_1 (decl, auto_delete)
rval = build_compound_expr (tree_cons (NULL_TREE, rval,
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)
resume_momentary (temp);
@ -12372,20 +12370,15 @@ void
cplus_expand_expr_stmt (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)
{
add_tree (build_min_nt (EXPR_STMT, exp));
return;
}
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
if (TREE_TYPE (exp) == unknown_type_node)
{
if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
@ -12415,16 +12408,7 @@ cplus_expand_expr_stmt (exp)
/* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */
expand_cleanups_to (old_cleanups);
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 ();
expand_end_target_temps ();
}
/* When a stmt has been parsed, this function is called.

View File

@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
extern tree get_file_function_name ();
extern tree cleanups_this_call;
static void grok_function_init PROTO((tree, tree));
void import_export_decl ();
extern int current_class_depth;
@ -420,7 +419,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
{"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
@ -2919,15 +2917,8 @@ finish_file ()
while (vars)
{
extern int temp_slot_level;
extern int target_temp_slot_level;
tree decl = TREE_VALUE (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,
then don't initialize it here. Also, don't bother
@ -2940,9 +2931,9 @@ finish_file ()
if (TREE_CODE (decl) == VAR_DECL)
{
int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
|| DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl)));
int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
|| DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl)));
/* Set these global variables so that GDB at least puts
us near the declaration which required the initialization. */
@ -2964,6 +2955,8 @@ finish_file ()
expand_start_cond (sentry, 0);
}
expand_start_target_temps ();
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0);
@ -2977,6 +2970,9 @@ finish_file ()
else
expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */
expand_end_target_temps ();
if (protect)
expand_end_cond ();
@ -2987,13 +2983,7 @@ finish_file ()
;
else my_friendly_abort (22);
/* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups);
next_mess:
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
vars = TREE_CHAIN (vars);
}

View File

@ -35,12 +35,12 @@ Boston, MA 02111-1307, USA. */
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;
/* 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;
@ -163,18 +163,17 @@ extern rtx gen_nop PROTO(());
/* local globals for function calls
====================================================================== */
/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
"set_unexpected ()" after default_conversion. (lib-except.c) */
/* Used to cache "terminate", "unexpected", "set_terminate", and
"set_unexpected" after default_conversion. (lib-except.c) */
static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
/* used to cache __find_first_exception_table_match ()
for throw (lib-except.c) */
/* Used to cache __find_first_exception_table_match for throw. */
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;
/* holds a ready to emit call to "terminate ()". */
/* Holds a ready to emit call to "terminate". */
static tree TerminateFunctionCall;
static tree empty_fndecl;
@ -245,8 +244,8 @@ init_exception_processing ()
tree PFV = build_pointer_type (build_function_type
(void_type_node, void_list_node));
/* arg list for the build_function_type call for set_terminate () and
set_unexpected () */
/* Arg list for the build_function_type call for set_terminate and
set_unexpected. */
tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
/* void (*pfvtype (void (*) ()))() */
@ -343,6 +342,10 @@ init_exception_processing ()
DECL_COMMON (d) = 1;
cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 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
@ -448,6 +451,8 @@ expand_start_catch_block (declspecs, declarator)
false_label_rtx = gen_label_rtx ();
push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
emit_line_note (input_filename, lineno);
if (declspecs)
{
tree exp;
@ -460,8 +465,11 @@ expand_start_catch_block (declspecs, declarator)
{
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 ();
return;
}
@ -513,11 +521,17 @@ expand_start_catch_block (declspecs, declarator)
emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
/* Because we are reordered out of line, we arrange
to rethrow in the outer context, should we encounter
an exception in the catch handler.
/* If we are not doing setjmp/longjmp EH, because we are reordered
out of line, we arrange to rethrow in the outer context so as to
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 ();
emit_line_note (input_filename, lineno);
@ -539,23 +553,42 @@ expand_end_catch_block ()
if (! doing_eh (1))
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);
TREE_TYPE (t) = void_type_node;
RTL_EXPR_RTL (t) = const0_rtx;
TREE_SIDE_EFFECTS (t) = 1;
start_sequence_for_rtl_expr (t);
expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
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)));
}
RTL_EXPR_SEQUENCE (t) = get_insns ();
end_sequence ();
/* Matches the start in expand_start_catch_block (). */
/* Matches the start in expand_start_catch_block. */
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 ();
/* Cleanup the EH parameter. */
@ -580,7 +613,7 @@ do_unwind (inner_throw_label)
rtx return_val_rtx;
rtx temp;
/* call to __builtin_return_address () */
/* Call to __builtin_return_address. */
params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
@ -633,7 +666,7 @@ do_unwind (inner_throw_label)
#if 0
/* 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);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
@ -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.
expands "throw" as the following pseudo code:
@ -731,7 +764,7 @@ expand_builtin_throw ()
/* code to deal with unwinding and looking for it again */
emit_label (gotta_rethrow_it);
/* call to __builtin_return_address () */
/* Call to __builtin_return_address. */
#if defined (ARM_FRAME_RTX) /* was __arm */
/* This should be moved into arm.h:RETURN_ADDR_RTX */
/* This replaces a 'call' to __builtin_return_address */
@ -743,7 +776,7 @@ expand_builtin_throw ()
return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
#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,
GET_MODE (return_val_rtx), 0, 0);
@ -837,6 +870,7 @@ expand_end_eh_spec (raises)
do_function_call (Unexpected, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Unexpected, 0));
emit_barrier ();
expand_eh_region_end (second_try);
emit_label (check);
@ -890,7 +924,6 @@ expand_exception_blocks ()
funcend = gen_label_rtx ();
emit_jump (funcend);
/* expand_null_return (); */
start_sequence ();
@ -931,12 +964,22 @@ expand_exception_blocks ()
if (insns)
{
/* Is this necessary? */
assemble_external (TREE_OPERAND (Terminate, 0));
/* 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? */
assemble_external (TREE_OPERAND (Terminate, 0));
expand_eh_region_start ();
}
expand_eh_region_start ();
emit_insns (insns);
expand_eh_region_end (TerminateFunctionCall);
if (exceptions_via_longjmp == 0)
expand_eh_region_end (TerminateFunctionCall);
expand_leftover_cleanups ();
}
@ -1125,13 +1168,18 @@ expand_throw (exp)
/* This part is easy, as we don't have to do anything else. */
}
/* 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
exception, so that the matching routine knows to search out. */
label = gen_label_rtx ();
emit_label (label);
if (exceptions_via_longjmp)
emit_throw ();
else
{
/* 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
exception, so that the matching routine knows to search out. */
label = gen_label_rtx ();
emit_label (label);
expand_internal_throw (label);
expand_internal_throw (label);
}
}
/* Build a throw expression. */

View File

@ -30,22 +30,23 @@
#include "typeinfo"
#include "exception"
/* terminate (), unexpected (), set_terminate (), set_unexpected () as
well as the default terminate func and default unexpected func */
/* Define terminate, unexpected, set_terminate, set_unexpected as
well as the default terminate func and default unexpected func. */
extern terminate_handler __terminate_func;
void
__default_terminate ()
terminate ()
{
abort ();
__terminate_func ();
}
void
__default_unexpected ()
{
__default_terminate ();
terminate ();
}
static terminate_handler __terminate_func = __default_terminate;
static unexpected_handler __unexpected_func = __default_unexpected;
terminate_handler
@ -66,12 +67,6 @@ set_unexpected (unexpected_handler func)
return old;
}
void
terminate ()
{
__terminate_func ();
}
void
unexpected ()
{

View File

@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
#include "except.h"
/* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST
@ -39,8 +40,6 @@ Boston, MA 02111-1307, USA. */
line. Perhaps this was not intended. */
tree current_base_init_list, current_member_init_list;
extern tree cleanups_this_call;
void emit_base_init ();
void check_base_init ();
static void expand_aggr_vbase_init ();
@ -153,13 +152,8 @@ perform_member_init (member, name, init, explicit)
{
tree decl;
tree type = TREE_TYPE (member);
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;
expand_start_target_temps ();
if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
@ -219,15 +213,8 @@ perform_member_init (member, name, init, explicit)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
}
expand_cleanups_to (old_cleanups);
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);
}
expand_end_target_temps ();
free_temp_slots ();
if (TYPE_NEEDS_DESTRUCTOR (type))
@ -589,27 +576,14 @@ emit_base_init (t, immediately)
if (init != void_list_node)
{
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;
expand_start_target_temps ();
member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
expand_cleanups_to (old_cleanups);
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);
}
expand_end_target_temps ();
free_temp_slots ();
}
@ -796,28 +770,14 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR);
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;
expand_start_target_temps ();
if (init)
init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (old_cleanups);
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);
}
expand_end_target_temps ();
free_temp_slots ();
}
@ -3109,20 +3069,22 @@ expand_vec_init (decl, base, maxindex, init, from_array)
push_obstacks_nochange ();
resume_temporary_allocation ();
{
tree e1, e2 = make_node (RTL_EXPR);
TREE_TYPE (e2) = void_type_node;
RTL_EXPR_RTL (e2) = const0_rtx;
TREE_SIDE_EFFECTS (e2) = 1;
start_sequence_for_rtl_expr (e2);
tree e1, cleanup = make_node (RTL_EXPR);
TREE_TYPE (cleanup) = void_type_node;
RTL_EXPR_RTL (cleanup) = const0_rtx;
TREE_SIDE_EFFECTS (cleanup) = 1;
start_sequence_for_rtl_expr (cleanup);
e1 = build_array_eh_cleanup
(rval,
build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
type);
expand_expr (e1, const0_rtx, VOIDmode, 0);
RTL_EXPR_SEQUENCE (e2) = get_insns ();
RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
end_sequence ();
expand_eh_region_end (e2);
cleanup = protect_with_terminate (cleanup);
expand_eh_region_end (cleanup);
}
pop_obstacks ();
}

View File

@ -70,8 +70,6 @@ Boston, MA 02111-1307, USA. */
"-fno-repo",
"-fsave-memoized",
"-fno-save-memoized",
"-fshort-temps",
"-fno-short-temps",
"-fstats",
"-fno-stats",
"-fstrict-prototype",

View File

@ -1698,7 +1698,7 @@ make_thunk (function, delta)
}
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)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
@ -1719,27 +1719,9 @@ void
emit_thunk (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);
int delta = THUNK_DELTA (thunk_fndecl);
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))
return;
@ -1749,203 +1731,58 @@ emit_thunk (thunk_fndecl)
TREE_ADDRESSABLE (function) = 1;
mark_used (function);
decl_printable_name = thunk_printable_name;
if (current_function_decl)
abort ();
current_function_decl = thunk_fndecl;
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
#ifdef ASM_OUTPUT_MI_THUNK
current_function_decl = thunk_fndecl;
temporary_allocation ();
assemble_start_function (thunk_fndecl, fnname);
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname);
permanent_allocation (1);
#else
save_ofp = flag_omit_frame_pointer;
flag_omit_frame_pointer = 1;
init_function_start (thunk_fndecl, input_filename, lineno);
pushlevel (0);
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);
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);*/
if (this_rtx == 0)
{
this_reg_rtx = entry_parm;
if (!entry_parm)
{
rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
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));
}
this_rtx = entry_parm;
}
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 ());
if (obey_regdecls)
{
stupid_life_analysis (insns, max_reg_num (), NULL);
failure = reload (insns, 0, NULL);
}
else
{
/* Do control and data flow analysis,
and write some of the results to dump file. */
flow_analysis (insns, max_reg_num (), NULL);
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 */
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
decl_printable_name = save_decl_printable_name;
current_function_decl = 0;
#else /* ASM_OUTPUT_MI_THUNK */
if (varargs_function_p (function))
cp_error ("generic thunk code does not work for variadic function `%#D'",
function);
{
tree a, t;
/* Set up clone argument trees for the thunk. */
t = NULL_TREE;
for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
{
tree x = copy_node (a);
TREE_CHAIN (x) = t;
DECL_CONTEXT (x) = thunk_fndecl;
t = x;
}
a = nreverse (t);
DECL_ARGUMENTS (thunk_fndecl) = a;
DECL_RESULT (thunk_fndecl) = NULL_TREE;
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1);
store_parm_decls ();
/* Build up the call to the real function. */
t = build_int_2 (delta, -1 * (delta < 0));
TREE_TYPE (t) = signed_type (sizetype);
t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
t = tree_cons (NULL_TREE, t, NULL_TREE);
for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
t = tree_cons (NULL_TREE, a, t);
t = nreverse (t);
t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
c_expand_return (t);
finish_function (lineno, 0, 0);
}
#endif /* ASM_OUTPUT_MI_THUNK */
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
/* Code for synthesizing methods which have default semantics defined. */

View File

@ -132,6 +132,9 @@ process_template_parm (list, next)
error (" a template type parameter must begin with `class' or `typename'");
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);
my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);
if (TREE_PERMANENT (parm) == 0)

View File

@ -299,11 +299,9 @@ yylex ()
case SELFNAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
if (lastiddecl != trrr)
{
lastiddecl = trrr;
if (got_scope)
tmp_token.yylval.ttype = trrr;
}
lastiddecl = trrr;
if (got_scope)
tmp_token.yylval.ttype = trrr;
break;
case IDENTIFIER:
lastiddecl = trrr;

View File

@ -43,7 +43,7 @@ fast_compare (const char *n1, const char *n2) {
};
bool
type_info::before (const type_info &arg)
type_info::before (const type_info &arg) const
{
return fast_compare (name (), arg.name ()) < 0;
}

View File

@ -108,6 +108,8 @@ real_lvalue_p (ref)
return 0;
}
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
int
lvalue_p (ref)
tree ref;
@ -2102,3 +2104,16 @@ error_type (arg)
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;
}

View File

@ -1507,7 +1507,7 @@ decay_conversion (exp)
inner = build1 (CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (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);
}
@ -4261,8 +4261,10 @@ build_unary_op (code, xarg, noconvert)
argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1;
arg = build1
(CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
else if (pedantic
@ -4283,16 +4285,12 @@ build_unary_op (code, xarg, noconvert)
if (arg == current_class_ref)
return current_class_ptr;
/* Keep `default_conversion' from converting if
ARG is of REFERENCE_TYPE. */
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
&& !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
arg = DECL_INITIAL (arg);
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1;
arg = build1
(CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
else if (lvalue_p (arg))
@ -7148,6 +7146,8 @@ c_expand_return (retval)
if (TREE_CODE (whats_returned) == ADDR_EXPR)
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)
{
whats_returned = TREE_OPERAND (whats_returned, 0);