parent
3a5ece659c
commit
8ccc31eb61
300
gcc/cp/ChangeLog
300
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -176,6 +176,9 @@ convert_harshness (type, parmtype, parm)
|
|||
if (type == parmtype)
|
||||
return ZERO_RETURN (h);
|
||||
|
||||
if (pedantic)
|
||||
return EVIL_RETURN (h);
|
||||
|
||||
/* Compare return types. */
|
||||
p1 = TREE_TYPE (type);
|
||||
p2 = TREE_TYPE (parmtype);
|
||||
|
@ -207,14 +210,16 @@ convert_harshness (type, parmtype, parm)
|
|||
|
||||
if (! BINFO_OFFSET_ZEROP (binfo))
|
||||
{
|
||||
#if 0
|
||||
static int explained = 0;
|
||||
if (h2.distance < 0)
|
||||
message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1);
|
||||
message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);
|
||||
else
|
||||
message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2);
|
||||
message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);
|
||||
|
||||
if (! explained++)
|
||||
sorry ("(because pointer values change during conversion)");
|
||||
#endif
|
||||
return EVIL_RETURN (h);
|
||||
}
|
||||
}
|
||||
|
@ -877,12 +882,15 @@ compute_conversion_costs (function, tta_in, cp, arglen)
|
|||
|
||||
inhibit_warnings = 1;
|
||||
conv = build_type_conversion
|
||||
(CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
|
||||
(CALL_EXPR, formal_type, TREE_VALUE (tta), 0);
|
||||
inhibit_warnings = old_inhibit_warnings;
|
||||
|
||||
if (conv)
|
||||
{
|
||||
if (conv == error_mark_node)
|
||||
if (conv == error_mark_node
|
||||
|| (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE
|
||||
&& ! TYPE_READONLY (TREE_VALUE (TREE_VALUE (ttf)))
|
||||
&& ! lvalue_p (conv)))
|
||||
win += 2;
|
||||
else
|
||||
{
|
||||
|
@ -891,22 +899,6 @@ compute_conversion_costs (function, tta_in, cp, arglen)
|
|||
extra_conversions = 1;
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
|
||||
{
|
||||
conv = build_type_conversion (CALL_EXPR, formal_type,
|
||||
TREE_VALUE (tta), 0);
|
||||
if (conv)
|
||||
{
|
||||
if (conv == error_mark_node)
|
||||
win += 2;
|
||||
else
|
||||
{
|
||||
win++;
|
||||
if (TREE_CODE (conv) != CALL_EXPR)
|
||||
extra_conversions = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dont_convert_types = 0;
|
||||
|
@ -2035,25 +2027,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
tree parm = instance_ptr;
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
|
||||
{
|
||||
/* TREE_VALUE (parms) may have been modified by now;
|
||||
restore it to its original value. */
|
||||
TREE_VALUE (parms) = parm;
|
||||
friend_parms = parms;
|
||||
}
|
||||
parm = convert_from_reference (parm);
|
||||
else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
|
||||
{
|
||||
tree new_type;
|
||||
parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
|
||||
new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
|
||||
volatilep);
|
||||
new_type = build_reference_type (new_type);
|
||||
parm = convert (new_type, parm);
|
||||
friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
|
||||
}
|
||||
parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
|
||||
else
|
||||
my_friendly_abort (167);
|
||||
|
||||
friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
|
||||
|
||||
cp->h_len = len;
|
||||
cp->harshness = (struct harshness_code *)
|
||||
alloca ((len + 1) * sizeof (struct harshness_code));
|
||||
|
@ -2602,6 +2583,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
TREE_TYPE (result) = value_type;
|
||||
TREE_SIDE_EFFECTS (result) = 1;
|
||||
TREE_HAS_CONSTRUCTOR (result) = is_constructor;
|
||||
result = convert_from_reference (result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1453,6 +1453,7 @@ finish_base_struct (t, b, t_binfo)
|
|||
chain = TREE_VEC_ELT (base_binfos, j);
|
||||
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
|
||||
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
|
||||
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
|
||||
}
|
||||
|
||||
/* Completely unshare potentially shared data, and
|
||||
|
@ -1711,8 +1712,9 @@ finish_struct_bits (t, max_has_virtual)
|
|||
/* Add FN to the method_vec growing on the class_obstack. Used by
|
||||
finish_struct_methods. */
|
||||
static void
|
||||
grow_method (fn)
|
||||
grow_method (fn, method_vec_ptr)
|
||||
tree fn;
|
||||
tree *method_vec_ptr;
|
||||
{
|
||||
tree method_vec = (tree)obstack_base (&class_obstack);
|
||||
tree *testp = &TREE_VEC_ELT (method_vec, 0);
|
||||
|
@ -1756,7 +1758,10 @@ grow_method (fn)
|
|||
}
|
||||
}
|
||||
else
|
||||
obstack_ptr_grow (&class_obstack, fn);
|
||||
{
|
||||
obstack_ptr_grow (&class_obstack, fn);
|
||||
*method_vec_ptr = (tree)obstack_base (&class_obstack);
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn about duplicate methods in fn_fields. Also compact method
|
||||
|
@ -1855,7 +1860,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
|
|||
else if (typecode_p (return_type, REAL_TYPE))
|
||||
TYPE_HAS_REAL_CONVERSION (t) = 1;
|
||||
|
||||
grow_method (fn_fields);
|
||||
grow_method (fn_fields, &method_vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1891,12 +1896,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
|
|||
}
|
||||
}
|
||||
|
||||
grow_method (fn_fields);
|
||||
grow_method (fn_fields, &method_vec);
|
||||
fn_fields = nextp;
|
||||
}
|
||||
|
||||
/* Update in case method_vec has moved. */
|
||||
method_vec = (tree)obstack_base (&class_obstack);
|
||||
TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
|
||||
- (&TREE_VEC_ELT (method_vec, 0));
|
||||
obstack_finish (&class_obstack);
|
||||
|
@ -2289,13 +2292,9 @@ modify_one_vtable (binfo, t, fndecl, pfn)
|
|||
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
|
||||
|
||||
/* Make sure we can modify the derived association with immunity. */
|
||||
if (TREE_USED (binfo)) {
|
||||
if (TREE_USED (binfo))
|
||||
my_friendly_assert (0, 999);
|
||||
#if 0
|
||||
my_friendly_assert (*binfo2_ptr == binfo, 999);
|
||||
*binfo2_ptr = copy_binfo (binfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (binfo == TYPE_BINFO (t))
|
||||
{
|
||||
/* In this case, it is *type*'s vtable we are modifying.
|
||||
|
@ -3160,8 +3159,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
|
|||
{
|
||||
cp_warning_at ("width of `%D' exceeds its type", x);
|
||||
}
|
||||
else if (width < TYPE_PRECISION (TREE_TYPE (x))
|
||||
&& TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE)
|
||||
else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
|
||||
&& ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
|
||||
TREE_UNSIGNED (TREE_TYPE (x))) > width)
|
||||
|| (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
|
||||
TREE_UNSIGNED (TREE_TYPE (x))) > width)))
|
||||
{
|
||||
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
|
||||
x, TREE_TYPE (x));
|
||||
|
|
|
@ -666,7 +666,9 @@ struct lang_type
|
|||
searched with TREE_CHAIN), or the first non-constructor function if
|
||||
there are no type conversion operators. */
|
||||
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
|
||||
TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
|
||||
TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \
|
||||
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \
|
||||
: NULL_TREE;
|
||||
|
||||
/* Pointer from any member function to the head of the list of
|
||||
member functions of the type that member function belongs to. */
|
||||
|
@ -842,6 +844,9 @@ struct lang_type
|
|||
|
||||
/* Nonzero if a _DECL node requires us to output debug info for this class. */
|
||||
#define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
|
||||
|
||||
#define TYPE_INCOMPLETE(NODE) \
|
||||
(TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM)
|
||||
|
||||
/* Additional macros for inheritance information. */
|
||||
|
||||
|
@ -1816,7 +1821,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
|
|||
CONV_CONST : Perform the explicit conversions for const_cast.
|
||||
CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast.
|
||||
CONV_PRIVATE : Perform upcasts to private bases.
|
||||
CONV_NONCONVERTING : Allow non-converting constructors to be used. */
|
||||
CONV_NONCONVERTING : Allow non-converting constructors to be used.
|
||||
CONV_FORCE_TEMP : Require a new temporary when converting to the same
|
||||
aggregate type. */
|
||||
|
||||
#define CONV_IMPLICIT 1
|
||||
#define CONV_STATIC 2
|
||||
|
@ -1824,11 +1831,12 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
|
|||
#define CONV_REINTERPRET 8
|
||||
#define CONV_PRIVATE 16
|
||||
#define CONV_NONCONVERTING 32
|
||||
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC)
|
||||
#define CONV_FORCE_TEMP 64
|
||||
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP)
|
||||
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
|
||||
| CONV_REINTERPRET)
|
||||
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
|
||||
| CONV_REINTERPRET | CONV_PRIVATE)
|
||||
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
|
||||
|
||||
/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
|
||||
purpose = friend name (IDENTIFIER_NODE);
|
||||
|
@ -1946,6 +1954,7 @@ extern tree pushdecl_top_level PROTO((tree));
|
|||
extern void push_class_level_binding PROTO((tree, tree));
|
||||
extern void push_overloaded_decl_top_level PROTO((tree, int));
|
||||
extern tree pushdecl_class_level PROTO((tree));
|
||||
extern tree pushdecl_nonclass_level PROTO((tree));
|
||||
extern int overloaded_globals_p PROTO((tree));
|
||||
extern tree push_overloaded_decl PROTO((tree, int));
|
||||
extern tree implicitly_declare PROTO((tree));
|
||||
|
@ -1971,8 +1980,8 @@ extern int complete_array_type PROTO((tree, tree, int));
|
|||
extern tree build_ptrmemfunc_type PROTO((tree));
|
||||
extern tree grokdeclarator (); /* PROTO((tree, tree, enum decl_context, int, tree)); */
|
||||
extern int parmlist_is_exprlist PROTO((tree));
|
||||
extern tree xref_defn_tag PROTO((tree, tree, tree));
|
||||
extern tree xref_tag PROTO((tree, tree, tree, int));
|
||||
extern void xref_basetypes PROTO((tree, tree, tree, tree));
|
||||
extern tree start_enum PROTO((tree));
|
||||
extern tree finish_enum PROTO((tree, tree));
|
||||
extern tree build_enumerator PROTO((tree, tree));
|
||||
|
@ -2019,7 +2028,7 @@ extern tree coerce_delete_type PROTO((tree));
|
|||
extern void walk_vtables PROTO((void (*)(), void (*)()));
|
||||
extern void walk_sigtables PROTO((void (*)(), void (*)()));
|
||||
extern void finish_file PROTO((void));
|
||||
extern void warn_if_unknown_interface PROTO((void));
|
||||
extern void warn_if_unknown_interface PROTO((tree));
|
||||
extern tree grok_x_components PROTO((tree, tree));
|
||||
extern tree reparse_absdcl_as_expr PROTO((tree, tree));
|
||||
extern tree reparse_absdcl_as_casts PROTO((tree, tree));
|
||||
|
@ -2286,7 +2295,6 @@ extern tree hash_chainon PROTO((tree, tree));
|
|||
extern tree get_decl_list PROTO((tree));
|
||||
extern tree list_hash_lookup_or_cons PROTO((tree));
|
||||
extern tree make_binfo PROTO((tree, tree, tree, tree, tree));
|
||||
extern tree copy_binfo PROTO((tree));
|
||||
extern tree binfo_value PROTO((tree, tree));
|
||||
extern tree reverse_path PROTO((tree));
|
||||
extern tree virtual_member PROTO((tree, tree));
|
||||
|
@ -2311,7 +2319,7 @@ extern tree array_type_nelts_total PROTO((tree));
|
|||
extern tree array_type_nelts_top PROTO((tree));
|
||||
|
||||
/* in typeck.c */
|
||||
extern tree bool_truthvalue_conversion PROTO((tree));
|
||||
extern tree condition_conversion PROTO((tree));
|
||||
extern tree target_type PROTO((tree));
|
||||
extern tree require_complete_type PROTO((tree));
|
||||
extern int type_unknown_p PROTO((tree));
|
||||
|
|
111
gcc/cp/cvt.c
111
gcc/cp/cvt.c
|
@ -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)
|
||||
|
|
549
gcc/cp/decl.c
549
gcc/cp/decl.c
|
@ -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)
|
||||
|
|
|
@ -683,11 +683,29 @@ substitute_nice_name (decl)
|
|||
interface/implementation is not used all the times it should be,
|
||||
inform the user. */
|
||||
void
|
||||
warn_if_unknown_interface ()
|
||||
warn_if_unknown_interface (decl)
|
||||
tree decl;
|
||||
{
|
||||
static int already_warned = 0;
|
||||
if (++already_warned == 1)
|
||||
warning ("templates that are built with -fexternal-templates should be in files that have #pragma interface/implementation");
|
||||
if (already_warned++)
|
||||
return;
|
||||
|
||||
if (flag_alt_external_templates)
|
||||
{
|
||||
struct tinst_level *til = tinst_for_decl ();
|
||||
int sl = lineno;
|
||||
char *sf = input_filename;
|
||||
|
||||
lineno = til->line;
|
||||
input_filename = til->file;
|
||||
cp_warning ("template `%#D' instantiated in file without #pragma interface",
|
||||
decl);
|
||||
lineno = sl;
|
||||
input_filename = sf;
|
||||
}
|
||||
else
|
||||
cp_warning_at ("template `%#D' defined in file without #pragma interface",
|
||||
decl);
|
||||
}
|
||||
|
||||
/* A subroutine of the parser, to handle a component list. */
|
||||
|
@ -734,7 +752,7 @@ grok_x_components (specs, components)
|
|||
else if (IS_SIGNATURE(t))
|
||||
tcode = signature_type_node;
|
||||
|
||||
t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
|
||||
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
|
||||
if (TYPE_CONTEXT(t))
|
||||
CLASSTYPE_NO_GLOBALIZE(t) = 1;
|
||||
return NULL_TREE;
|
||||
|
@ -747,7 +765,7 @@ grok_x_components (specs, components)
|
|||
else
|
||||
tcode = enum_type_node;
|
||||
|
||||
t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
|
||||
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
|
||||
if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t))
|
||||
CLASSTYPE_NO_GLOBALIZE(t) = 1;
|
||||
if (TREE_CODE (t) == UNION_TYPE
|
||||
|
@ -1103,12 +1121,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
|
|||
|
||||
if (code == POINTER_TYPE)
|
||||
{
|
||||
#if 0
|
||||
/* As of Valley Forge, you can delete a pointer to constant. */
|
||||
/* You can't delete a pointer to constant. */
|
||||
if (TREE_READONLY (TREE_TYPE (type)))
|
||||
{
|
||||
error ("`const *' cannot be deleted");
|
||||
return error_mark_node;
|
||||
}
|
||||
#endif
|
||||
/* You also can't delete functions. */
|
||||
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
|
||||
{
|
||||
|
@ -1288,7 +1309,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
|
|||
DECL_CONTEXT (value) = current_class_type;
|
||||
DECL_CLASS_CONTEXT (value) = current_class_type;
|
||||
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
|
||||
pushdecl_class_level (value);
|
||||
|
||||
/* If we declare a typedef name for something that has no name,
|
||||
the typedef name is used for linkage. See 7.1.3 p4 94/0158. */
|
||||
|
@ -1299,6 +1319,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
|
|||
TYPE_NAME (TREE_TYPE (value)) = value;
|
||||
TYPE_STUB_DECL (TREE_TYPE (value)) = value;
|
||||
}
|
||||
|
||||
pushdecl_class_level (value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -599,6 +599,7 @@ dump_decl (t, v)
|
|||
{
|
||||
dump_type_prefix (TREE_TYPE (t), v);
|
||||
OB_PUTC (' ');
|
||||
dump_readonly_or_volatile (t, after);
|
||||
}
|
||||
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
|
||||
if (DECL_CONTEXT (t)
|
||||
|
|
129
gcc/cp/except.c
129
gcc/cp/except.c
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
130
gcc/cp/init.c
130
gcc/cp/init.c
|
@ -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))
|
||||
|
|
10
gcc/cp/lex.c
10
gcc/cp/lex.c
|
@ -1539,7 +1539,7 @@ reinit_parse_for_method (yychar, decl)
|
|||
t->can_free = 1;
|
||||
t->deja_vu = 0;
|
||||
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
|
||||
warn_if_unknown_interface ();
|
||||
warn_if_unknown_interface (decl);
|
||||
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
|
||||
store_pending_inline (decl, t);
|
||||
}
|
||||
|
@ -1700,8 +1700,8 @@ reinit_parse_for_block (yychar, obstackp, is_template)
|
|||
When KIND == 6, build default operator = (X&). */
|
||||
|
||||
tree
|
||||
cons_up_default_function (type, name, kind)
|
||||
tree type, name;
|
||||
cons_up_default_function (type, full_name, kind)
|
||||
tree type, full_name;
|
||||
int kind;
|
||||
{
|
||||
extern tree void_list_node;
|
||||
|
@ -1712,8 +1712,8 @@ cons_up_default_function (type, name, kind)
|
|||
tree argtype;
|
||||
int retref = 0;
|
||||
int complex = 0;
|
||||
tree name = constructor_name (full_name);
|
||||
|
||||
name = constructor_name (name);
|
||||
switch (kind)
|
||||
{
|
||||
/* Destructors. */
|
||||
|
@ -1750,7 +1750,7 @@ cons_up_default_function (type, name, kind)
|
|||
/* Fall through... */
|
||||
case 6:
|
||||
retref = 1;
|
||||
declspecs = build_decl_list (NULL_TREE, name);
|
||||
declspecs = build_decl_list (NULL_TREE, full_name);
|
||||
|
||||
name = ansi_opname [(int) MODIFY_EXPR];
|
||||
|
||||
|
|
|
@ -2069,7 +2069,9 @@ do_build_copy_constructor (fndecl)
|
|||
t = TREE_CHAIN (t))
|
||||
{
|
||||
tree basetype = BINFO_TYPE (t);
|
||||
tree p = convert (build_reference_type (basetype), parm);
|
||||
tree p = convert_to_reference
|
||||
(build_reference_type (basetype), parm,
|
||||
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
|
||||
p = convert_from_reference (p);
|
||||
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
|
||||
p, current_base_init_list);
|
||||
|
@ -2079,10 +2081,12 @@ do_build_copy_constructor (fndecl)
|
|||
{
|
||||
tree p, basetype = TREE_VEC_ELT (binfos, i);
|
||||
if (TREE_VIA_VIRTUAL (basetype))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
basetype = BINFO_TYPE (basetype);
|
||||
p = convert (build_reference_type (basetype), parm);
|
||||
p = convert_to_reference
|
||||
(build_reference_type (basetype), parm,
|
||||
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
|
||||
p = convert_from_reference (p);
|
||||
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
|
||||
p, current_base_init_list);
|
||||
|
@ -2153,7 +2157,9 @@ do_build_assign_ref (fndecl)
|
|||
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
|
||||
if (TYPE_HAS_ASSIGN_REF (basetype))
|
||||
{
|
||||
tree p = convert (build_reference_type (basetype), parm);
|
||||
tree p = convert_to_reference
|
||||
(build_reference_type (basetype), parm,
|
||||
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
|
||||
p = convert_from_reference (p);
|
||||
p = build_member_call (TYPE_NESTED_NAME (basetype),
|
||||
ansi_opname [MODIFY_EXPR],
|
||||
|
|
|
@ -280,7 +280,7 @@ empty_parms ()
|
|||
/* Used in lex.c for parsing pragmas. */
|
||||
%token END_OF_LINE
|
||||
|
||||
/* spew.c depends on this being the last token. Define
|
||||
/* lex.c and pt.c depends on this being the last token. Define
|
||||
any new tokens before this one! */
|
||||
%token END_OF_SAVED_INPUT
|
||||
|
||||
|
@ -940,8 +940,7 @@ paren_expr_or_null:
|
|||
cond_stmt_keyword);
|
||||
$$ = integer_zero_node; }
|
||||
| '(' expr ')'
|
||||
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
|
||||
bool_truthvalue_conversion ($2)); }
|
||||
{ $$ = condition_conversion ($2); }
|
||||
;
|
||||
|
||||
paren_cond_or_null:
|
||||
|
@ -950,16 +949,14 @@ paren_cond_or_null:
|
|||
cond_stmt_keyword);
|
||||
$$ = integer_zero_node; }
|
||||
| '(' condition ')'
|
||||
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
|
||||
bool_truthvalue_conversion ($2)); }
|
||||
{ $$ = condition_conversion ($2); }
|
||||
;
|
||||
|
||||
xcond:
|
||||
/* empty */
|
||||
{ $$ = NULL_TREE; }
|
||||
| condition
|
||||
{ $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node,
|
||||
bool_truthvalue_conversion ($$)); }
|
||||
{ $$ = condition_conversion ($$); }
|
||||
| error
|
||||
{ $$ = NULL_TREE; }
|
||||
;
|
||||
|
@ -1800,6 +1797,7 @@ type_id:
|
|||
typed_declspecs:
|
||||
typed_typespecs %prec EMPTY
|
||||
| typed_declspecs1
|
||||
;
|
||||
|
||||
typed_declspecs1:
|
||||
declmods typespec
|
||||
|
@ -2151,9 +2149,9 @@ structsp:
|
|||
{ $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE);
|
||||
check_for_missing_semicolon ($$); }
|
||||
| ENUM identifier
|
||||
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
|
||||
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
|
||||
| ENUM complex_type_name
|
||||
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
|
||||
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
|
||||
|
||||
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
|
||||
| class_head left_curly opt.component_decl_list '}'
|
||||
|
@ -2206,16 +2204,11 @@ structsp:
|
|||
check_for_missing_semicolon ($$); }
|
||||
| class_head %prec EMPTY
|
||||
{
|
||||
#if 0
|
||||
/* It's no longer clear what the following error is supposed to
|
||||
accomplish. If it turns out to be needed, add a comment why. */
|
||||
if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$))
|
||||
{
|
||||
error ("incomplete definition of type `%s'",
|
||||
TYPE_NAME_STRING ($$));
|
||||
$$ = error_mark_node;
|
||||
}
|
||||
#endif
|
||||
/* struct B: public A; is not accepted by the WP grammar. */
|
||||
if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)
|
||||
&& ! TYPE_BEING_DEFINED ($$))
|
||||
cp_error ("base clause without member specification for `%#T'",
|
||||
$$);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -2257,6 +2250,12 @@ named_class_head_sans_basetype:
|
|||
{ current_aggr = $$; $$ = $2; }
|
||||
| aggr template_type %prec EMPTY
|
||||
{ current_aggr = $$; $$ = $2; }
|
||||
| specialization
|
||||
;
|
||||
|
||||
named_class_head_sans_basetype_defn:
|
||||
aggr identifier_defn %prec EMPTY
|
||||
{ current_aggr = $$; $$ = $2; }
|
||||
| aggr template_type_name '{'
|
||||
{ yyungetc ('{', 1);
|
||||
aggr2:
|
||||
|
@ -2265,37 +2264,21 @@ named_class_head_sans_basetype:
|
|||
overload_template_name ($$, 0); }
|
||||
| aggr template_type_name ':'
|
||||
{ yyungetc (':', 1); goto aggr2; }
|
||||
| specialization
|
||||
;
|
||||
|
||||
named_class_head_sans_basetype_defn:
|
||||
aggr identifier_defn %prec EMPTY
|
||||
{ current_aggr = $$; $$ = $2; }
|
||||
;
|
||||
|
||||
do_xref: /* empty */ %prec EMPTY
|
||||
{ $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 1); }
|
||||
|
||||
do_xref_defn: /* empty */ %prec EMPTY
|
||||
{ $<ttype>$ = xref_defn_tag (current_aggr, $<ttype>0, NULL_TREE); }
|
||||
{ $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
|
||||
;
|
||||
|
||||
named_class_head:
|
||||
named_class_head_sans_basetype do_xref
|
||||
maybe_base_class_list %prec EMPTY
|
||||
{
|
||||
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:
|
||||
|
|
12
gcc/cp/pt.c
12
gcc/cp/pt.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
195
gcc/cp/typeck.c
195
gcc/cp/typeck.c
|
@ -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;
|
||||
}
|
||||
|
|
136
gcc/cp/typeck2.c
136
gcc/cp/typeck2.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue