Commit 8ccc31eb by Mike Stump

56th Cygnus<->FSF merge

From-SVN: r8957
parent 3a5ece65
......@@ -176,6 +176,9 @@ convert_harshness (type, parmtype, parm)
if (type == parmtype)
return ZERO_RETURN (h);
if (pedantic)
return EVIL_RETURN (h);
/* Compare return types. */
p1 = TREE_TYPE (type);
p2 = TREE_TYPE (parmtype);
......@@ -207,14 +210,16 @@ convert_harshness (type, parmtype, parm)
if (! BINFO_OFFSET_ZEROP (binfo))
{
#if 0
static int explained = 0;
if (h2.distance < 0)
message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1);
message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);
else
message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2);
message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);
if (! explained++)
sorry ("(because pointer values change during conversion)");
#endif
return EVIL_RETURN (h);
}
}
......@@ -877,12 +882,15 @@ compute_conversion_costs (function, tta_in, cp, arglen)
inhibit_warnings = 1;
conv = build_type_conversion
(CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
(CALL_EXPR, formal_type, TREE_VALUE (tta), 0);
inhibit_warnings = old_inhibit_warnings;
if (conv)
{
if (conv == error_mark_node)
if (conv == error_mark_node
|| (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE
&& ! TYPE_READONLY (TREE_VALUE (TREE_VALUE (ttf)))
&& ! lvalue_p (conv)))
win += 2;
else
{
......@@ -891,22 +899,6 @@ compute_conversion_costs (function, tta_in, cp, arglen)
extra_conversions = 1;
}
}
else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
{
conv = build_type_conversion (CALL_EXPR, formal_type,
TREE_VALUE (tta), 0);
if (conv)
{
if (conv == error_mark_node)
win += 2;
else
{
win++;
if (TREE_CODE (conv) != CALL_EXPR)
extra_conversions = 1;
}
}
}
}
}
dont_convert_types = 0;
......@@ -2035,25 +2027,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
tree parm = instance_ptr;
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
{
/* TREE_VALUE (parms) may have been modified by now;
restore it to its original value. */
TREE_VALUE (parms) = parm;
friend_parms = parms;
}
parm = convert_from_reference (parm);
else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
{
tree new_type;
parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
volatilep);
new_type = build_reference_type (new_type);
parm = convert (new_type, parm);
friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
}
parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
else
my_friendly_abort (167);
friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
cp->h_len = len;
cp->harshness = (struct harshness_code *)
alloca ((len + 1) * sizeof (struct harshness_code));
......@@ -2602,6 +2583,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_TYPE (result) = value_type;
TREE_SIDE_EFFECTS (result) = 1;
TREE_HAS_CONSTRUCTOR (result) = is_constructor;
result = convert_from_reference (result);
return result;
}
}
......
......@@ -1453,6 +1453,7 @@ finish_base_struct (t, b, t_binfo)
chain = TREE_VEC_ELT (base_binfos, j);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
}
/* Completely unshare potentially shared data, and
......@@ -1711,8 +1712,9 @@ finish_struct_bits (t, max_has_virtual)
/* Add FN to the method_vec growing on the class_obstack. Used by
finish_struct_methods. */
static void
grow_method (fn)
grow_method (fn, method_vec_ptr)
tree fn;
tree *method_vec_ptr;
{
tree method_vec = (tree)obstack_base (&class_obstack);
tree *testp = &TREE_VEC_ELT (method_vec, 0);
......@@ -1756,7 +1758,10 @@ grow_method (fn)
}
}
else
obstack_ptr_grow (&class_obstack, fn);
{
obstack_ptr_grow (&class_obstack, fn);
*method_vec_ptr = (tree)obstack_base (&class_obstack);
}
}
/* Warn about duplicate methods in fn_fields. Also compact method
......@@ -1855,7 +1860,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
else if (typecode_p (return_type, REAL_TYPE))
TYPE_HAS_REAL_CONVERSION (t) = 1;
grow_method (fn_fields);
grow_method (fn_fields, &method_vec);
}
else
{
......@@ -1891,12 +1896,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
}
}
grow_method (fn_fields);
grow_method (fn_fields, &method_vec);
fn_fields = nextp;
}
/* Update in case method_vec has moved. */
method_vec = (tree)obstack_base (&class_obstack);
TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
- (&TREE_VEC_ELT (method_vec, 0));
obstack_finish (&class_obstack);
......@@ -2289,13 +2292,9 @@ modify_one_vtable (binfo, t, fndecl, pfn)
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (binfo)) {
if (TREE_USED (binfo))
my_friendly_assert (0, 999);
#if 0
my_friendly_assert (*binfo2_ptr == binfo, 999);
*binfo2_ptr = copy_binfo (binfo);
#endif
}
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
......@@ -3160,8 +3159,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{
cp_warning_at ("width of `%D' exceeds its type", x);
}
else if (width < TYPE_PRECISION (TREE_TYPE (x))
&& TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE)
else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
TREE_UNSIGNED (TREE_TYPE (x))) > width)
|| (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
TREE_UNSIGNED (TREE_TYPE (x))) > width)))
{
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
x, TREE_TYPE (x));
......
......@@ -666,7 +666,9 @@ struct lang_type
searched with TREE_CHAIN), or the first non-constructor function if
there are no type conversion operators. */
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \
: NULL_TREE;
/* Pointer from any member function to the head of the list of
member functions of the type that member function belongs to. */
......@@ -842,6 +844,9 @@ struct lang_type
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
#define TYPE_INCOMPLETE(NODE) \
(TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM)
/* Additional macros for inheritance information. */
......@@ -1816,7 +1821,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
CONV_CONST : Perform the explicit conversions for const_cast.
CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast.
CONV_PRIVATE : Perform upcasts to private bases.
CONV_NONCONVERTING : Allow non-converting constructors to be used. */
CONV_NONCONVERTING : Allow non-converting constructors to be used.
CONV_FORCE_TEMP : Require a new temporary when converting to the same
aggregate type. */
#define CONV_IMPLICIT 1
#define CONV_STATIC 2
......@@ -1824,11 +1831,12 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define CONV_REINTERPRET 8
#define CONV_PRIVATE 16
#define CONV_NONCONVERTING 32
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC)
#define CONV_FORCE_TEMP 64
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP)
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET)
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET | CONV_PRIVATE)
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
purpose = friend name (IDENTIFIER_NODE);
......@@ -1946,6 +1954,7 @@ extern tree pushdecl_top_level PROTO((tree));
extern void push_class_level_binding PROTO((tree, tree));
extern void push_overloaded_decl_top_level PROTO((tree, int));
extern tree pushdecl_class_level PROTO((tree));
extern tree pushdecl_nonclass_level PROTO((tree));
extern int overloaded_globals_p PROTO((tree));
extern tree push_overloaded_decl PROTO((tree, int));
extern tree implicitly_declare PROTO((tree));
......@@ -1971,8 +1980,8 @@ 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)); */
extern int parmlist_is_exprlist PROTO((tree));
extern tree xref_defn_tag PROTO((tree, tree, tree));
extern tree xref_tag PROTO((tree, tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
extern tree start_enum PROTO((tree));
extern tree finish_enum PROTO((tree, tree));
extern tree build_enumerator PROTO((tree, tree));
......@@ -2019,7 +2028,7 @@ extern tree coerce_delete_type PROTO((tree));
extern void walk_vtables PROTO((void (*)(), void (*)()));
extern void walk_sigtables PROTO((void (*)(), void (*)()));
extern void finish_file PROTO((void));
extern void warn_if_unknown_interface PROTO((void));
extern void warn_if_unknown_interface PROTO((tree));
extern tree grok_x_components PROTO((tree, tree));
extern tree reparse_absdcl_as_expr PROTO((tree, tree));
extern tree reparse_absdcl_as_casts PROTO((tree, tree));
......@@ -2286,7 +2295,6 @@ extern tree hash_chainon PROTO((tree, tree));
extern tree get_decl_list PROTO((tree));
extern tree list_hash_lookup_or_cons PROTO((tree));
extern tree make_binfo PROTO((tree, tree, tree, tree, tree));
extern tree copy_binfo PROTO((tree));
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
extern tree virtual_member PROTO((tree, tree));
......@@ -2311,7 +2319,7 @@ extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree));
/* in typeck.c */
extern tree bool_truthvalue_conversion PROTO((tree));
extern tree condition_conversion PROTO((tree));
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
extern int type_unknown_p PROTO((tree));
......
......@@ -113,7 +113,7 @@ cp_convert_to_pointer (type, expr)
register tree intype = TREE_TYPE (expr);
register enum tree_code form = TREE_CODE (intype);
if (form == POINTER_TYPE)
if (form == POINTER_TYPE || form == REFERENCE_TYPE)
{
intype = TYPE_MAIN_VARIANT (intype);
......@@ -632,31 +632,49 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{
register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
register tree intype = TREE_TYPE (expr);
register enum tree_code form = TREE_CODE (intype);
tree rval = NULL_TREE;
tree rval_as_conversion = NULL_TREE;
int i;
if (TREE_CODE (intype) == REFERENCE_TYPE)
my_friendly_abort (364);
if (form == REFERENCE_TYPE)
intype = TREE_TYPE (intype);
intype = TYPE_MAIN_VARIANT (intype);
if (((convtype & CONV_STATIC) && comptypes (type, intype, -1))
|| ((convtype & CONV_IMPLICIT) && comptypes (type, intype, 0)))
i = comp_target_types (type, intype, 0);
if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
&& ! (flags & LOOKUP_NO_CONVERSION))
{
/* Look for a user-defined conversion to lvalue that we can use. */
rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
{
expr = rval_as_conversion;
rval_as_conversion = NULL_TREE;
intype = type;
i = 1;
}
}
if (((convtype & CONV_STATIC) && i == -1)
|| ((convtype & CONV_IMPLICIT) && i == 1))
{
if (flags & LOOKUP_COMPLAIN)
{
tree ttl = TREE_TYPE (reftype);
tree ttr;
if (form == REFERENCE_TYPE)
ttr = TREE_TYPE (TREE_TYPE (expr));
else
{
int r = TREE_READONLY (expr);
int v = TREE_THIS_VOLATILE (expr);
ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
}
{
int r = TREE_READONLY (expr);
int v = TREE_THIS_VOLATILE (expr);
ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
}
if (! lvalue_p (expr) &&
if (! real_lvalue_p (expr) &&
(decl == NULL_TREE || ! TYPE_READONLY (ttl)))
{
if (decl)
......@@ -678,34 +696,9 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
}
}
if (form == REFERENCE_TYPE)
{
tree type = TREE_TYPE (expr);
TREE_TYPE (expr) = build_pointer_type (TREE_TYPE (type));
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), expr,
convtype, flags);
TREE_TYPE (expr) = type;
TREE_TYPE (rval) = reftype;
if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR)
TREE_TYPE (TREE_OPERAND (rval, 0))
= TREE_TYPE (TREE_OPERAND (rval, 1)) = reftype;
return rval;
}
return build_up_reference (reftype, expr, flags,
! (convtype & CONV_CONST));
}
if ((convtype & CONV_IMPLICIT)
&& IS_AGGR_TYPE (intype)
&& ! (flags & LOOKUP_NO_CONVERSION)
&& (rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1)))
{
if (rval == error_mark_node)
cp_error ("conversion from `%T' to `%T' is ambiguous",
intype, reftype);
return rval;
}
else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
{
/* When casting an lvalue to a reference type, just convert into
......@@ -715,7 +708,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
meant. */
if (form == POINTER_TYPE
if (TREE_CODE (intype) == POINTER_TYPE
&& (comptypes (TREE_TYPE (intype), type, -1)))
cp_warning ("casting `%T' to `%T' does not dereference pointer",
intype, reftype);
......@@ -728,16 +721,18 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
}
else if (decl)
{
tree rval_as_conversion = NULL_TREE;
tree rval_as_ctor = NULL_TREE;
if (IS_AGGR_TYPE (intype)
&& (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1)))
if (rval_as_conversion)
{
if (rval == error_mark_node)
return rval;
rval_as_conversion = build_up_reference (reftype, rval, flags, 1);
if (rval_as_conversion == error_mark_node)
{
cp_error ("conversion from `%T' to `%T' is ambiguous",
intype, reftype);
return error_mark_node;
}
rval_as_conversion = build_up_reference (reftype, rval_as_conversion,
flags, 1);
}
/* Definitely need to go through a constructor here. */
......@@ -815,7 +810,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
return rval;
}
my_friendly_assert (form != OFFSET_TYPE, 189);
my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
......@@ -1206,8 +1201,10 @@ cp_convert (type, expr, convtype, flags)
|| TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
return error_mark_node;
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP))
/* We need a new temporary; don't take this shortcut. */;
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
return fold (build1 (NOP_EXPR, type, e));
if (code == VOID_TYPE && (convtype & CONV_STATIC))
......@@ -1227,10 +1224,12 @@ cp_convert (type, expr, convtype, flags)
code = TREE_CODE (type);
}
#if 0
if (code == REFERENCE_TYPE)
return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
#endif
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
......@@ -1266,7 +1265,7 @@ cp_convert (type, expr, convtype, flags)
return truthvalue_conversion (e);
return fold (convert_to_integer (type, e));
}
if (code == POINTER_TYPE)
if (code == POINTER_TYPE || code == REFERENCE_TYPE)
return fold (cp_convert_to_pointer (type, e));
if (code == REAL_TYPE)
{
......@@ -1458,7 +1457,7 @@ convert_force (type, expr, convtype)
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
}
return cp_convert (type, e, CONV_OLD_CONVERT|convtype, 0);
return cp_convert (type, e, CONV_C_CAST|convtype, 0);
}
/* Subroutine of build_type_conversion. */
......@@ -1484,9 +1483,9 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
return NULL_TREE;
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE
&& TREE_CODE (xtype) != REFERENCE_TYPE)
rval = default_conversion (rval);
if (IS_AGGR_TYPE (TREE_TYPE (rval)))
return rval;
if (warn_cast_qual
&& TREE_TYPE (xtype)
......
......@@ -683,11 +683,29 @@ substitute_nice_name (decl)
interface/implementation is not used all the times it should be,
inform the user. */
void
warn_if_unknown_interface ()
warn_if_unknown_interface (decl)
tree decl;
{
static int already_warned = 0;
if (++already_warned == 1)
warning ("templates that are built with -fexternal-templates should be in files that have #pragma interface/implementation");
if (already_warned++)
return;
if (flag_alt_external_templates)
{
struct tinst_level *til = tinst_for_decl ();
int sl = lineno;
char *sf = input_filename;
lineno = til->line;
input_filename = til->file;
cp_warning ("template `%#D' instantiated in file without #pragma interface",
decl);
lineno = sl;
input_filename = sf;
}
else
cp_warning_at ("template `%#D' defined in file without #pragma interface",
decl);
}
/* A subroutine of the parser, to handle a component list. */
......@@ -734,7 +752,7 @@ grok_x_components (specs, components)
else if (IS_SIGNATURE(t))
tcode = signature_type_node;
t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (TYPE_CONTEXT(t))
CLASSTYPE_NO_GLOBALIZE(t) = 1;
return NULL_TREE;
......@@ -747,7 +765,7 @@ grok_x_components (specs, components)
else
tcode = enum_type_node;
t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t))
CLASSTYPE_NO_GLOBALIZE(t) = 1;
if (TREE_CODE (t) == UNION_TYPE
......@@ -1103,12 +1121,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (code == POINTER_TYPE)
{
#if 0
/* As of Valley Forge, you can delete a pointer to constant. */
/* You can't delete a pointer to constant. */
if (TREE_READONLY (TREE_TYPE (type)))
{
error ("`const *' cannot be deleted");
return error_mark_node;
}
#endif
/* You also can't delete functions. */
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
......@@ -1288,7 +1309,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
pushdecl_class_level (value);
/* If we declare a typedef name for something that has no name,
the typedef name is used for linkage. See 7.1.3 p4 94/0158. */
......@@ -1299,6 +1319,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
TYPE_NAME (TREE_TYPE (value)) = value;
TYPE_STUB_DECL (TREE_TYPE (value)) = value;
}
pushdecl_class_level (value);
return value;
}
......
......@@ -599,6 +599,7 @@ dump_decl (t, v)
{
dump_type_prefix (TREE_TYPE (t), v);
OB_PUTC (' ');
dump_readonly_or_volatile (t, after);
}
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
if (DECL_CONTEXT (t)
......
......@@ -48,7 +48,12 @@ tree builtin_return_address_fndecl;
#define __rs6000
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm)
#ifdef mips
#ifndef __mips
#define __mips
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha)
#define TRY_NEW_EH
#endif
#endif
......@@ -390,44 +395,45 @@ static tree TerminateFunctionCall;
/* =================================================================== */
struct labelNode {
rtx label;
struct labelNode *chain;
};
rtx label;
struct labelNode *chain;
};
/* this is the most important structure here. Basically this is how I store
an exception table entry internally. */
struct ehEntry {
rtx start_label;
rtx end_label;
rtx exception_handler_label;
rtx start_label;
rtx end_label;
rtx exception_handler_label;
tree finalization;
};
tree finalization;
tree context;
};
struct ehNode {
struct ehEntry *entry;
struct ehNode *chain;
};
struct ehEntry *entry;
struct ehNode *chain;
};
struct ehStack {
struct ehNode *top;
};
struct ehNode *top;
};
struct ehQueue {
struct ehNode *head;
struct ehNode *tail;
};
struct ehNode *head;
struct ehNode *tail;
};
struct exceptNode {
rtx catchstart;
rtx catchend;
rtx catchstart;
rtx catchend;
struct exceptNode *chain;
};
struct exceptNode *chain;
};
struct exceptStack {
struct exceptNode *top;
struct exceptNode *top;
};
/* ========================================================================= */
......@@ -603,6 +609,7 @@ push_eh_entry (stack)
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
entry->finalization = NULL_TREE;
entry->context = current_function_decl;
node->entry = entry;
node->chain = stack->top;
......@@ -715,6 +722,8 @@ lang_interim_eh (finalization)
start_protect ();
}
extern tree auto_function PROTO((tree, tree, enum built_in_function));
/* sets up all the global eh stuff that needs to be initialized at the
start of compilation.
......@@ -735,44 +744,34 @@ init_exception_processing ()
tree catch_match_fndecl;
tree find_first_exception_match_fndecl;
tree unwind_fndecl;
tree temp, PFV;
interim_eh_hook = lang_interim_eh;
/* void (*)() */
PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
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 () */
temp = tree_cons (NULL_TREE, PFV, void_list_node);
tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
push_lang_context (lang_name_c);
/* void (*pfvtype (void (*) ()))() */
tree pfvtype = build_function_type (PFV, pfvlist);
set_terminate_fndecl =
define_function ("set_terminate",
build_function_type (PFV, temp),
NOT_BUILT_IN,
pushdecl,
0);
set_unexpected_fndecl =
define_function ("set_unexpected",
build_function_type (PFV, temp),
NOT_BUILT_IN,
pushdecl,
0);
/* void vtype () */
tree vtype = build_function_type (void_type_node, void_list_node);
set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
pfvtype, NOT_BUILT_IN);
set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
pfvtype, NOT_BUILT_IN);
unexpected_fndecl = auto_function (get_identifier ("unexpected"),
vtype, NOT_BUILT_IN);
terminate_fndecl = auto_function (get_identifier ("terminate"),
vtype, NOT_BUILT_IN);
interim_eh_hook = lang_interim_eh;
push_lang_context (lang_name_c);
unexpected_fndecl =
define_function ("unexpected",
build_function_type (void_type_node, void_list_node),
NOT_BUILT_IN,
pushdecl,
0);
terminate_fndecl =
define_function ("terminate",
build_function_type (void_type_node, void_list_node),
NOT_BUILT_IN,
pushdecl,
0);
catch_match_fndecl =
define_function ("__throw_type_match",
build_function_type (integer_type_node,
......@@ -844,6 +843,11 @@ init_exception_processing ()
saved_throw_type = gen_rtx (REG, Pmode, 8);
saved_throw_value = gen_rtx (REG, Pmode, 9);
#endif
#ifdef __alpha
saved_pc = gen_rtx (REG, Pmode, 9);
saved_throw_type = gen_rtx (REG, Pmode, 10);
saved_throw_value = gen_rtx (REG, Pmode, 11);
#endif
new_eh_queue (&ehqueue);
new_eh_queue (&eh_table_output_queue);
new_eh_stack (&ehstack);
......@@ -989,6 +993,7 @@ expand_start_all_catch ()
entry->end_label = gen_label_rtx ();
entry->exception_handler_label = gen_label_rtx ();
entry->finalization = TerminateFunctionCall;
entry->context = current_function_decl;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm ();
......@@ -1091,6 +1096,7 @@ expand_leftover_cleanups ()
entry.end_label = label;
entry.exception_handler_label = gen_label_rtx ();
entry.finalization = TerminateFunctionCall;
entry.context = current_function_decl;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm ();
......@@ -1243,13 +1249,15 @@ void expand_end_catch_block ()
emit_jump (throw_label);
/* No associated finalization. */
entry.finalization = NULL_TREE;
entry.context = current_function_decl;
/* Because we are reordered out of line, we have to protect this. */
/* label for the start of the protection region. */
start_protect_label_rtx = pop_label_entry (&false_label_stack);
/* Cleanup the EH paramater. */
expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
/* label we emit to jump to if this catch block didn't match. */
emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
......@@ -1309,7 +1317,7 @@ do_unwind (throw_label)
easy_expand_asm ("restore");
emit_barrier ();
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined(__alpha)
extern FILE *asm_out_file;
tree fcall;
tree params;
......@@ -1449,7 +1457,7 @@ expand_builtin_throw ()
#ifndef sparc
/* On the SPARC, __builtin_return_address is already -8, no need to
subtract any more from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
return_val_rtx = plus_constant (return_val_rtx, -1);
#endif
#endif
......@@ -1542,10 +1550,8 @@ expand_throw (exp)
rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
rtx throw_value_rtx;
exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node);
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), exp, 0);
exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
if (exp == error_mark_node)
error (" in thrown expression");
......@@ -1557,7 +1563,7 @@ expand_throw (exp)
else
{
/* rethrow current exception */
/* This part is easy, as we dont' have to do anything else. */
/* This part is easy, as we don't have to do anything else. */
}
emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
......@@ -1585,6 +1591,11 @@ build_exception_table ()
while (entry = dequeue_eh_entry (&eh_table_output_queue))
{
tree context = entry->context;
if (context && ! TREE_ASM_WRITTEN (context))
continue;
if (count == 0)
{
exception_section ();
......
......@@ -1193,17 +1193,17 @@ The below points out some flaws in g++'s exception handling, as it now
stands.
Only exact type matching or reference matching of throw types works.
Only works on a SPARC machines (like Suns), and i386 machines. Partial
support is also in for rs6000, hppa, m68k and mips machines, but a stack
unwinder called __unwind_function has to be written, and added to
libgcc2 for them. All completely constructed temps and local variables
are cleaned up in all unwinded scopes. Completed parts of partially
constructed objects are not cleaned up. Don't expect exception handling
to work right if you optimize, in fact the compiler will probably core
dump. If two EH regions are the exact same size, the backend cannot
tell which one is first. It punts by picking the last one, if they tie.
This is usually right. We really should stick in a nop, if they are the
same size.
Only works on a SPARC machines (like Suns), i386 machines, arm machines
and rs6000 machines. Partial support is also in for alpha, hppa, m68k
and mips machines, but a stack unwinder called __unwind_function has to
be written, and added to libgcc2 for them. All completely constructed
temps and local variables are cleaned up in all unwinded scopes.
Completed parts of partially constructed objects are not cleaned up.
Don't expect exception handling to work right if you optimize, in fact
the compiler will probably core dump. If two EH regions are the exact
same size, the backend cannot tell which one is first. It punts by
picking the last one, if they tie. This is usually right. We really
should stick in a nop, if they are the same size.
When we invoke the copy constructor for an exception object because it
is passed by value, and if we take a hit (exception) inside the copy
......@@ -1223,14 +1223,14 @@ implements set compares, not exact list equality. Type smashing should
smash exception specifications using set union.
Thrown objects are allocated on the heap, in the usual way, but they are
never deleted. They should be deleted by the catch clauses.
In stmt.c, expand_end_bindings attempts to eliminate the generation of
destructors for a binding contour if the code would be unreachable (last
insn == BARRIER). In this case, interim_eh_hook is never called for the
end of the lifetimes of auto variables, so the compiler generates
invalid assembler (the end label for the scope is never declared, and
destructor code isn't generated on the exception path).
never deleted. They should be deleted by the catch clauses. If one
runs out of heap space, throwing an object will probably never work.
This could be relaxed some by passing an __in_chrg parameter to track
who has control over the exception object.
When the backend returns a value, it can create new exception regions
that need protecting. The new region should rethrow the object in
context of the last associated cleanup that ran to completion.
@node Free Store, Concept Index, Exception Handling, Top
@section Free Store
......
......@@ -574,6 +574,12 @@ emit_base_init (t, immediately)
tree base = current_class_decl;
tree base_binfo = TREE_VEC_ELT (binfos, i);
#if 0 /* Once unsharing happens soon enough. */
my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
#else
BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
#endif
if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
{
if (! TREE_VIA_VIRTUAL (base_binfo)
......@@ -1210,7 +1216,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
if (parms)
init = TREE_VALUE (parms);
}
else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
{
rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
TREE_USED (rval) = 1;
......@@ -2932,11 +2939,8 @@ build_new (placement, decl, init, use_global_new)
}
if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
{
pedwarn ("const and volatile types cannot be created with operator new");
type = true_type = TYPE_MAIN_VARIANT (type);
}
type = TYPE_MAIN_VARIANT (type);
/* If our base type is an array, then make sure we know how many elements
it has. */
while (TREE_CODE (true_type) == ARRAY_TYPE)
......@@ -3000,7 +3004,7 @@ build_new (placement, decl, init, use_global_new)
rval = convert (TYPE_POINTER_TO (true_type), rval);
}
else if (! has_array && flag_this_is_variable > 0
&& TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
&& TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
{
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
rval = NULL_TREE;
......@@ -3061,57 +3065,8 @@ build_new (placement, decl, init, use_global_new)
build_tree_list (NULL_TREE, rval)));
}
/* We've figured out where the allocation is to go.
If we're not eliding constructors, then if a constructor
is defined, we must go through it. */
if (!has_array && (rval == NULL_TREE || !flag_elide_constructors)
&& TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
{
tree newrval;
/* Constructors are never virtual. If it has an initialization, we
need to complain if we aren't allowed to use the ctor that took
that argument. */
int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
/* If a copy constructor might work, set things up so that we can
try that after this. We deliberately don't clear LOOKUP_COMPLAIN
any more, since that would make it impossible to rationally use
the access of a constructor that matches perfectly. */
#if 0
if (rval != NULL_TREE)
flags |= LOOKUP_SPECULATIVELY;
#endif
if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
{
init = tree_cons (NULL_TREE, integer_one_node, init);
flags |= LOOKUP_HAS_IN_CHARGE;
}
{
tree tmp = rval;
if (tmp && TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE)
tmp = build_indirect_ref (tmp, NULL_PTR);
newrval = build_method_call (tmp, constructor_name_full (true_type),
init, NULL_TREE, flags);
}
if (newrval)
{
rval = newrval;
TREE_HAS_CONSTRUCTOR (rval) = 1;
}
else
rval = error_mark_node;
goto done;
}
if (rval == error_mark_node)
return error_mark_node;
rval = save_expr (rval);
TREE_HAS_CONSTRUCTOR (rval) = 1;
/* Don't call any constructors or do any initialization. */
if (init == void_type_node)
......@@ -3123,20 +3078,60 @@ build_new (placement, decl, init, use_global_new)
{
/* New 2.0 interpretation: `new int (10)' means
allocate an int, and initialize it with 10. */
tree deref;
rval = save_expr (rval);
deref = build_indirect_ref (rval, NULL_PTR);
TREE_READONLY (deref) = 0;
init = build_c_cast (type, init, 1);
if (TREE_CHAIN (init) != NULL_TREE)
pedwarn ("initializer list being treated as compound expression");
init = build_compound_expr (init);
init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL,
"new", NULL_TREE, 0);
rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
build_modify_expr (build_indirect_ref (rval, NULL_PTR),
NOP_EXPR, init),
build_modify_expr (deref, NOP_EXPR, init),
rval);
TREE_SIDE_EFFECTS (rval) = 1;
TREE_CALLS_NEW (rval) = 1;
}
else if (! has_array)
{
tree newrval;
/* Constructors are never virtual. If it has an initialization, we
need to complain if we aren't allowed to use the ctor that took
that argument. */
int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
{
init = tree_cons (NULL_TREE, integer_one_node, init);
flags |= LOOKUP_HAS_IN_CHARGE;
}
newrval = rval;
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
newrval = build_indirect_ref (newrval, NULL_PTR);
newrval = build_method_call (newrval, constructor_name_full (true_type),
init, NULL_TREE, flags);
if (newrval)
{
rval = newrval;
TREE_HAS_CONSTRUCTOR (rval) = 1;
}
else
rval = error_mark_node;
}
else if (current_function_decl == NULL_TREE)
{
extern tree static_aggregates;
/* In case of static initialization, SAVE_EXPR is good enough. */
rval = save_expr (rval);
init = copy_to_permanent (init);
rval = copy_to_permanent (rval);
static_aggregates = perm_tree_cons (init, rval, static_aggregates);
......@@ -3156,12 +3151,11 @@ build_new (placement, decl, init, use_global_new)
/* As a matter of principle, `start_sequence' should do this. */
emit_note (0, -1);
if (has_array)
rval = expand_vec_init (decl, rval,
build_binary_op (MINUS_EXPR, nelts, integer_one_node, 1),
init, 0);
else
expand_aggr_init (build_indirect_ref (rval, NULL_PTR), init, 0, 0);
rval = save_expr (rval);
rval = expand_vec_init (decl, rval,
build_binary_op (MINUS_EXPR, nelts,
integer_one_node, 1),
init, 0);
do_pending_stack_adjust ();
......@@ -3185,13 +3179,15 @@ build_new (placement, decl, init, use_global_new)
rval = xval;
}
}
else if (TYPE_READONLY (true_type))
cp_error ("uninitialized const in `new' of `%#T'", true_type);
done:
if (flag_check_new && alloc_expr && rval != alloc_expr)
{
tree ifexp = build_binary_op (NE_EXPR, alloc_expr, integer_zero_node, 1);
rval = build_conditional_expr (ifexp, rval, convert (TREE_TYPE (rval),
integer_zero_node));
rval = build_conditional_expr (ifexp, rval, alloc_expr);
}
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
......
......@@ -1539,7 +1539,7 @@ reinit_parse_for_method (yychar, decl)
t->can_free = 1;
t->deja_vu = 0;
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface ();
warn_if_unknown_interface (decl);
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (decl, t);
}
......@@ -1700,8 +1700,8 @@ reinit_parse_for_block (yychar, obstackp, is_template)
When KIND == 6, build default operator = (X&). */
tree
cons_up_default_function (type, name, kind)
tree type, name;
cons_up_default_function (type, full_name, kind)
tree type, full_name;
int kind;
{
extern tree void_list_node;
......@@ -1712,8 +1712,8 @@ cons_up_default_function (type, name, kind)
tree argtype;
int retref = 0;
int complex = 0;
tree name = constructor_name (full_name);
name = constructor_name (name);
switch (kind)
{
/* Destructors. */
......@@ -1750,7 +1750,7 @@ cons_up_default_function (type, name, kind)
/* Fall through... */
case 6:
retref = 1;
declspecs = build_decl_list (NULL_TREE, name);
declspecs = build_decl_list (NULL_TREE, full_name);
name = ansi_opname [(int) MODIFY_EXPR];
......
......@@ -2069,7 +2069,9 @@ do_build_copy_constructor (fndecl)
t = TREE_CHAIN (t))
{
tree basetype = BINFO_TYPE (t);
tree p = convert (build_reference_type (basetype), parm);
tree p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
......@@ -2079,10 +2081,12 @@ do_build_copy_constructor (fndecl)
{
tree p, basetype = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (basetype))
continue;
continue;
basetype = BINFO_TYPE (basetype);
p = convert (build_reference_type (basetype), parm);
p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
......@@ -2153,7 +2157,9 @@ do_build_assign_ref (fndecl)
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (TYPE_HAS_ASSIGN_REF (basetype))
{
tree p = convert (build_reference_type (basetype), parm);
tree p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
p = build_member_call (TYPE_NESTED_NAME (basetype),
ansi_opname [MODIFY_EXPR],
......
......@@ -280,7 +280,7 @@ empty_parms ()
/* Used in lex.c for parsing pragmas. */
%token END_OF_LINE
/* spew.c depends on this being the last token. Define
/* lex.c and pt.c depends on this being the last token. Define
any new tokens before this one! */
%token END_OF_SAVED_INPUT
......@@ -940,8 +940,7 @@ paren_expr_or_null:
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' expr ')'
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
bool_truthvalue_conversion ($2)); }
{ $$ = condition_conversion ($2); }
;
paren_cond_or_null:
......@@ -950,16 +949,14 @@ paren_cond_or_null:
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' condition ')'
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
bool_truthvalue_conversion ($2)); }
{ $$ = condition_conversion ($2); }
;
xcond:
/* empty */
{ $$ = NULL_TREE; }
| condition
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
bool_truthvalue_conversion ($$)); }
{ $$ = condition_conversion ($$); }
| error
{ $$ = NULL_TREE; }
;
......@@ -1800,6 +1797,7 @@ type_id:
typed_declspecs:
typed_typespecs %prec EMPTY
| typed_declspecs1
;
typed_declspecs1:
declmods typespec
......@@ -2151,9 +2149,9 @@ structsp:
{ $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE);
check_for_missing_semicolon ($$); }
| ENUM identifier
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
| ENUM complex_type_name
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly opt.component_decl_list '}'
......@@ -2206,16 +2204,11 @@ structsp:
check_for_missing_semicolon ($$); }
| class_head %prec EMPTY
{
#if 0
/* It's no longer clear what the following error is supposed to
accomplish. If it turns out to be needed, add a comment why. */
if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$))
{
error ("incomplete definition of type `%s'",
TYPE_NAME_STRING ($$));
$$ = error_mark_node;
}
#endif
/* struct B: public A; is not accepted by the WP grammar. */
if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)
&& ! TYPE_BEING_DEFINED ($$))
cp_error ("base clause without member specification for `%#T'",
$$);
}
;
......@@ -2257,6 +2250,12 @@ named_class_head_sans_basetype:
{ current_aggr = $$; $$ = $2; }
| aggr template_type %prec EMPTY
{ current_aggr = $$; $$ = $2; }
| specialization
;
named_class_head_sans_basetype_defn:
aggr identifier_defn %prec EMPTY
{ current_aggr = $$; $$ = $2; }
| aggr template_type_name '{'
{ yyungetc ('{', 1);
aggr2:
......@@ -2265,37 +2264,21 @@ named_class_head_sans_basetype:
overload_template_name ($$, 0); }
| aggr template_type_name ':'
{ yyungetc (':', 1); goto aggr2; }
| specialization
;
named_class_head_sans_basetype_defn:
aggr identifier_defn %prec EMPTY
{ current_aggr = $$; $$ = $2; }
;
do_xref: /* empty */ %prec EMPTY
{ $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 1); }
do_xref_defn: /* empty */ %prec EMPTY
{ $<ttype>$ = xref_defn_tag (current_aggr, $<ttype>0, NULL_TREE); }
{ $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
;
named_class_head:
named_class_head_sans_basetype do_xref
maybe_base_class_list %prec EMPTY
{
if ($3)
$$ = xref_tag (current_aggr, $1, $3, 1);
else
$$ = $<ttype>2;
}
|
named_class_head_sans_basetype_defn do_xref_defn
maybe_base_class_list %prec EMPTY
{
named_class_head_sans_basetype %prec EMPTY
{ $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
| named_class_head_sans_basetype_defn do_xref_defn
maybe_base_class_list %prec EMPTY
{
$$ = $<ttype>2;
if ($3)
$$ = xref_defn_tag (current_aggr, $1, $3);
else
$$ = $<ttype>2;
xref_basetypes (current_aggr, $1, $<ttype>2, $3);
}
;
......@@ -3472,8 +3455,12 @@ handler_seq:
/* empty */
| handler_seq CATCH
{ emit_line_note (input_filename, lineno); }
handler_args compstmt
{ expand_end_catch_block (); }
.pushlevel handler_args compstmt
{ expand_end_catch_block ();
expand_end_bindings (getdecls (), kept_level_p (), 1);
poplevel (kept_level_p (), 1, 0);
pop_momentary ();
}
;
type_specifier_seq:
......
......@@ -128,6 +128,7 @@ process_template_parm (list, next)
defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
}
}
SET_DECL_ARTIFICIAL (decl);
pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm);
......@@ -238,8 +239,10 @@ end_template_decl (d1, d2, is_class, defn)
DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
DECL_NAME (decl) = DECL_NAME (d2);
TREE_TYPE (decl) = TREE_TYPE (d2);
if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface ();
if (interface_unknown && flag_external_templates
&& ! flag_alt_external_templates
&& ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface (decl);
TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;
DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
&& !(DECL_CLASS_CONTEXT (d2)
......@@ -690,6 +693,7 @@ push_template_decls (parmlist, arglist, class_level)
}
if (decl != 0)
{
SET_DECL_ARTIFICIAL (decl);
layout_decl (decl, 0);
if (class_level)
pushdecl_class_level (decl);
......@@ -1755,7 +1759,7 @@ instantiate_template (tmpl, targ_ptr)
= CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
}
else if (! DECL_IN_SYSTEM_HEADER (tmpl))
warn_if_unknown_interface ();
warn_if_unknown_interface (tmpl);
}
if (interface_unknown || ! flag_external_templates)
......@@ -1850,7 +1854,7 @@ overload_template_name (id, classlevel)
}
#endif
t = xref_tag (tinfo->aggr, id, NULL_TREE, 0);
t = xref_tag (tinfo->aggr, id, NULL_TREE, 1);
my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
|| TREE_CODE (t) == UNION_TYPE
|| TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
......
......@@ -32,6 +32,79 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Lvalues can have their address taken, unless they have DECL_REGISTER. */
int
real_lvalue_p (ref)
tree ref;
{
if (! language_lvalue_valid (ref))
return 0;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
if (ref == current_class_decl && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
return 1;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 1))
&& real_lvalue_p (TREE_OPERAND (ref, 2)));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 1));
case MAX_EXPR:
case MIN_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1)));
}
return 0;
}
int
lvalue_p (ref)
tree ref;
{
......@@ -496,6 +569,7 @@ propagate_binfo_offsets (binfo, offset)
chain = TREE_VEC_ELT (base_binfos, k);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
}
/* Now propagate the offset to the base types. */
propagate_binfo_offsets (base_binfo, offset);
......@@ -616,6 +690,8 @@ layout_vbasetypes (rec, max)
{
tree base_binfos = BINFO_BASETYPES (vbase_types);
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
if (base_binfos)
{
tree chain = NULL_TREE;
......@@ -636,6 +712,7 @@ layout_vbasetypes (rec, max)
chain = TREE_VEC_ELT (base_binfos, j);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = vbase_types;
}
propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
......@@ -1169,22 +1246,6 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
return new_binfo;
}
tree
copy_binfo (list)
tree list;
{
tree binfo = copy_list (list);
tree rval = binfo;
while (binfo)
{
TREE_USED (binfo) = 0;
if (BINFO_BASETYPES (binfo))
BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo));
binfo = TREE_CHAIN (binfo);
}
return rval;
}
/* Return the binfo value for ELEM in TYPE. */
tree
......
......@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 363. Free: */
/* First used: 0 (reserved), Last used: 364. Free: */
static int abortcount = 0;
......@@ -379,65 +379,131 @@ my_friendly_assert (cond, where)
for use in initializing a static variable; one that can be an
element of a "constant" initializer.
Return 1 if the value is absolute; return 2 if it is relocatable.
Return null_pointer_node if the value is absolute;
if it is relocatable, return the variable that determines the relocation.
We assume that VALUE has been folded as much as possible;
therefore, we do not need to check for such things as
arithmetic-combinations of integers. */
static int
initializer_constant_valid_p (value)
tree
initializer_constant_valid_p (value, endtype)
tree value;
tree endtype;
{
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
return TREE_STATIC (value);
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
&& TREE_CONSTANT (value))
return
initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
endtype);
return TREE_STATIC (value) ? null_pointer_node : 0;
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
return 1;
case COMPLEX_CST:
return null_pointer_node;
case ADDR_EXPR:
return 2;
return TREE_OPERAND (value, 0);
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
case CONVERT_EXPR:
case NOP_EXPR:
/* Allow conversions between types of the same kind. */
if (TREE_CODE (TREE_TYPE (value))
== TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0));
/* Allow conversions between pointer types. */
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow conversions between real types. */
if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow length-preserving conversions between integer types. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (value))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow conversions between other integer types only if
explicit value. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
{
tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
if (inner == null_pointer_node)
return null_pointer_node;
return 0;
}
/* Allow (int) &foo provided int is as wide as a pointer. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
&& ! tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (value)),
TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0));
&& (TYPE_PRECISION (TREE_TYPE (value))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
/* Likewise conversions from int to pointers. */
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (value))
<= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
/* Allow conversions to union types if the value inside is okay. */
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
return 0;
case PLUS_EXPR:
if (TREE_CODE (endtype) == INTEGER_TYPE
&& TYPE_PRECISION (endtype) < POINTER_SIZE)
return 0;
{
int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
if (valid0 == 1 && valid1 == 2)
return 2;
if (valid0 == 2 && valid1 == 1)
return 2;
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
endtype);
/* If either term is absolute, use the other terms relocation. */
if (valid0 == null_pointer_node)
return valid1;
if (valid1 == null_pointer_node)
return valid0;
return 0;
}
case MINUS_EXPR:
if (TREE_CODE (endtype) == INTEGER_TYPE
&& TYPE_PRECISION (endtype) < POINTER_SIZE)
return 0;
{
int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
if (valid0 == 2 && valid1 == 1)
return 2;
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
endtype);
/* Win if second argument is absolute. */
if (valid1 == null_pointer_node)
return valid0;
/* Win if both arguments have the same relocation.
Then the value is absolute. */
if (valid0 == valid1)
return null_pointer_node;
return 0;
}
default:
return 0;
}
return 0;
}
/* Perform appropriate conversions on the initial value of a variable,
......@@ -583,7 +649,7 @@ store_init_value (decl, init)
;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))
#if 0
/* A STATIC PUBLIC int variable doesn't have to be
run time inited when doing pic. (mrs) */
......@@ -920,7 +986,7 @@ process_init_constructor (type, init, elts)
erroneous = 1;
else if (!TREE_CONSTANT (next1))
allconstant = 0;
else if (! initializer_constant_valid_p (next1))
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
members = tree_cons (NULL_TREE, next1, members);
}
......@@ -984,7 +1050,7 @@ process_init_constructor (type, init, elts)
erroneous = 1;
else if (!TREE_CONSTANT (next1))
allconstant = 0;
else if (! initializer_constant_valid_p (next1))
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
members = tree_cons (field, next1, members);
}
......@@ -1001,7 +1067,7 @@ process_init_constructor (type, init, elts)
erroneous = 1;
else if (!TREE_CONSTANT (next1))
allconstant = 0;
else if (! initializer_constant_valid_p (next1))
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
members = tree_cons (field, next1, members);
}
......@@ -1082,7 +1148,7 @@ process_init_constructor (type, init, elts)
erroneous = 1;
else if (!TREE_CONSTANT (next1))
allconstant = 0;
else if (initializer_constant_valid_p (next1) == 0)
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
allsimple = 0;
members = tree_cons (field, next1, members);
}
......@@ -1425,11 +1491,13 @@ build_functional_cast (exp, parms)
/* this must build a C cast */
if (parms == NULL_TREE)
parms = integer_zero_node;
else if (TREE_CHAIN (parms) != NULL_TREE)
else
{
pedwarn ("initializer list being treated as compound expression");
if (TREE_CHAIN (parms) != NULL_TREE)
pedwarn ("initializer list being treated as compound expression");
parms = build_compound_expr (parms);
}
return build_c_cast (type, parms, 1);
}
......
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