Commit f30432d7 by Mike Stump

75th Cygnus<->FSF merge

From-SVN: r10438
parent c3583620
......@@ -156,6 +156,55 @@ convert_harshness (type, parmtype, parm)
if (coder == ERROR_MARK)
return EVIL_RETURN (h);
if (codel == REFERENCE_TYPE)
{
tree ttl, ttr;
int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
: TYPE_VOLATILE (parmtype));
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
ttl = TREE_TYPE (type);
/* Only allow const reference binding if we were given a parm to deal
with, since it isn't really a conversion. This is a hack to
prevent build_type_conversion from finding this conversion, but
still allow overloading to find it. */
if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
return EVIL_RETURN (h);
if (TYPE_READONLY (ttl) < constp
|| TYPE_VOLATILE (ttl) < volatilep)
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
little, so a non-const reference is preferred over this one. */
penalty = ((TYPE_READONLY (ttl) > constp)
+ (TYPE_VOLATILE (ttl) > volatilep));
ttl = TYPE_MAIN_VARIANT (ttl);
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
ttr = intype;
/* Maybe handle conversion to base here? */
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
h.code = QUAL_CODE;
h.int_penalty = penalty;
}
return h;
}
if (codel == POINTER_TYPE && fntype_p (parmtype))
{
tree p1, p2;
......@@ -198,7 +247,7 @@ convert_harshness (type, parmtype, parm)
/* We allow the default conversion between function type
and pointer-to-function type for free. */
if (type == parmtype)
if (comptypes (type, parmtype, 1))
return h;
if (pedantic)
......@@ -421,10 +470,21 @@ convert_harshness (type, parmtype, parm)
}
/* Convert arrays which have not previously been converted. */
#if 0
if (codel == ARRAY_TYPE)
codel = POINTER_TYPE;
#endif
if (coder == ARRAY_TYPE)
coder = POINTER_TYPE;
{
coder = POINTER_TYPE;
if (parm)
{
parm = decay_conversion (parm);
parmtype = TREE_TYPE (parm);
}
else
parmtype = build_pointer_type (TREE_TYPE (parmtype));
}
/* Conversions among pointers */
if (codel == POINTER_TYPE && coder == POINTER_TYPE)
......@@ -462,7 +522,7 @@ convert_harshness (type, parmtype, parm)
ttr = unsigned_type (ttr);
penalty = 10;
}
if (comp_target_types (ttl, ttr, 0) <= 0)
if (comp_target_types (type, parmtype, 1) <= 0)
return EVIL_RETURN (h);
}
#else
......@@ -559,54 +619,6 @@ convert_harshness (type, parmtype, parm)
&& IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
return ZERO_RETURN (h);
if (codel == REFERENCE_TYPE)
{
tree ttl, ttr;
int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
: TYPE_VOLATILE (parmtype));
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
ttl = TREE_TYPE (type);
/* Only allow const reference binding if we were given a parm to deal
with, since it isn't really a conversion. This is a hack to
prevent build_type_conversion from finding this conversion, but
still allow overloading to find it. */
if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
return EVIL_RETURN (h);
if (TYPE_READONLY (ttl) < constp
|| TYPE_VOLATILE (ttl) < volatilep)
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
little, so a non-const reference is preferred over this one. */
penalty = ((TYPE_READONLY (ttl) > constp)
+ (TYPE_VOLATILE (ttl) > volatilep));
ttl = TYPE_MAIN_VARIANT (ttl);
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
ttr = intype;
/* Maybe handle conversion to base here? */
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
h.code = QUAL_CODE;
h.int_penalty = penalty;
}
return h;
}
if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{
int b_or_d = get_base_distance (type, parmtype, 0, 0);
......@@ -625,6 +637,9 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h);
}
/* A clone of build_type_conversion for checking user-defined conversions in
overload resolution. */
int
user_harshness (type, parmtype, parm)
register tree type, parmtype;
......@@ -1766,7 +1781,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
basetype = SIGNATURE_TYPE (basetype);
instance_ptr = build_optr_ref (instance);
instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
basetype_path = TYPE_BINFO (basetype);
}
else
......@@ -1788,7 +1803,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
within the scope of this function. */
if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
need_vtbl = maybe_needed;
instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);
}
else
{
......@@ -1883,7 +1898,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype = inst_ptr_basetype;
else
{
instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
......@@ -1999,40 +2014,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
}
if (flag_this_is_variable > 0)
{
constp = 0;
volatilep = 0;
instance_ptr = build_int_2 (0, 0);
TREE_TYPE (instance_ptr) = TYPE_POINTER_TO (basetype);
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
else
{
constp = 0;
volatilep = 0;
instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0);
if (instance_ptr == error_mark_node)
return error_mark_node;
instance_ptr = save_expr (instance_ptr);
TREE_CALLS_NEW (instance_ptr) = 1;
instance = build_indirect_ref (instance_ptr, NULL_PTR);
#if 0
/* This breaks initialization of a reference from a new
expression of a different type. And it doesn't appear to
serve its original purpose any more, either. jason 10/12/94 */
/* If it's a default argument initialized from a ctor, what we get
from instance_ptr will match the arglist for the FUNCTION_DECL
of the constructor. */
if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR
&& TREE_OPERAND (TREE_VALUE (parms), 1)
&& TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
parms = build_tree_list (NULL_TREE, instance_ptr);
else
#endif
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
constp = 0;
volatilep = 0;
instance_ptr = build_int_2 (0, 0);
TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
......@@ -2385,9 +2371,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
else if (ever_seen > 1)
{
TREE_CHAIN (last) = void_list_node;
cp_error ("no matching function for call to `%T::%D (%A)'",
TREE_TYPE (TREE_TYPE (instance_ptr)),
name, TREE_CHAIN (parmtypes));
cp_error ("no matching function for call to `%T::%D (%A)%V'",
TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))),
name, TREE_CHAIN (parmtypes),
TREE_TYPE (TREE_TYPE (instance_ptr)));
TREE_CHAIN (last) = NULL_TREE;
print_candidates (found_fns);
}
......@@ -2486,7 +2473,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
&& ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
cp_pedwarn ("inline function `%#D' called before definition", function);
cp_warning ("inline function `%#D' called before definition", function);
fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == POINTER_TYPE)
......
......@@ -35,6 +35,15 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected
from being evaluated more than once should be reset so that a new
expand_expr call of this expr will cause those to be re-evaluated.
This is useful when we want to reuse a tree in different places,
but where we must re-expand. */
DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
/* Value is reference to particular overloaded class method.
Operand 0 is the class name (an IDENTIFIER_NODE);
operand 1 is the field (also an IDENTIFIER_NODE).
......
......@@ -450,11 +450,12 @@ struct lang_type
unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
/* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */
unsigned dummy : 20;
unsigned dummy : 19;
unsigned n_vancestors : 16;
} type_flags;
......@@ -1054,6 +1055,9 @@ struct lang_decl
class where a virtual function instance is actually defined, and the
lexical scope of a friend function defined in a class body. */
#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
#define DECL_REAL_CONTEXT(NODE) \
((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \
? DECL_CLASS_CONTEXT (NODE) : DECL_CONTEXT (NODE))
/* For a FUNCTION_DECL: the chain through which the next method
in the method chain is found. We now use TREE_CHAIN to
......@@ -1068,7 +1072,7 @@ struct lang_decl
#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
/* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed (local) variable. */
this is the shadowed variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
/* Points back to the decl which caused this lang_decl to be allocated. */
......@@ -1218,6 +1222,13 @@ extern int flag_new_for_scope;
#define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE))
#endif
/* Nonzero means that an object of this type can not be initialized using
an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \
(TYPE_LANG_SPECIFIC (NODE)->type_flags.non_aggregate)
#define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if there is a user-defined X::op=(x&) for this class. */
#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
......@@ -1953,6 +1964,7 @@ extern int root_lang_context_p PROTO((void));
extern tree instantiate_type PROTO((tree, tree, int));
extern void print_class_statistics PROTO((void));
extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
......@@ -2030,7 +2042,7 @@ extern void cp_finish_decl PROTO((tree, tree, tree, int, int));
extern void expand_static_init PROTO((tree, tree));
extern int complete_array_type PROTO((tree, tree, int));
extern tree build_ptrmemfunc_type PROTO((tree));
extern tree grokdeclarator (); /* PROTO((tree, tree, enum decl_context, int, tree)); */
/* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PROTO((tree));
extern tree xref_tag PROTO((tree, tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
......@@ -2038,8 +2050,10 @@ extern tree start_enum PROTO((tree));
extern tree finish_enum PROTO((tree, tree));
extern tree build_enumerator PROTO((tree, tree));
extern tree grok_enum_decls PROTO((tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern int start_function PROTO((tree, tree, tree, tree, int));
extern void store_parm_decls PROTO((void));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_in_parms PROTO((struct rtx_def *));
extern void store_return_init PROTO((tree, tree));
extern void finish_function PROTO((int, int, int));
extern tree start_method PROTO((tree, tree, tree));
......@@ -2059,8 +2073,8 @@ extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int));
extern void check_classfn PROTO((tree, tree, tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree));
extern tree check_classfn PROTO((tree, tree, tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree));
extern tree grokoptypename PROTO((tree, tree));
......@@ -2093,6 +2107,7 @@ extern tree do_toplevel_using_decl PROTO((tree));
extern tree do_class_using_decl PROTO((tree));
extern tree current_namespace_id PROTO((tree));
extern tree get_namespace_id PROTO((void));
extern void check_default_args PROTO((tree));
/* in edsel.c */
......@@ -2113,12 +2128,16 @@ extern int might_have_exceptions_p PROTO((void));
extern void emit_exception_table PROTO((void));
extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void));
extern void expand_builtin_throw PROTO((void));
extern void expand_start_eh_spec PROTO((void));
extern void expand_end_eh_spec PROTO((tree));
/* in expr.c */
/* skip cplus_expand_expr */
extern void init_cplus_expand PROTO((void));
extern void fixup_result_decl PROTO((tree, struct rtx_def *));
extern int decl_in_memory_p PROTO((tree));
extern tree unsave_expr_now PROTO((tree));
/* in gc.c */
extern int type_needs_gc_entry PROTO((tree));
......@@ -2232,6 +2251,7 @@ extern char *code_as_string PROTO((enum tree_code, int));
extern char *language_as_string PROTO((enum languages, int));
extern char *parm_as_string PROTO((int, int));
extern char *op_as_string PROTO((enum tree_code, int));
extern char *cv_as_string PROTO((tree, int));
/* in method.c */
extern void init_method PROTO((void));
......@@ -2367,13 +2387,15 @@ extern int promotes_to_aggr_type PROTO((tree, enum tree_code));
extern int is_aggr_type_2 PROTO((tree, tree));
extern void message_2_types PROTO((void (*)(), char *, tree, tree));
extern char *lang_printable_name PROTO((tree));
extern tree build_exception_variant PROTO((tree, tree, tree));
extern tree build_exception_variant PROTO((tree, tree));
extern tree copy_to_permanent PROTO((tree));
extern void print_lang_statistics PROTO((void));
/* skip __eprintf */
extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree));
extern tree break_out_target_exprs PROTO((tree));
extern tree build_unsave_expr PROTO((tree));
extern int cp_expand_decl_cleanup PROTO((tree, tree));
/* in typeck.c */
extern tree condition_conversion PROTO((tree));
......@@ -2397,6 +2419,7 @@ extern tree signed_or_unsigned_type PROTO((int, tree));
extern tree c_sizeof PROTO((tree));
extern tree c_sizeof_nowarn PROTO((tree));
extern tree c_alignof PROTO((tree));
extern tree decay_conversion PROTO((tree));
extern tree default_conversion PROTO((tree));
extern tree build_object_ref PROTO((tree, tree, tree));
extern tree build_component_ref_1 PROTO((tree, tree, int));
......
......@@ -180,6 +180,15 @@ cp_convert_to_pointer (type, expr)
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
|| (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
}
return build1 (NOP_EXPR, type, expr);
}
......@@ -904,7 +913,7 @@ convert_to_aggr (type, expr, msgp, protect)
/* The type of the first argument will be filled in inside the loop. */
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
#if 0
method_name = build_decl_overload (name, parmtypes, 1);
......@@ -1164,32 +1173,6 @@ convert_pointer_to (binfo, expr)
type = binfo;
return convert_pointer_to_real (type, expr);
}
/* Same as above, but don't abort if we get an "ambiguous" baseclass.
There's only one virtual baseclass we are looking for, and once
we find one such virtual baseclass, we have found them all. */
tree
convert_pointer_to_vbase (binfo, expr)
tree binfo;
tree expr;
{
tree intype = TREE_TYPE (TREE_TYPE (expr));
tree binfos = TYPE_BINFO_BASETYPES (intype);
int i;
for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (BINFO_TYPE (binfo) == basetype)
return convert_pointer_to (binfo, expr);
if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))
return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));
}
my_friendly_abort (6);
/* NOTREACHED */
return NULL_TREE;
}
/* Conversion...
......@@ -1374,44 +1357,7 @@ cp_convert (type, expr, convtype, flags)
return conversion;
else if (ctor)
{
if (current_function_decl)
/* We can't pass 1 to the with_cleanup_p arg here, because that
screws up passing classes by value. */
ctor = build_cplus_new (type, ctor, 0);
else
{
register tree parm = TREE_OPERAND (ctor, 1);
/* Initializers for static variables and parameters
have to handle doing the initialization and
cleanup themselves. */
my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322);
#if 0
/* The following assertion fails in cases where we
are initializing a static member variable of a
particular instance of a template class with a
call to a constructor of the given instance, as
in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do
the same thing for a static member of a
non-template class, as in:
T object = T();
I can't see why we should care here whether or not
the initializer expression involves a call to
`new', so for the time being, it seems best to
just avoid doing this assertion. */
my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)),
323);
#endif
TREE_VALUE (parm) = NULL_TREE;
ctor = build_indirect_ref (ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (ctor) = 1;
}
ctor = build_cplus_new (type, ctor, 0);
return ctor;
}
}
......@@ -1524,7 +1470,14 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
If (FOR_SURE & 1) is non-zero, then we allow this type conversion
to take place immediately. Otherwise, we build a SAVE_EXPR
which can be evaluated if the results are ever needed. */
which can be evaluated if the results are ever needed.
Changes to this functions should be mirrored in user_harshness.
FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */
tree
build_type_conversion (code, xtype, expr, for_sure)
......@@ -1604,10 +1557,9 @@ build_expr_type_conversion (desires, expr, complain)
tree winner = NULL_TREE;
if (TREE_CODE (basetype) == OFFSET_TYPE)
{
expr = resolve_offset_ref (expr);
basetype = TREE_TYPE (expr);
}
expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
if (! IS_AGGR_TYPE (basetype))
switch (TREE_CODE (basetype))
......@@ -1641,11 +1593,16 @@ build_expr_type_conversion (desires, expr, complain)
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
int win = 0;
tree candidate;
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
continue;
switch (TREE_CODE (TREE_VALUE (conv)))
candidate = TREE_VALUE (conv);
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
switch (TREE_CODE (candidate))
{
case BOOLEAN_TYPE:
case INTEGER_TYPE:
......@@ -1817,8 +1774,13 @@ tree
type_promotes_to (type)
tree type;
{
int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type);
int constp, volatilep;
if (type == error_mark_node)
return error_mark_node;
constp = TYPE_READONLY (type);
volatilep = TYPE_VOLATILE (type);
type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same
......
......@@ -30,6 +30,9 @@ enum decl_context
MEMFUNCDEF /* Member function definition */
};
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree, tree));
/* C++: Keep these around to reduce calls to `get_identifier'.
Identifiers for `this' in member functions and the auto-delete
parameter for destructors. */
......
......@@ -43,11 +43,11 @@ extern int cp_line_of PROTO((tree));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
#define NARGS 3
#define arglist a1, a2, a3
#define arglist_dcl HOST_WIDE_INT a1, a2, a3;
#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3;
#define ARGSLIST args[0], args[1], args[2]
#define NARGS 4
#define arglist a1, a2, a3, a4
#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4;
#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;
#define ARGSLIST args[0], args[1], args[2], args[3]
static void
cp_thing (errfn, atarg1, format, arglist)
......
......@@ -35,6 +35,7 @@ typedef char* cp_printer ();
#define O op_as_string
#define P parm_as_string
#define T type_as_string
#define V cv_as_string
#define _ (cp_printer *) 0
cp_printer * cp_printers[256] =
......@@ -45,7 +46,7 @@ cp_printer * cp_printers[256] =
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
P, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */
P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
};
......@@ -56,6 +57,7 @@ cp_printer * cp_printers[256] =
#undef O
#undef P
#undef T
#undef V
#undef _
#define obstack_chunk_alloc xmalloc
......@@ -269,7 +271,7 @@ dump_aggr_type (t, v)
name = TYPE_NAME (t);
if (DECL_CONTEXT (name))
if (name && DECL_CONTEXT (name))
{
/* FUNCTION_DECL or RECORD_TYPE */
dump_decl (DECL_CONTEXT (name), 0);
......@@ -277,10 +279,10 @@ dump_aggr_type (t, v)
}
/* kludge around weird behavior on g++.brendan/line1.C */
if (TREE_CODE (name) != IDENTIFIER_NODE)
if (name && TREE_CODE (name) != IDENTIFIER_NODE)
name = DECL_NAME (name);
if (ANON_AGGRNAME_P (name))
if (name == 0 || ANON_AGGRNAME_P (name))
{
OB_PUTS ("{anonymous");
if (!v)
......@@ -512,6 +514,9 @@ ident_fndecl (t)
{
tree n = lookup_name (t, 0);
if (n == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (n) == FUNCTION_DECL)
return n;
else if (TREE_CODE (n) == TREE_LIST
......@@ -643,26 +648,30 @@ dump_decl (t, v)
/* These special cases are duplicated here so that other functions
can feed identifiers to cp_error and get them demangled properly. */
case IDENTIFIER_NODE:
if (DESTRUCTOR_NAME_P (t))
{
OB_PUTC ('~');
dump_decl (DECL_NAME (ident_fndecl (t)), 0);
}
else if (IDENTIFIER_TYPENAME_P (t))
{
OB_PUTS ("operator ");
/* Not exactly IDENTIFIER_TYPE_VALUE. */
dump_type (TREE_TYPE (t), 0);
break;
}
else if (IDENTIFIER_OPNAME_P (t))
{
char *name_string = operator_name_string (t);
OB_PUTS ("operator ");
OB_PUTCP (name_string);
}
else
OB_PUTID (t);
{ tree f;
if (DESTRUCTOR_NAME_P (t)
&& (f = ident_fndecl (t))
&& DECL_LANGUAGE (f) == lang_cplusplus)
{
OB_PUTC ('~');
dump_decl (DECL_NAME (f), 0);
}
else if (IDENTIFIER_TYPENAME_P (t))
{
OB_PUTS ("operator ");
/* Not exactly IDENTIFIER_TYPE_VALUE. */
dump_type (TREE_TYPE (t), 0);
break;
}
else if (IDENTIFIER_OPNAME_P (t))
{
char *name_string = operator_name_string (t);
OB_PUTS ("operator ");
OB_PUTCP (name_string);
}
else
OB_PUTID (t);
}
break;
case FUNCTION_DECL:
......@@ -785,7 +794,7 @@ dump_function_decl (t, v)
parmtypes = TREE_CHAIN (parmtypes);
}
if (DESTRUCTOR_NAME_P (name))
if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
parmtypes = TREE_CHAIN (parmtypes);
dump_function_name (t);
......@@ -824,7 +833,8 @@ dump_function_name (t)
/* There ought to be a better way to find out whether or not something is
a destructor. */
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
&& DECL_LANGUAGE (t) == lang_cplusplus)
{
OB_PUTC ('~');
dump_decl (name, 0);
......@@ -1456,3 +1466,17 @@ args_as_string (p, v)
return type_as_string (p, v);
}
char *
cv_as_string (p, v)
tree p;
int v;
{
OB_INIT ();
dump_readonly_or_volatile (p, before);
OB_FINISH ();
return (char *)obstack_base (&scratch_obstack);
}
......@@ -105,7 +105,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
&& TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
{
type = TYPE_POINTER_TO (type);
type = build_pointer_type (type);
/* Don't clobber a value that might be part of a default
parameter value. */
mark_addressable (slot);
......@@ -226,6 +226,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
expand_throw (TREE_OPERAND (exp, 0));
return NULL;
case UNSAVE_EXPR:
{
rtx temp;
temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
return temp;
}
default:
break;
}
......
......@@ -8,7 +8,7 @@
\(**
..
.SH NAME
g++ \- GNU project C++ Compiler (v2.4)
g++ \- GNU project C++ Compiler
.SH SYNOPSIS
.RB g++ " [" \c
.IR option " | " filename " ].\|.\|.
......@@ -31,8 +31,12 @@ C++ source files use one of the suffixes `\|\c
.B .C\c
\&\|', `\|\c
.B .cc\c
\&\|', or `\|\c
\&\|', `\|\c
.B .cxx\c
\&\|', `\|\c
.B .cpp\c
\&\|', or `\|\c
.B .c++\c
\&\|'; preprocessed C++ files use the suffix `\|\c
.B .ii\c
\&\|'.
......
......@@ -9,13 +9,9 @@ __asm, GCC_ASM_KEYWORD, NORID
__asm__, GCC_ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID
__classof, CLASSOF, NORID
__classof__, CLASSOF, NORID
__const, TYPE_QUAL, RID_CONST
__const__, TYPE_QUAL, RID_CONST
__extension__, EXTENSION, NORID
__headof, HEADOF, NORID
__headof__, HEADOF, NORID
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID
......@@ -40,7 +36,6 @@ case, CASE, NORID,
catch, CATCH, NORID,
char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS,
classof, CLASSOF, NORID,
compl, '~', NORID,
const, TYPE_QUAL, RID_CONST,
const_cast, CONST_CAST, NORID,
......@@ -59,7 +54,6 @@ float, TYPESPEC, RID_FLOAT,
for, FOR, NORID,
friend, SCSPEC, RID_FRIEND,
goto, GOTO, NORID,
headof, HEADOF, NORID,
if, IF, NORID,
inline, SCSPEC, RID_INLINE,
int, TYPESPEC, RID_INT,
......
......@@ -1559,8 +1559,8 @@ reinit_parse_for_method (yychar, decl)
output if something goes wrong. This should really be cleaned up somehow,
without loss of clarity. */
void
reinit_parse_for_block (yychar, obstackp, is_template)
int yychar;
reinit_parse_for_block (pyychar, obstackp, is_template)
int pyychar;
struct obstack *obstackp;
int is_template;
{
......@@ -1572,23 +1572,35 @@ reinit_parse_for_block (yychar, obstackp, is_template)
int look_for_semicolon = 0;
int look_for_lbrac = 0;
if (yychar == '{')
if (pyychar == '{')
obstack_1grow (obstackp, '{');
else if (yychar == '=')
else if (pyychar == '=')
look_for_semicolon = 1;
else if (yychar != ':' && (yychar != RETURN || is_template))
else if (pyychar == ':')
{
yyerror (is_template
? "parse error in template specification"
: "parse error in method specification");
obstack_1grow (obstackp, '{');
obstack_1grow (obstackp, pyychar);
look_for_lbrac = 1;
blev = 0;
}
else
else if (pyychar == RETURN && !is_template)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
blev = 0;
}
else if (pyychar == TRY && !is_template)
{
obstack_1grow (obstackp, yychar);
obstack_grow (obstackp, "try", 3);
look_for_lbrac = 1;
blev = 0;
}
else
{
yyerror (is_template
? "parse error in template specification"
: "parse error in method specification");
obstack_1grow (obstackp, '{');
}
if (nextchar != EOF)
{
......@@ -1640,7 +1652,26 @@ reinit_parse_for_block (yychar, obstackp, is_template)
{
blev--;
if (blev == 0 && !look_for_semicolon)
goto done;
{
if (pyychar == TRY)
{
if (peekyylex () == CATCH)
{
yylex ();
obstack_grow (obstackp, " catch ", 7);
look_for_lbrac = 1;
}
else
{
yychar = '{';
goto done;
}
}
else
{
goto done;
}
}
}
else if (c == '\\')
{
......@@ -1783,7 +1814,8 @@ cons_up_default_function (type, full_name, kind)
if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator);
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
}
if (fn == void_type_node)
......@@ -2278,8 +2310,8 @@ check_newline ()
}
#endif
#endif
goto skipline;
}
goto skipline;
}
else if (c == 'd')
{
......@@ -2817,6 +2849,9 @@ identifier_type (decl)
void
see_typename ()
{
looking_for_typename = 1;
if (yychar < 0)
if ((yychar = yylex()) < 0) yychar = 0;
looking_for_typename = 0;
if (yychar == IDENTIFIER)
{
......@@ -2920,8 +2955,6 @@ do_identifier (token)
if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
{
tree shadowed = DECL_SHADOWED_FOR_VAR (id);
if (!shadowed)
shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
if (shadowed)
{
if (!DECL_ERROR_REPORTED (id))
......@@ -3143,6 +3176,12 @@ real_yylex ()
*p++ = c;
c = getc (finput);
}
if (linemode && c == '\n')
{
put_back (c);
c = EOF;
}
}
else
{
......@@ -4668,7 +4707,10 @@ handle_sysv_pragma ()
handle_pragma_token (NULL_PTR, NULL_TREE);
return;
default:
abort ();
handle_pragma_token (NULL_PTR, NULL_TREE);
while (yylex () != END_OF_LINE)
/* continue */;
return;
}
}
}
......
......@@ -165,14 +165,6 @@ report_type_mismatch (cp, parmtypes, name_kind)
cp->function);
return;
case -3:
if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))))
cp_error ("call to const %s `%#D' with non-const object", name_kind,
cp->function);
else
cp_error ("call to non-const %s `%#D' with const object", name_kind,
cp->function);
return;
case -2:
cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
return;
......@@ -180,14 +172,15 @@ report_type_mismatch (cp, parmtypes, name_kind)
cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
return;
case 0:
if (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
{
/* Happens when we have an ambiguous base class. */
my_friendly_assert (get_binfo (DECL_CLASS_CONTEXT (cp->function),
TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))), 1) == error_mark_node,
241);
return;
}
if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE)
break;
case -3:
/* Happens when the implicit object parameter is rejected. */
my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
241);
cp_error ("call to non-const %s `%#D' with const object",
name_kind, cp->function);
return;
}
ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
......@@ -512,6 +505,12 @@ build_overload_value (type, value)
sorry ("template instantiation with pointer to method that is too complex");
return;
}
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value);
numeric_output_need_bar = 1;
return;
}
value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL)
{
......@@ -1803,7 +1802,9 @@ make_thunk (function, delta)
{
thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, 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_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
......@@ -2249,7 +2250,7 @@ synthesize_method (fndecl)
input_filename = DECL_SOURCE_FILE (fndecl);
interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
interface_only = CLASSTYPE_INTERFACE_ONLY (base);
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
store_parm_decls ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
......
......@@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA. */
#include "defaults.h"
extern struct obstack permanent_obstack;
extern tree grokdeclarator ();
extern int lineno;
extern char *input_filename;
......@@ -102,7 +101,7 @@ process_template_parm (list, next)
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE);
PARM, 0, NULL_TREE, NULL_TREE);
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
if (IS_AGGR_TYPE (TREE_TYPE (parm)))
......@@ -239,7 +238,7 @@ end_template_decl (d1, d2, is_class, defn)
my_friendly_assert (code == BIT_NOT_EXPR
|| code == OP_IDENTIFIER
|| code == SCOPE_REF, 264);
d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE);
d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);
decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
TREE_TYPE (d2));
DECL_TEMPLATE_RESULT (decl) = d2;
......@@ -407,12 +406,6 @@ coerce_template_parms (parms, arglist, in_decl)
}
if (is_type)
val = groktypename (arg);
else if (TREE_CODE (arg) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument", arg);
error ("because it is the address of an object with static linkage");
val = error_mark_node;
}
else
{
tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
......@@ -431,14 +424,41 @@ coerce_template_parms (parms, arglist, in_decl)
arg);
val = error_mark_node;
}
else if (TREE_CODE (val) == ADDR_EXPR)
else if (POINTER_TYPE_P (TREE_TYPE (val))
&& ! integer_zerop (val)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != METHOD_TYPE)
{
tree a = TREE_OPERAND (val, 0);
if ((TREE_CODE (a) == VAR_DECL
|| TREE_CODE (a) == FUNCTION_DECL)
&& ! DECL_PUBLIC (a))
t = val;
STRIP_NOPS (t);
if (TREE_CODE (t) == ADDR_EXPR)
{
tree a = TREE_OPERAND (t, 0);
STRIP_NOPS (a);
if (TREE_CODE (a) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument", a);
error ("because it is the address of an object with static linkage");
val = error_mark_node;
}
else if (TREE_CODE (a) != VAR_DECL
&& TREE_CODE (a) != FUNCTION_DECL)
goto bad;
else if (! DECL_PUBLIC (a))
{
cp_error ("address of non-extern `%E' cannot be used as template argument", a);
val = error_mark_node;
}
}
else
{
cp_error ("address of non-extern `%E' cannot be used as template argument", a);
bad:
cp_error ("`%E' is not a valid template argument", t);
error ("it must be %s%s with external linkage",
TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE
? "a pointer to " : "",
TREE_CODE (TREE_TYPE (TREE_TYPE (val))) == FUNCTION_TYPE
? "a function" : "an object");
val = error_mark_node;
}
}
......@@ -1714,11 +1734,9 @@ instantiate_template (tmpl, targ_ptr)
if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
&& DECL_STATIC_FUNCTION_P (fndecl))
{
tree olddecl = DECL_RESULT (tmpl);
revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
/* Chop off the this pointer that grokclassfn so kindly added
for us (it didn't know yet if the fn was static or not). */
DECL_ARGUMENTS (olddecl) = TREE_CHAIN (DECL_ARGUMENTS (olddecl));
DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
}
......@@ -1726,7 +1744,7 @@ instantiate_template (tmpl, targ_ptr)
/* If we have a preexisting version of this function, don't expand
the template version, use the other instead. */
if (TREE_STATIC (fndecl))
if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0;
......@@ -1888,12 +1906,13 @@ overload_template_name (id, classlevel)
#endif
}
extern struct pending_input *to_be_restored;
/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
void
end_template_instantiation (name)
tree name;
{
extern struct pending_input *to_be_restored;
tree t, decl;
processing_template_defn--;
......@@ -2502,7 +2521,8 @@ void
do_function_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0);
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0,
NULL_TREE, NULL_TREE);
tree name;
tree fn;
tree result = NULL_TREE;
......
......@@ -942,12 +942,12 @@ build_signature_method_call (basetype, instance, function, parms)
deflt_call = build_function_call (pfn, parms);
}
new_object_ptr = build (PLUS_EXPR, TYPE_POINTER_TO (basetype),
new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
convert (ptrdiff_type_node, object_ptr),
convert (ptrdiff_type_node, delta));
parms = tree_cons (NULL_TREE,
convert (TYPE_POINTER_TO (basetype), object_ptr),
convert (build_pointer_type (basetype), object_ptr),
TREE_CHAIN (parms));
new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
......@@ -956,7 +956,7 @@ build_signature_method_call (basetype, instance, function, parms)
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
build_type_variant (TYPE_POINTER_TO (basetype),
build_type_variant (build_pointer_type (basetype),
TYPE_READONLY (old_this),
TYPE_VOLATILE (old_this));
......
......@@ -246,6 +246,13 @@ tree got_scope;
tree got_object;
int
peekyylex()
{
scan_tokens (0);
return nth_token (0)->yychar;
}
int
yylex()
{
struct token tmp_token;
......
......@@ -236,7 +236,7 @@ build_cplus_new (type, init, with_cleanup_p)
{
TREE_OPERAND (rval, 2) = error_mark_node;
rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
build_delete (TYPE_POINTER_TO (type),
build_delete (build_pointer_type (type),
build_unary_op (ADDR_EXPR, slot, 0),
integer_two_node,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
......@@ -1318,7 +1318,7 @@ void
debug_binfo (elem)
tree elem;
{
int i;
unsigned HOST_WIDE_INT n;
tree virtuals;
fprintf (stderr, "type \"%s\"; offset = %d\n",
......@@ -1332,20 +1332,17 @@ debug_binfo (elem)
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem);
if (virtuals != 0)
{
/* skip the rtti type descriptor entry */
virtuals = TREE_CHAIN (virtuals);
}
i = 1;
n = skip_rtti_stuff (&virtuals);
while (virtuals)
{
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
fprintf (stderr, "%s [%d =? %d]\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
++n;
virtuals = TREE_CHAIN (virtuals);
i += 1;
}
}
......@@ -1567,11 +1564,11 @@ id_cmp (p1, p2)
return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
}
/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
tree
build_exception_variant (ctype, type, raises)
tree ctype, type;
build_exception_variant (type, raises)
tree type;
tree raises;
{
int i;
......@@ -1903,3 +1900,96 @@ break_out_target_exprs (t)
{
return mapcar (t, bot_manip);
}
tree
unsave_expr (expr)
tree expr;
{
tree t;
t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
return t;
}
/* Modify a tree in place so that all the evaluate only once things
are cleared out. Return the EXPR given. */
tree
unsave_expr_now (expr)
tree expr;
{
enum tree_code code;
register int i;
if (expr == NULL_TREE)
return expr;
code = TREE_CODE (expr);
switch (code)
{
case SAVE_EXPR:
SAVE_EXPR_RTL (expr) = NULL_RTX;
break;
case TARGET_EXPR:
sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
break;
case RTL_EXPR:
warning ("RTL_EXPR reused inside UNSAVE_EXPR");
RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
break;
case CALL_EXPR:
CALL_EXPR_RTL (expr) = NULL_RTX;
if (TREE_OPERAND (expr, 1)
&& TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
{
tree exp = TREE_OPERAND (expr, 1);
while (exp)
{
unsave_expr_now (TREE_VALUE (exp));
exp = TREE_CHAIN (exp);
}
}
break;
case WITH_CLEANUP_EXPR:
warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
RTL_EXPR_RTL (expr) = NULL_RTX;
break;
}
switch (TREE_CODE_CLASS (code))
{
case 'c': /* a constant */
case 't': /* a type node */
case 'x': /* something random, like an identifier or an ERROR_MARK. */
case 'd': /* A decl node */
case 'b': /* A block node */
return expr;
case 'e': /* an expression */
case 'r': /* a reference */
case 's': /* an expression with side effects */
case '<': /* a comparison expression */
case '2': /* a binary arithmetic expression */
case '1': /* a unary arithmetic expression */
for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
unsave_expr_now (TREE_OPERAND (expr, i));
return expr;
default:
my_friendly_abort (999);
}
}
/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
by itself. */
int
cp_expand_decl_cleanup (decl, cleanup)
tree decl, cleanup;
{
return expand_decl_cleanup (decl, unsave_expr (cleanup));
}
......@@ -884,9 +884,15 @@ digest_init (type, init, tail)
if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)
{
if (raw_constructor)
if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type))
{
cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
type, init);
return error_mark_node;
}
else if (raw_constructor)
return process_init_constructor (type, init, (tree *)0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
else if (TYPE_NON_AGGREGATE_CLASS (type))
{
/* This can only be reached when caller is initializing
ARRAY_TYPE. In that case, we don't want to convert
......
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