56th Cygnus<->FSF merge

From-SVN: r8957
This commit is contained in:
Mike Stump 1995-02-16 15:24:37 +00:00
parent 3a5ece659c
commit 8ccc31eb61
18 changed files with 1235 additions and 700 deletions

View File

@ -10,6 +10,306 @@ Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
* class.c (instantiate_type): Change error message text.
* typeck2.c (store_init_value): Likewise.
Thu Feb 16 03:28:49 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine
whether an enumerated type fits in a bitfield.
Wed Feb 15 15:38:12 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* class.c (grow_method): Update method_vec after growing the class
obstack.
Wed Feb 15 13:42:59 1995 Mike Stump <mrs@cygnus.com>
* parse.y (handler_seq): Push a level for the catch parameters.
Wed Feb 15 12:42:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my
bases, in case they've been clobbered.
Wed Feb 15 12:07:29 1995 Mike Stump <mrs@cygnus.com>
* class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here,
so that one day it will always be valid.
* tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto.
* cp-tree.h (copy_binfo): Removed, unused.
* tree.c (copy_binfo): Ditto.
Wed Feb 15 00:05:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (build_new): Save the allocation before calling
expand_vec_init on it.
* decl.c (finish_enum): The TYPE_PRECISION of the enum type mush
match the TYPE_PRECISION of the underlying type for constant folding
to work.
Tue Feb 14 15:31:25 1995 Mike Stump <mrs@cygnus.com>
* except.c (push_eh_entry, expand_start_all_catch,
expand_leftover_cleanups, expand_end_catch_block): Keep track of
the context in which the exception region occurs.
(build_exception_table): If the region was not output, don't output
the entry in the eh table for it.
Tue Feb 14 02:15:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (expand_default_init): Only use a previous constructor call
if it's a call to our constructor. Does the word "Duh" mean
anything to you?
* decl.c (grokparms): Fine, just don't call
convert_for_initialization at all. OK? Happy now?
Mon Feb 13 02:23:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class
method vector has a second element before returning it.
* decl.c (grokparms): Don't strip REFERENCE_TYPE before calling
convert_for_initialization.
Sun Feb 12 03:57:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_modify_expr): Compare function name to
constructor_name (current_class_type) instead of current_class_name.
* decl.c (grokparms): Don't do anything with the return value of
convert_for_initialization.
* error.c (dump_decl): Also dump_readonly_or_volatile on the decl.
* decl.c (duplicate_decls): Tweak error message.
* typeck.c (build_const_cast): Implement checking.
(build_reinterpret_cast): Implement some checking.
* cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when
converting to the same aggregate type.
(CONV_STATIC_CAST): Include it.
(CONV_C_CAST): Ditto.
* cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT.
(cp_convert): Only force a new temporary if CONV_FORCE_TEMP.
Fri Feb 10 16:18:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_c_cast): Use non_lvalue to tack something on
where necessary.
* decl.c (auto_function): Now a function.
* except.c (init_exception_processing): terminate, unexpected,
set_terminate, and set_unexpected have C++ linkage.
* typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of
truthvalue_conversion for converting to bool, as it handles
user-defined conversions properly.
(condition_conversion): Ditto.
* except.c (expand_throw): Don't call convert_to_reference.
Pass the correct parameters to build_new.
* method.c (do_build_assign_ref): Don't use access control when
converting to a base reference here.
(do_build_copy_constructor): Or here.
* init.c (build_new): Unset TREE_READONLY on the dereferenced
pointer before assigning to it.
* decl.c (maybe_build_cleanup): Don't bother stripping const here.
* decl2.c (delete_sanity): You can now delete pointer to const.
Fri Feb 10 13:28:38 1995 Jason Merrill <jason@python.cygnus.com>
* decl.c (finish_function): Don't rely on actual parameters being
evaluated left-to-right.
* except.c (expand_end_catch_block): Ditto.
Fri Feb 10 00:52:04 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't
considered lvalues.
* cvt.c (convert_to_reference): Use real_lvalue_p instead of
lvalue_p.
* cvt.c (build_type_conversion_1): Don't call convert on aggregate
types.
(convert_to_reference): Fix erroneous text substitution.
* typeck2.c (initializer_constant_valid_p): Update from C frontend.
Add new argument to all callers.
* typeck.c (convert_arguments): Check for error_mark_node before
trying to do anything with the actual parameter.
* typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and
fold it.
(bool_truthvalue_conversion): Remove. Fix all callers to call
truthvalue_conversion instead.
(various): Fold CLEANUP_POINT_EXPRs.
* parse.y (conditions): Call condition_conversion rather than
building up a CLEANUP_POINT_EXPR.
* pt.c (end_template_decl): Don't warn_if_unknown_interface here
under -falt-external-templates.
Thu Feb 9 05:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (build_new): Complain about new of const type without
initializer. Other cleanup.
* call.c (compute_conversion_costs): Don't call
build_type_conversion with a reference type; convert to the target
type and check its lvaluetude.
* cvt.c (convert_to_reference): Ditto.
* cvt.c (build_type_conversion_1): There will never be any need to
dereference references here now.
Thu Feb 9 00:37:47 1995 Mike Stump <mrs@cygnus.com>
* except.c (expand_builtin_throw): Make sure we only `use' the
value of return_val_rtx.
Wed Feb 8 15:45:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* parse.y (structsp): Don't complain about declaring a type being
defined to be a friend.
* decl2.c (warn_if_unknown_interface): Note the template in question
and the point of instantiation, for -falt-external-templates.
* lex.c (reinit_parse_for_method): Pass the decl to
warn_if_unknown_interface.
* pt.c (instantiate_template): Ditto.
(end_template_decl): Ditto.
* decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the
nested name again, to make local classes work a bit better.
* typeck.c (build_function_call_real): Dereference reference after
checking for incomplete type.
* init.c (build_new): Accept new of const and volatile types.
Wed Feb 8 14:04:16 1995 Jason Merrill <jason@deneb.cygnus.com>
* decl.c (grokdeclarator): Fix error message.
Wed Feb 8 03:16:15 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (convert_for_initialization): Do bash arrays when
converting to a reference to non-array.
Tue Feb 7 15:50:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cvt.c (cp_convert): Don't call convert_to_reference, or
automatically dereference references. Do pass reference conversions
to cp_convert_to_pointer.
(cp_convert_to_pointer): Support references.
* call.c (build_method_call): Don't build up a reference to the
parameter here; let build_overload_call handle that.
* typeck.c (build_c_cast): Call convert_to_reference directly if
converting to a reference type.
* method.c (do_build_copy_constructor): Ditto.
* method.c (do_build_copy_constructor): Ditto.
(do_build_assign_ref): Ditto.
* call.c (build_method_call): Dereference a returned reference.
* typeck.c (build_function_call_real): Ditto.
* decl.c (xref_basetypes): Check for unions with basetypes here.
(xref_tag): Instead of here.
* pt.c (process_template_parm): Template type parm decls are
artificial.
Mon Feb 6 04:32:09 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* parse.y (typed_declspecs): Add missing semicolon.
(do_xref_defn): Resurrect.
(named_class_head_sans_basetype): Move template specialization
definition cases to named_class_head_sans_basetype_defn.
* decl2.c (grokfield): Call pushdecl_class_level after setting the
TYPE_NAME, not before.
Sun Feb 5 02:50:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (convert_harshness): Don't call sorry here. Don't allow
conversions between function pointer types if pedantic.
* pt.c (overload_template_name): Pass globalize=1 to xref_tag.
* lex.c (cons_up_default_function): Use the full name for the return
type of op=.
* decl.c (set_nested_typename): Don't worry about anonymous types,
as they already have a unique name.
(pushdecl): Remove redundant set_nested_typename
(xref_tag): Split out base handling into xref_basetypes.
* cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are
not considered incomplete even though their definition is unknown.
* decl.c (xref_defn_tag): Lose.
(xref_tag): xref_next_defn = ! globalize.
(pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls. The
ones that should have it set will have it set by pushtag.
(pushdecl_class_level): Ditto.
(pushtag): Tidy up a bit.
(set_nested_typename): Push a decl for the nested typename from
here, rather than from xref_defn_tag.
* parse.y (do_xref): Lose.
(named_class_head): If we see 'class foo:' we know it's a
definition, so don't worry about base lists for non-definitions.
* pt.c (push_template_decls): Template parm decls are artificial.
* decl.c (duplicate_decls): Restore check for qualifier
disagreement for non-functions.
(decls_match): Remove check for qualifier disagreement.
Fri Feb 3 14:58:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (grok_reference_init): Convert initializer from
reference.
* typeck.c (convert_for_initialization): Ditto.
* decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME.
* cvt.c (cp_convert): Don't convert to the same class type by just
tacking on a NOP_EXPR.
(convert_to_reference): Use comp_target_types instead of comptypes
so that we don't allow conversions two levels down.
Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* class.c (build_vbase_path): Bash types to make the backend happy.
* cvt.c (build_up_reference): Bash the types bashed by
build_vbase_path to be reference types instead of pointer types.
(convert_to_reference): Ditto.
* typeck.c (build_c_cast): Don't strip NOPs if we're converting to a
reference type.
* parse.y (structsp): Put back error for 'struct B: public A;'.
Wed Feb 1 23:02:06 1995 Mike Stump <mrs@cygnus.com>
* except.c: Add support for mips systems that don't define __mips
but do define mips, like Ultrix.
Wed Feb 1 22:39:07 1995 Mike Stump <mrs@cygnus.com>
* except.c: Add support for exception handling on the Alpha.
Wed Feb 1 10:12:14 1995 Mike Stump <mrs@cygnus.com>
* decl2.c (finish_file): Fix bug in Jan 31st change.

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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));

View File

@ -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)

View File

@ -121,17 +121,6 @@ static struct stack_level *decl_stack;
#define WCHAR_TYPE "int"
#endif
#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
#define auto_function(NAME, TYPE, CODE) \
do { \
tree __name = NAME; \
tree __type = TYPE; \
define_function (IDENTIFIER_POINTER (__name), __type, CODE, \
(void (*)())push_overloaded_decl_1, \
IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\
} while (0)
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message PROTO((tree, tree));
@ -1647,6 +1636,14 @@ set_nested_typename (decl, classname, name, type)
{
char *buf;
my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
/* No need to do this for anonymous names, since they're unique. */
if (ANON_AGGRNAME_P (name))
{
DECL_NESTED_TYPENAME (decl) = name;
return;
}
if (classname == NULL_TREE)
classname = get_identifier ("");
@ -1659,11 +1656,27 @@ set_nested_typename (decl, classname, name, type)
DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
/* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
correspondence in any binding_level. This is ok since the
DECL_NESTED_TYPENAME is just a convenience identifier whose
IDENTIFIER_TYPE_VALUE will remain constant from now on. */
SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
/* Create an extra decl so that the nested name will have a type value
where appropriate. */
{
tree nested, type_decl;
nested = DECL_NESTED_TYPENAME (decl);
type_decl = build_decl (TYPE_DECL, nested, type);
DECL_NESTED_TYPENAME (type_decl) = nested;
SET_DECL_ARTIFICIAL (type_decl);
#ifdef DWARF_DEBUGGING_INFO
/* Mark the TYPE_DECL node created just above as a
gratuitous one so that dwarfout.c will know not to
generate a TAG_typedef DIE for it. */
if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */
/* Remove this when local classes are fixed. */
SET_IDENTIFIER_TYPE_VALUE (nested, type);
pushdecl_nonclass_level (type_decl);
}
}
/* Pop off extraneous binding levels left over due to syntax errors. */
@ -1820,7 +1833,7 @@ pushtag (name, type, globalize)
}
#endif /* DWARF_DEBUGGING_INFO */
TYPE_NAME (type) = d;
TYPE_MAIN_DECL (type) = d;
/* Make sure we're in this type's scope when we push the
decl for a template, otherwise class_binding_level will
@ -1832,37 +1845,31 @@ pushtag (name, type, globalize)
if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
popclass (0);
}
if (write_symbols != DWARF_DEBUG)
{
if (ANON_AGGRNAME_P (name))
DECL_IGNORED_P (d) = 1;
}
if (context == NULL_TREE)
/* Non-nested class. */
set_nested_typename (d, NULL_TREE, name, type);
else if (context && TREE_CODE (context) == FUNCTION_DECL)
{
/* Function-nested class. */
set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
name, type);
/* This builds the links for classes nested in fn scope. */
DECL_CONTEXT (d) = context;
}
/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
*/
else if (context && IS_AGGR_TYPE (context))
{
/* Class-nested class. */
set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
name, type);
/* This builds the links for classes nested in type scope. */
DECL_CONTEXT (d) = context;
}
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
if (newdecl)
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
{
if (write_symbols != DWARF_DEBUG)
{
if (ANON_AGGRNAME_P (name))
DECL_IGNORED_P (d) = 1;
}
if (context == NULL_TREE)
/* Non-nested class. */
set_nested_typename (d, NULL_TREE, name, type);
else if (context && TREE_CODE (context) == FUNCTION_DECL)
/* Function-nested class. */
set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
name, type);
else /* if (context && IS_AGGR_TYPE (context)) */
/* Class-nested class. */
set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
name, type);
DECL_CONTEXT (d) = context;
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
{
@ -2042,9 +2049,7 @@ decls_match (newdecl, olddecl)
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
types_match = (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1)
&& TREE_READONLY (newdecl) == TREE_READONLY (olddecl)
&& TREE_THIS_VOLATILE (newdecl) == TREE_THIS_VOLATILE (olddecl));
types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
}
return types_match;
@ -2312,6 +2317,13 @@ duplicate_decls (newdecl, olddecl)
}
}
}
/* These bits are logically part of the type for non-functions. */
else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
{
cp_pedwarn ("type qualifiers for `%#D'", newdecl);
cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
}
}
/* If new decl is `static' and an `extern' was seen previously,
@ -2347,6 +2359,8 @@ duplicate_decls (newdecl, olddecl)
register tree newtype = TREE_TYPE (newdecl);
register tree oldtype = TREE_TYPE (olddecl);
DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl);
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
{
@ -2826,6 +2840,7 @@ pushdecl (x)
{
tree tname = DECL_NAME (name);
/* This is a disgusting kludge for dealing with UPTs. */
if (global_bindings_p () && ANON_AGGRNAME_P (tname))
{
/* do gratuitous C++ typedefing, and make sure that
@ -2837,7 +2852,10 @@ pushdecl (x)
}
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
if (! DECL_NESTED_TYPENAME (x))
/* Don't set nested_typename on template type parms, for instance.
Any artificial decls that need DECL_NESTED_TYPENAME will have it
set in pushtag. */
if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
set_nested_typename (x, current_class_name, DECL_NAME (x), type);
if (type != error_mark_node
@ -3056,16 +3074,6 @@ pushdecl (x)
}
}
if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE)
{
if (current_class_name)
{
if (! TREE_MANGLED (name))
set_nested_typename (x, current_class_name, DECL_NAME (x),
TREE_TYPE (x));
}
}
/* Put decls on list in reverse order.
We will reverse them later if necessary. */
TREE_CHAIN (x) = b->names;
@ -3190,7 +3198,11 @@ pushdecl_class_level (x)
if (TREE_CODE (x) == TYPE_DECL)
{
set_identifier_type_value (name, TREE_TYPE (x));
if (!DECL_NESTED_TYPENAME (x))
/* Don't set nested_typename on template type parms, for instance.
Any artificial decls that need DECL_NESTED_TYPENAME will have it
set in pushtag. */
if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
}
}
@ -4259,6 +4271,22 @@ push_overloaded_decl_1 (x)
push_overloaded_decl (x, 0);
}
#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
#ifdef __GNUC__
__inline
#endif
tree auto_function (name, type, code)
tree name, type;
enum built_in_function code;
{
return define_function
(IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1,
IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
0)));
}
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *)0).
Initialize the global binding level.
@ -5733,6 +5761,9 @@ grok_reference_init (decl, type, init, cleanupp)
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
init = convert_from_reference (init);
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
{
@ -7442,7 +7473,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
|| id == ridpointers[(int) RID_WCHAR])
{
if (type)
error ("extraneous `%T' ignored", id);
{
if (id == ridpointers[(int) RID_BOOL])
error ("`bool' is now a keyword");
else
cp_error ("extraneous `%T' ignored", id);
}
else
{
if (id == ridpointers[(int) RID_INT])
@ -9558,17 +9594,7 @@ grokparms (first_parm, funcdef_flag)
}
else
init = require_instantiated_type (type, init, integer_zero_node);
/* Don't actually try to build up a reference here. */
{
tree t = type;
if (TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
init = convert_for_initialization
(NULL_TREE, t, init, LOOKUP_NORMAL,
"argument passing", 0, 0);
}
}
}
#if 0 /* This is too early to check; trailing parms might be merged in by
duplicate_decls. */
else if (any_init)
@ -9961,73 +9987,6 @@ grok_op_properties (decl, virtualp, friendp)
the current frame for the name (since C++ allows new names in any
scope.) */
/* avoid rewriting all callers of xref_tag */
static int xref_next_defn = 0;
tree
xref_defn_tag (code_type_node, name, binfo)
tree code_type_node;
tree name, binfo;
{
tree rv, ncp;
xref_next_defn = 1;
if (class_binding_level)
{
tree n1;
char *buf;
/* we need to build a new IDENTIFIER_NODE for name which nukes
* the pieces... */
/*
n1 = IDENTIFIER_LOCAL_VALUE (current_class_name);
if (n1)
n1 = DECL_NAME (n1);
else
n1 = current_class_name;
*/
n1 = TYPE_NAME (current_class_type);
if (n1)
n1 = DECL_NESTED_TYPENAME(n1);
else
n1 = current_class_name;
buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1)
+ IDENTIFIER_LENGTH (name));
sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1),
IDENTIFIER_POINTER (name));
ncp = get_identifier (buf);
#ifdef SPEW_DEBUG
if (spew_debug)
printf("*** %s ***\n", IDENTIFIER_POINTER (ncp));
#endif
#if 0
IDENTIFIER_LOCAL_VALUE (name) =
build_decl (TYPE_DECL, ncp, NULL_TREE);
#endif
rv = xref_tag (code_type_node, name, binfo, 0);
if (! ANON_AGGRNAME_P (name))
{
register tree type_decl = build_decl (TYPE_DECL, ncp, rv);
SET_DECL_ARTIFICIAL (type_decl);
#ifdef DWARF_DEBUGGING_INFO
/* Mark the TYPE_DECL node created just above as a gratuitous one
so that dwarfout.c will know not to generate a TAG_typedef DIE
for it. */
if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */
pushdecl_nonclass_level (type_decl);
}
}
else
{
rv = xref_tag (code_type_node, name, binfo, 0);
}
xref_next_defn = 0;
return rv;
}
tree
xref_tag (code_type_node, name, binfo, globalize)
tree code_type_node;
@ -10037,7 +9996,7 @@ xref_tag (code_type_node, name, binfo, globalize)
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
int i, len;
int i;
register tree ref, t;
struct binding_level *b = inner_binding_level;
@ -10048,16 +10007,9 @@ xref_tag (code_type_node, name, binfo, globalize)
case class_type:
case signature_type:
code = RECORD_TYPE;
len = list_length (binfo);
break;
case union_type:
code = UNION_TYPE;
if (binfo)
{
cp_error ("derived union `%T' invalid", name);
binfo = NULL_TREE;
}
len = 0;
break;
case enum_type:
code = ENUMERAL_TYPE;
@ -10072,18 +10024,12 @@ xref_tag (code_type_node, name, binfo, globalize)
if (t && TREE_CODE (t) != code)
t = NULL_TREE;
if (xref_next_defn)
if (! globalize)
{
/* If we know we are defining this tag, only look it up in this scope
* and don't try to find it as a type. */
xref_next_defn = 0;
if (t && TYPE_CONTEXT(t))
{
if (TREE_MANGLED (name))
ref = t;
else
ref = lookup_tag (code, name, b, 1);
}
if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name))
ref = t;
else
ref = lookup_tag (code, name, b, 1);
}
@ -10180,6 +10126,7 @@ xref_tag (code_type_node, name, binfo, globalize)
&& IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
#if 0
if (binfo)
{
tree tt1 = binfo;
@ -10202,128 +10149,11 @@ xref_tag (code_type_node, name, binfo, globalize)
build them on the permanent obstack. */
end_temporary_allocation ();
}
#endif
}
if (binfo)
{
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
tree binfos;
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
{
/* The base of a derived struct is public by default. */
int via_public
= (TREE_PURPOSE (binfo) == (tree)access_public
|| TREE_PURPOSE (binfo) == (tree)access_public_virtual
|| (tag_code != class_type
&& (TREE_PURPOSE (binfo) == (tree)access_default
|| TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
int via_virtual
= (TREE_PURPOSE (binfo) == (tree)access_private_virtual
|| TREE_PURPOSE (binfo) == (tree)access_public_virtual
|| TREE_PURPOSE (binfo) == (tree)access_default_virtual);
tree basetype = TREE_TYPE (TREE_VALUE (binfo));
tree base_binfo;
GNU_xref_hier (IDENTIFIER_POINTER (name),
IDENTIFIER_POINTER (TREE_VALUE (binfo)),
via_public, via_virtual, 0);
if (basetype && TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
{
error ("base type `%s' fails to be a struct or class type",
IDENTIFIER_POINTER (TREE_VALUE (binfo)));
continue;
}
#if 1
/* This code replaces similar code in layout_basetypes. */
else if (TYPE_SIZE (basetype) == NULL_TREE)
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
#endif
else
{
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
cp_error ("recursive type `%T' undefined", basetype);
else
cp_error ("duplicate base type `%T' invalid", basetype);
continue;
}
/* Note that the BINFO records which describe individual
inheritances are *not* shared in the lattice! They
cannot be shared because a given baseclass may be
inherited with different `accessibility' by different
derived classes. (Each BINFO record describing an
individual inheritance contains flags which say what
the `accessibility' of that particular inheritance is.) */
base_binfo = make_binfo (integer_zero_node, basetype,
TYPE_BINFO_VTABLE (basetype),
TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
TREE_VIA_PROTECTED (base_binfo) = via_protected;
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
SET_CLASSTYPE_MARKED (basetype);
#if 0
/* XYZZY TEST VIRTUAL BASECLASSES */
if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
&& via_virtual == 0)
{
warning ("making type `%s' a virtual baseclass",
TYPE_NAME_STRING (basetype));
via_virtual = 1;
}
#endif
/* We are free to modify these bits because they are meaningless
at top level, and BASETYPE is a top-level type. */
if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
i += 1;
}
}
if (i)
TREE_VEC_LENGTH (binfos) = i;
else
BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref)
= TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
/* Unmark all the types. */
while (--i >= 0)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
}
xref_basetypes (code_type_node, name, ref, binfo);
just_return:
@ -10344,6 +10174,145 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
return ref;
}
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
tree name, ref;
tree binfo;
{
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
tree binfos;
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
if (tag_code == union_type)
{
cp_error ("derived union `%T' invalid", ref);
return;
}
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
{
/* The base of a derived struct is public by default. */
int via_public
= (TREE_PURPOSE (binfo) == (tree)access_public
|| TREE_PURPOSE (binfo) == (tree)access_public_virtual
|| (tag_code != class_type
&& (TREE_PURPOSE (binfo) == (tree)access_default
|| TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
int via_virtual
= (TREE_PURPOSE (binfo) == (tree)access_private_virtual
|| TREE_PURPOSE (binfo) == (tree)access_public_virtual
|| TREE_PURPOSE (binfo) == (tree)access_default_virtual);
tree basetype = TREE_TYPE (TREE_VALUE (binfo));
tree base_binfo;
GNU_xref_hier (IDENTIFIER_POINTER (name),
IDENTIFIER_POINTER (TREE_VALUE (binfo)),
via_public, via_virtual, 0);
if (basetype && TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
{
cp_error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
continue;
}
#if 1
/* This code replaces similar code in layout_basetypes. */
else if (TYPE_INCOMPLETE (basetype))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
#endif
else
{
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
cp_error ("recursive type `%T' undefined", basetype);
else
cp_error ("duplicate base type `%T' invalid", basetype);
continue;
}
/* Note that the BINFO records which describe individual
inheritances are *not* shared in the lattice! They
cannot be shared because a given baseclass may be
inherited with different `accessibility' by different
derived classes. (Each BINFO record describing an
individual inheritance contains flags which say what
the `accessibility' of that particular inheritance is.) */
base_binfo = make_binfo (integer_zero_node, basetype,
TYPE_BINFO_VTABLE (basetype),
TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
TREE_VIA_PROTECTED (base_binfo) = via_protected;
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
SET_CLASSTYPE_MARKED (basetype);
#if 0
/* XYZZY TEST VIRTUAL BASECLASSES */
if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
&& via_virtual == 0)
{
warning ("making type `%s' a virtual baseclass",
TYPE_NAME_STRING (basetype));
via_virtual = 1;
}
#endif
/* We are free to modify these bits because they are meaningless
at top level, and BASETYPE is a top-level type. */
if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
i += 1;
}
}
if (i)
TREE_VEC_LENGTH (binfos) = i;
else
BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref)
= TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
/* Unmark all the types. */
while (--i >= 0)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
pop_obstacks ();
}
static tree current_local_enum = NULL_TREE;
@ -10452,19 +10421,23 @@ finish_enum (enumtype, values)
TYPE_SIZE (enumtype) = NULL_TREE;
/* Lay out the type as though it were an integer. */
if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node))
{
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
layout_type (enumtype);
}
/* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
TYPE_PRECISION (enumtype) = precision;
if (unsignedp)
fixup_unsigned_type (enumtype);
else
fixup_signed_type (enumtype);
if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
/* Use the width of the narrowest normal C type which is wide enough. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
(precision, 1));
else
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
}
if (flag_cadillac)
@ -11530,7 +11503,8 @@ finish_function (lineno, call_poplevel, nested)
if (call_poplevel)
{
expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 1, 0);
}
@ -12002,11 +11976,6 @@ maybe_build_cleanup (decl)
|| flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
/* Use TYPE_MAIN_VARIANT so we don't get a warning about
calling delete on a `const' variable. */
if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval))))
rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval);
rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
/* void (*pfvtype (void (*) ()))() */
tree pfvtype = build_function_type (PFV, pfvlist);
/* 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);
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);
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,
@ -843,6 +842,11 @@ init_exception_processing ()
saved_pc = gen_rtx (REG, Pmode, 7);
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);
@ -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 ();

View File

@ -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.
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.
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).
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

View File

@ -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;
init = build_c_cast (type, init, 1);
rval = save_expr (rval);
deref = build_indirect_ref (rval, NULL_PTR);
TREE_READONLY (deref) = 0;
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))

View File

@ -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];

View File

@ -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],

View File

@ -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
{
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_tag (current_aggr, $1, $3, 1);
else
$$ = $<ttype>2;
}
|
named_class_head_sans_basetype_defn do_xref_defn
maybe_base_class_list %prec EMPTY
{
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:

View File

@ -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);

View File

@ -31,6 +31,79 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Lvalues can be assigned, unless they have TREE_READONLY.
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

View File

@ -2382,11 +2382,13 @@ build_function_call_real (function, params, require_complete, flags)
function, coerced_params, NULL_TREE);
TREE_SIDE_EFFECTS (result) = 1;
if (! require_complete)
return result;
return convert_from_reference (result);
if (value_type == void_type_node)
return result;
return require_complete_type (result);
result = require_complete_type (result);
return convert_from_reference (result);
}
}
@ -2463,6 +2465,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
register tree type = typetail ? TREE_VALUE (typetail) : 0;
register tree val = TREE_VALUE (valtail);
if (val == error_mark_node)
continue;
if (type == void_type_node)
{
if (fndecl)
@ -2987,9 +2992,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
result_type = boolean_type_node;
op0 = bool_truthvalue_conversion (op0);
op1 = bool_truthvalue_conversion (op1);
converted = 1;
break;
/* Shift operations: result has same type as first operand;
@ -3779,17 +3781,17 @@ build_x_unary_op (code, xarg)
return build_unary_op (code, xarg, 0);
}
/* Just like truthvalue_conversion, but we want a BOOLEAN_TYPE */
/* Just like truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */
tree
bool_truthvalue_conversion (expr)
condition_conversion (expr)
tree expr;
{
/* We really want to preform the optimizations in truthvalue_conversion
but, not this way. */
/* expr = truthvalue_conversion (expr); */
return convert (boolean_type_node, expr);
tree t = convert (boolean_type_node, expr);
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
/* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion
@ -3927,7 +3929,7 @@ build_unary_op (code, xarg, noconvert)
break;
case TRUTH_NOT_EXPR:
arg = bool_truthvalue_conversion (arg);
arg = convert (boolean_type_node, arg);
val = invert_truthvalue (arg);
if (arg != error_mark_node)
return val;
@ -4538,7 +4540,7 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
ifexp = bool_truthvalue_conversion (ifexp);
ifexp = truthvalue_conversion (ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
@ -4895,6 +4897,16 @@ build_compound_expr (list)
break_out_cleanups (TREE_VALUE (list)), rest);
}
#ifdef __GNUC__
__inline
#endif
int
null_ptr_cst_p (t)
tree t;
{
return (TREE_CODE (t) == INTEGER_CST && integer_zerop (t));
}
tree build_static_cast (type, expr)
tree type, expr;
{
@ -4904,12 +4916,104 @@ tree build_static_cast (type, expr)
tree build_reinterpret_cast (type, expr)
tree type, expr;
{
tree intype = TREE_TYPE (expr);
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
if (TYPE_PTRMEMFUNC_P (intype))
intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
{
cp_error ("reinterpret_cast cannot convert to type `%T'", type);
return error_mark_node;
}
if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE)
{
cp_error ("reinterpret_cast cannot convert from type `%T'", type);
return error_mark_node;
}
if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
{
cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
intype, type);
return error_mark_node;
}
if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
{
cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
intype, type);
return error_mark_node;
}
if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE)
expr = convert (ptr_type_node, expr);
return build_c_cast (type, expr, 0);
}
tree build_const_cast (type, expr)
tree type, expr;
{
tree intype = TREE_TYPE (expr);
tree t1, t2;
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
if (TYPE_PTRMEMFUNC_P (intype))
intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
if (! POINTER_TYPE_P (type))
{
cp_error ("const_cast cannot convert to non-pointer type `%T'", type);
return error_mark_node;
}
if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr))
{
cp_error ("const_cast cannot convert rvalue to type `%T'", type);
return error_mark_node;
}
if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
{
cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'",
intype, type);
return error_mark_node;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
t1 = TREE_TYPE (type);
t2 = intype;
}
else
{
t1 = TREE_TYPE (type);
t2 = TREE_TYPE (intype);
for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE;
t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2))
;
}
if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE)
{
if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2))
{
cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'",
TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1));
return error_mark_node;
}
t1 = TREE_TYPE (t1);
t2 = TREE_TYPE (t2);
}
if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
{
cp_error ("const_cast cannot convert unrelated type `%T' to `%T'",
t2, t1);
return error_mark_node;
}
return build_c_cast (type, expr, 0);
}
@ -4930,8 +5034,9 @@ build_c_cast (type, expr, allow_nonconverting)
return error_mark_node;
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since VALUE is being used in non-lvalue context. */
if (TREE_CODE (value) == NOP_EXPR
Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
if (TREE_CODE (type) != REFERENCE_TYPE
&& TREE_CODE (value) == NOP_EXPR
&& TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
value = TREE_OPERAND (value, 0);
@ -4989,7 +5094,8 @@ build_c_cast (type, expr, allow_nonconverting)
}
else
{
tree otype, ovalue;
tree otype;
int flag;
/* Convert functions and arrays to pointers and
convert references to their expanded types,
@ -5041,17 +5147,28 @@ build_c_cast (type, expr, allow_nonconverting)
warning ("cast to pointer from integer of different size");
#endif
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
ovalue = value;
value = convert_force (type, value, allow_nonconverting?CONV_NONCONVERTING:0);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
(convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
LOOKUP_COMPLAIN, NULL_TREE)));
else
{
TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
tree ovalue;
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
ovalue = value;
value = convert_force (type, value, flag);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
{
TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
}
@ -5064,11 +5181,7 @@ build_c_cast (type, expr, allow_nonconverting)
&& TREE_CODE (value) == INTEGER_CST
&& TREE_CODE (expr) == INTEGER_CST
&& TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE))
{
tree nvalue = build1 (NOP_EXPR, type, value);
TREE_CONSTANT (nvalue) = TREE_CONSTANT (value);
return nvalue;
}
value = non_lvalue (value);
return value;
}
@ -5667,7 +5780,8 @@ build_modify_expr (lhs, modifycode, rhs)
{
if (flag_this_is_variable > 0
&& DECL_NAME (current_function_decl) != NULL_TREE
&& current_class_name != DECL_NAME (current_function_decl))
&& (DECL_NAME (current_function_decl)
!= constructor_name (current_class_type)))
warning ("assignment to `this' not in constructor or destructor");
current_function_just_assigned_this = 1;
}
@ -6724,12 +6838,15 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
rhs = resolve_offset_ref (rhs);
if (rhs == error_mark_node)
return error_mark_node;
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
}
if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
&& TREE_CODE (type) != ARRAY_TYPE && TREE_CODE (type) != REFERENCE_TYPE)
&& TREE_CODE (type) != ARRAY_TYPE
&& (TREE_CODE (type) != REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
|| TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
rhs = default_conversion (rhs);
@ -7166,7 +7283,8 @@ c_expand_return (retval)
/* Here is where we finally get RETVAL into RESULT.
`expand_return' does the magic of protecting
RESULT from cleanups. */
retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval);
retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result),
retval));
/* This part _must_ come second, because expand_return looks for
the INIT_EXPR as the toplevel node only. :-( */
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
@ -7278,8 +7396,9 @@ c_expand_start_case (exp)
exp = index;
}
expand_start_case (1, build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp),
type, "switch statement");
expand_start_case
(1, fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp)),
type, "switch statement");
return exp;
}

View File

@ -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);
}