Commit 8ccc31eb by Mike Stump

56th Cygnus<->FSF merge

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