* 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.
if (type == parmtype)
return ZERO_RETURN (h);
+ if (pedantic)
+ return EVIL_RETURN (h);
+
/* Compare return types. */
p1 = TREE_TYPE (type);
p2 = TREE_TYPE (parmtype);
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);
}
}
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
{
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;
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));
TREE_TYPE (result) = value_type;
TREE_SIDE_EFFECTS (result) = 1;
TREE_HAS_CONSTRUCTOR (result) = is_constructor;
+ result = convert_from_reference (result);
return result;
}
}
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
/* 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);
}
}
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
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
{
}
}
- 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);
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.
{
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));
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. */
/* 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)
\f
/* Additional macros for inheritance information. */
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
#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);
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));
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));
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));
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));
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));
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);
{
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)
}
}
- 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
/* 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);
}
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. */
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;
|| 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))
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);
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)
{
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. */
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)
#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));
{
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 ("");
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. */
}
#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
if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
popclass (0);
}
- if (write_symbols != DWARF_DEBUG)
+ if (newdecl)
{
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 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);
- 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);
+ DECL_ASSEMBLER_NAME (d)
+ = get_identifier (build_overload_name (type, 1, 1));
}
- TYPE_CONTEXT (type) = DECL_CONTEXT (d);
- if (newdecl)
- DECL_ASSEMBLER_NAME (d)
- = get_identifier (build_overload_name (type, 1, 1));
}
if (b->parm_flag == 2)
{
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;
}
}
}
+ /* 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,
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))
{
{
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
}
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
}
}
- 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;
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));
}
}
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.
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)
{
|| 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])
}
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)
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;
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;
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;
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);
}
&& IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
+#if 0
if (binfo)
{
tree tt1 = binfo;
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:
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 ();
+}
+
\f
static tree current_local_enum = NULL_TREE;
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)
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);
}
|| 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)
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. */
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;
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
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)
{
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. */
TYPE_NAME (TREE_TYPE (value)) = value;
TYPE_STUB_DECL (TREE_TYPE (value)) = value;
}
+
+ pushdecl_class_level (value);
return value;
}
{
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)
#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
/* =================================================================== */
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;
};
/* ========================================================================= */
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
entry->finalization = NULL_TREE;
+ entry->context = current_function_decl;
node->entry = entry;
node->chain = stack->top;
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.
tree catch_match_fndecl;
tree find_first_exception_match_fndecl;
tree unwind_fndecl;
- tree temp, PFV;
-
- interim_eh_hook = lang_interim_eh;
/* void (*)() */
- PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
+ tree PFV = build_pointer_type (build_function_type
+ (void_type_node, void_list_node));
/* arg list for the build_function_type call for set_terminate () and
set_unexpected () */
- temp = tree_cons (NULL_TREE, PFV, void_list_node);
+ tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
- push_lang_context (lang_name_c);
+ /* void (*pfvtype (void (*) ()))() */
+ tree pfvtype = build_function_type (PFV, pfvlist);
- set_terminate_fndecl =
- define_function ("set_terminate",
- build_function_type (PFV, temp),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- set_unexpected_fndecl =
- define_function ("set_unexpected",
- build_function_type (PFV, temp),
- NOT_BUILT_IN,
- pushdecl,
- 0);
+ /* void vtype () */
+ tree vtype = build_function_type (void_type_node, void_list_node);
+
+ set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
+ pfvtype, NOT_BUILT_IN);
+ set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
+ pfvtype, NOT_BUILT_IN);
+ unexpected_fndecl = auto_function (get_identifier ("unexpected"),
+ vtype, NOT_BUILT_IN);
+ terminate_fndecl = auto_function (get_identifier ("terminate"),
+ vtype, NOT_BUILT_IN);
+
+ interim_eh_hook = lang_interim_eh;
+
+ push_lang_context (lang_name_c);
- unexpected_fndecl =
- define_function ("unexpected",
- build_function_type (void_type_node, void_list_node),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- terminate_fndecl =
- define_function ("terminate",
- build_function_type (void_type_node, void_list_node),
- NOT_BUILT_IN,
- pushdecl,
- 0);
catch_match_fndecl =
define_function ("__throw_type_match",
build_function_type (integer_type_node,
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);
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 ();
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 ();
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));
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;
#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
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");
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));
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 ();
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
smash exception specifications using set union.
Thrown objects are allocated on the heap, in the usual way, but they are
-never deleted. They should be deleted by the catch clauses.
-
-In stmt.c, expand_end_bindings attempts to eliminate the generation of
-destructors for a binding contour if the code would be unreachable (last
-insn == BARRIER). In this case, interim_eh_hook is never called for the
-end of the lifetimes of auto variables, so the compiler generates
-invalid assembler (the end label for the scope is never declared, and
-destructor code isn't generated on the exception path).
+never deleted. They should be deleted by the catch clauses. If one
+runs out of heap space, throwing an object will probably never work.
+This could be relaxed some by passing an __in_chrg parameter to track
+who has control over the exception object.
+
+When the backend returns a value, it can create new exception regions
+that need protecting. The new region should rethrow the object in
+context of the last associated cleanup that ran to completion.
@node Free Store, Concept Index, Exception Handling, Top
@section Free Store
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)
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;
}
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)
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;
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)
{
/* New 2.0 interpretation: `new int (10)' means
allocate an int, and initialize it with 10. */
+ tree deref;
+
+ rval = save_expr (rval);
+ deref = build_indirect_ref (rval, NULL_PTR);
+ TREE_READONLY (deref) = 0;
- init = build_c_cast (type, init, 1);
+ if (TREE_CHAIN (init) != NULL_TREE)
+ pedwarn ("initializer list being treated as compound expression");
+ init = build_compound_expr (init);
+
+ init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL,
+ "new", NULL_TREE, 0);
rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
- build_modify_expr (build_indirect_ref (rval, NULL_PTR),
- NOP_EXPR, init),
+ build_modify_expr (deref, NOP_EXPR, init),
rval);
TREE_SIDE_EFFECTS (rval) = 1;
TREE_CALLS_NEW (rval) = 1;
}
+ else if (! has_array)
+ {
+ tree newrval;
+ /* Constructors are never virtual. If it has an initialization, we
+ need to complain if we aren't allowed to use the ctor that took
+ that argument. */
+ int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
+
+ if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
+ {
+ init = tree_cons (NULL_TREE, integer_one_node, init);
+ flags |= LOOKUP_HAS_IN_CHARGE;
+ }
+
+ newrval = rval;
+
+ if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
+ newrval = build_indirect_ref (newrval, NULL_PTR);
+
+ newrval = build_method_call (newrval, constructor_name_full (true_type),
+ init, NULL_TREE, flags);
+
+ if (newrval)
+ {
+ rval = newrval;
+ TREE_HAS_CONSTRUCTOR (rval) = 1;
+ }
+ else
+ rval = error_mark_node;
+ }
else if (current_function_decl == NULL_TREE)
{
extern tree static_aggregates;
/* In case of static initialization, SAVE_EXPR is good enough. */
+ rval = save_expr (rval);
init = copy_to_permanent (init);
rval = copy_to_permanent (rval);
static_aggregates = perm_tree_cons (init, rval, static_aggregates);
/* 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 ();
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))
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);
}
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;
tree argtype;
int retref = 0;
int complex = 0;
+ tree name = constructor_name (full_name);
- name = constructor_name (name);
switch (kind)
{
/* Destructors. */
/* 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];
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);
{
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);
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],
/* 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
\f
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:
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; }
;
typed_declspecs:
typed_typespecs %prec EMPTY
| typed_declspecs1
+ ;
typed_declspecs1:
declmods typespec
{ $$ = 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 '}'
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'",
+ $$);
}
;
{ 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:
overload_template_name ($$, 0); }
| aggr template_type_name ':'
{ yyungetc (':', 1); goto aggr2; }
- | specialization
;
-named_class_head_sans_basetype_defn:
- aggr identifier_defn %prec EMPTY
- { current_aggr = $$; $$ = $2; }
- ;
-
-do_xref: /* empty */ %prec EMPTY
- { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 1); }
-
do_xref_defn: /* empty */ %prec EMPTY
- { $<ttype>$ = xref_defn_tag (current_aggr, $<ttype>0, NULL_TREE); }
+ { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
+ ;
named_class_head:
- named_class_head_sans_basetype do_xref
- maybe_base_class_list %prec EMPTY
- {
- if ($3)
- $$ = xref_tag (current_aggr, $1, $3, 1);
- else
- $$ = $<ttype>2;
- }
- |
- named_class_head_sans_basetype_defn do_xref_defn
- maybe_base_class_list %prec EMPTY
- {
+ named_class_head_sans_basetype %prec EMPTY
+ { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
+ | named_class_head_sans_basetype_defn do_xref_defn
+ maybe_base_class_list %prec EMPTY
+ {
+ $$ = $<ttype>2;
if ($3)
- $$ = xref_defn_tag (current_aggr, $1, $3);
- else
- $$ = $<ttype>2;
+ xref_basetypes (current_aggr, $1, $<ttype>2, $3);
}
;
/* 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:
defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
}
}
+ SET_DECL_ARTIFICIAL (decl);
pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm);
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)
}
if (decl != 0)
{
+ SET_DECL_ARTIFICIAL (decl);
layout_decl (decl, 0);
if (class_level)
pushdecl_class_level (decl);
= 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)
}
#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);
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;
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);
{
tree base_binfos = BINFO_BASETYPES (vbase_types);
+ BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
+
if (base_binfos)
{
tree chain = NULL_TREE;
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));
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
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);
}
}
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)
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;
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
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;
ifexp = op1 = save_expr (ifexp);
}
- ifexp = bool_truthvalue_conversion (ifexp);
+ ifexp = truthvalue_conversion (ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
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;
{
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);
}
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);
}
else
{
- tree otype, ovalue;
+ tree otype;
+ int flag;
/* Convert functions and arrays to pointers and
convert references to their expanded types,
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);
+ }
}
}
&& 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;
}
{
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;
}
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);
/* 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);
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;
}
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;
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;
}
\f
/* Perform appropriate conversions on the initial value of a variable,
;
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) */
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);
}
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);
}
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);
}
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);
}
/* 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);
}