31th Cygnus<->FSF merge.

From-SVN: r6996
This commit is contained in:
Mike Stump 1994-04-08 06:08:43 +00:00
parent 779c643ac3
commit 8926095fe7
21 changed files with 1117 additions and 841 deletions

View File

@ -2658,7 +2658,7 @@ build_scoped_method_call (exp, scopes, name, parms)
return error_mark_node;
}
if (binfo = binfo_or_else (basetype, type))
if ((binfo = binfo_or_else (basetype, type)))
{
if (binfo == error_mark_node)
return error_mark_node;
@ -2965,13 +2965,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (basetype) == REFERENCE_TYPE)
{
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (basetype));
basetype = TREE_TYPE (basetype);
if (! IS_AGGR_TYPE (basetype))
goto non_aggr_error;
/* Call to convert not needed because we are remaining
within the same type. */
instance_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), instance);
inst_ptr_basetype = basetype;
instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype),
instance);
inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype);
}
else
{
@ -3077,7 +3078,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
return error_mark_node;
}
save_basetype = basetype;
save_basetype = TYPE_MAIN_VARIANT (basetype);
#if 0
if (all_virtual == 1
@ -3118,8 +3119,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (instance)
{
constp = TREE_READONLY (instance);
volatilep = TREE_THIS_VOLATILE (instance);
/* TREE_READONLY (instance) fails for references. */
constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr)));
volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr)));
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
else
@ -3161,9 +3163,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
}
parmtypes = tree_cons (NULL_TREE,
build_pointer_type (build_type_variant (basetype, constp, volatilep)),
parmtypes);
parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
if (last == NULL_TREE)
last = parmtypes;
@ -3253,19 +3255,22 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (flags & LOOKUP_GLOBAL)
{
tree friend_parms;
tree parm = TREE_VALUE (parms);
tree parm = instance_ptr;
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
friend_parms = parms;
{
/* TREE_VALUE (parms) may have been modified by now;
restore it to its original value. */
TREE_VALUE (parms) = parm;
friend_parms = parms;
}
else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
{
tree new_type;
parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
new_type = build_reference_type (TREE_TYPE (parm));
/* It is possible that this should go down a layer. */
new_type = build_type_variant (new_type,
TREE_READONLY (parm),
TREE_THIS_VOLATILE (parm));
new_type = build_type_variant (new_type, constp, volatilep);
parm = convert (new_type, parm);
friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
}
@ -3330,9 +3335,20 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype_path = TREE_VALUE (basetype_path);
basetype = BINFO_TYPE (basetype_path);
/* Cast the instance variable to the appropriate type. */
TREE_VALUE (parms) = convert_force (TYPE_POINTER_TO (basetype),
instance_ptr);
/* Cast the instance variable if necessary. */
if (basetype != TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
{
if (basetype == save_basetype)
TREE_VALUE (parms) = instance_ptr;
else
{
tree type = build_pointer_type
(build_type_variant (basetype, constp, volatilep));
TREE_VALUE (parms) = convert_force (type, instance_ptr);
}
}
/* FIXME: this is the wrong place to get an error. Hopefully
the access-control rewrite will make this change more cleanly. */
if (TREE_VALUE (parms) == error_mark_node)
@ -3468,12 +3484,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
then all we ever saw were private members. */
if (cp - candidates > 1)
{
int n_candidates = cp - candidates;
TREE_VALUE (parms) = instance_ptr;
cp = ideal_candidate (save_basetype, candidates,
cp - candidates, parms, len);
n_candidates, parms, len);
if (cp == (struct candidate *)0)
{
cp_error ("ambiguous type conversion requested for %s `%D'",
name_kind, name);
if (flags & LOOKUP_COMPLAIN)
{
cp_error ("call of overloaded %s `%D' is ambiguous",
name_kind, name);
print_n_candidates (candidates, n_candidates);
}
return error_mark_node;
}
if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE))
@ -3483,8 +3505,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
else if ((flag_ansi_overloading && (cp[-1].h.code & EVIL_CODE))
|| (!flag_ansi_overloading && cp[-1].evil == 2))
{
cp_error ("ambiguous type conversion requested for %s `%D'",
name_kind, name);
if (flags & LOOKUP_COMPLAIN)
cp_error ("ambiguous type conversion requested for %s `%D'",
name_kind, name);
return error_mark_node;
}
else
@ -3549,10 +3572,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
continue;
found_and_maybe_warn:
if ((flag_ansi_overloading
&& (cp->v.ansi_harshness[0].code & CONST_CODE))
|| (!flag_ansi_overloading
&& CONST_HARSHNESS (cp->v.old_harshness[0])))
if (((flag_ansi_overloading
&& (cp->v.ansi_harshness[0].code & CONST_CODE))
|| (!flag_ansi_overloading
&& CONST_HARSHNESS (cp->v.old_harshness[0])))
/* 12.1p2: Constructors can be called for const objects. */
&& ! DECL_CONSTRUCTOR_P (cp->function))
{
if (flags & LOOKUP_COMPLAIN)
{

View File

@ -371,35 +371,67 @@ tree
build_vtable_entry (delta, pfn)
tree delta, pfn;
{
extern int flag_huge_objects;
tree elems = tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, integer_zero_node,
build_tree_list (NULL_TREE, pfn)));
tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
extern tree abort_fndecl;
if (TREE_CODE (pfn) == ADDR_EXPR)
{
tree fndecl = TREE_OPERAND (pfn, 0);
if (TREE_CODE(fndecl) == FUNCTION_DECL
&& DECL_ABSTRACT_VIRTUAL_P(fndecl))
{
tree d = copy_node (fndecl);
DECL_RTL (d) = DECL_RTL (abort_fndecl);
TREE_OPERAND (pfn, 0) = d;
}
}
/* DELTA is constructed by `size_int', which means it may be an
unsigned quantity on some platforms. Therefore, we cannot use
`int_fits_type_p', because when DELTA is really negative,
`force_fit_type' will make it look like a very large number. */
if (flag_vtable_thunks)
{
HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
extern tree make_thunk ();
if (idelta)
{
pfn = build1 (ADDR_EXPR, ptr_type_node,
make_thunk (pfn, idelta));
TREE_READONLY (pfn) = 1;
TREE_CONSTANT (pfn) = 1;
}
#ifdef GATHER_STATISTICS
n_vtable_entries += 1;
#endif
return pfn;
}
else
{
extern int flag_huge_objects;
tree elems = tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, integer_zero_node,
build_tree_list (NULL_TREE, pfn)));
tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))
< TREE_INT_CST_LOW (delta))
|| (TREE_INT_CST_LOW (delta)
< TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))
if (flag_huge_objects)
sorry ("object size exceeds built-in limit for virtual function table implementation");
else
sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
/* DELTA is constructed by `size_int', which means it may be an
unsigned quantity on some platforms. Therefore, we cannot use
`int_fits_type_p', because when DELTA is really negative,
`force_fit_type' will make it look like a very large number. */
TREE_CONSTANT (entry) = 1;
TREE_STATIC (entry) = 1;
TREE_READONLY (entry) = 1;
if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))
< TREE_INT_CST_LOW (delta))
|| (TREE_INT_CST_LOW (delta)
< TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))
if (flag_huge_objects)
sorry ("object size exceeds built-in limit for virtual function table implementation");
else
sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
TREE_CONSTANT (entry) = 1;
TREE_STATIC (entry) = 1;
TREE_READONLY (entry) = 1;
#ifdef GATHER_STATISTICS
n_vtable_entries += 1;
n_vtable_entries += 1;
#endif
return entry;
return entry;
}
}
/* Given an object INSTANCE, return an expression which yields the
@ -471,7 +503,7 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
NULL_PTR);
}
if (!flag_vtable_hack)
if (!flag_vtable_thunks)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
@ -480,12 +512,17 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)
TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
*ptr_to_instptr
= build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
*ptr_to_instptr,
convert (ptrdiff_type_node,
build_component_ref (aref, delta_identifier, 0, 0)));
return build_component_ref (aref, pfn_identifier, 0, 0);
if (flag_vtable_thunks)
return aref;
else
{
*ptr_to_instptr
= build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
*ptr_to_instptr,
convert (ptrdiff_type_node,
build_component_ref (aref, delta_identifier, 0, 0)));
return build_component_ref (aref, pfn_identifier, 0, 0);
}
}
/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
@ -828,18 +865,14 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
DECL_VINDEX (fndecl) = vindex;
else
{
if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex))
if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex)
&& ! doing_hard_virtuals)
{
tree elts = CONSTRUCTOR_ELTS (new_entry);
if (! doing_hard_virtuals)
{
pending_hard_virtuals
= tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
pending_hard_virtuals);
TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
return;
}
pending_hard_virtuals
= tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
pending_hard_virtuals);
TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
return;
}
}
}
@ -972,7 +1005,6 @@ static int
is_normal (binfo, t)
tree t, binfo;
{
tree binfo2;
int i = CLASSTYPE_VFIELD_PARENT (t);
if (i != -1)
{
@ -992,10 +1024,13 @@ modify_other_vtable_entries (t, binfo, fndecl, base_fndecl, pfn)
tree t, binfo;
tree fndecl, base_fndecl, pfn;
{
tree vfields, virtuals;
tree virtuals;
tree binfos;
int i, n_baselinks;
unsigned HOST_WIDE_INT n;
#if 0
tree vfields;
#endif
virtuals = BINFO_VIRTUALS (binfo);
n = 0;
@ -1173,7 +1208,10 @@ modify_vtable_entries (t, fndecl, base_fndecl, pfn)
DECL_ASSEMBLER_NAME(fndecl));
}
#endif
#if 0
/* this is wrong, see p4736a.C testcase */
DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
#endif
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
@ -1377,7 +1415,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
TREE_CONSTANT (vfn) = 1;
/* current_class_type may be NULL_TREE in case of error. */
if (current_class_type)
if (current_class_type && !flag_vtable_thunks)
TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);
/* If the virtual function is a redefinition of a prior one,
@ -1386,7 +1424,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
to hold that entry. */
if (DECL_VINDEX (x) == error_mark_node)
{
tree entry = build_vtable_entry (integer_zero_node, vfn);
tree entry;
if (flag_dossier && *has_virtual == 0)
{
@ -1416,6 +1454,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
DECL_VINDEX (x) = index;
}
#endif
entry = build_vtable_entry (integer_zero_node, vfn);
pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);
}
/* Happens if declared twice in class or we're not in a class definition.
@ -2041,7 +2080,7 @@ finish_base_struct (t, b, t_binfo)
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, j)
= make_binfo (BINFO_OFFSET (base_base_binfo),
BINFO_TYPE (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
@ -2773,7 +2812,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
int any_default_members = 0;
int const_sans_init = 0;
int ref_sans_init = 0;
int do_mem_init = 0;
int nonprivate_method = 0;
tree t_binfo = TYPE_BINFO (t);
tree access_decls = 0;
@ -3005,10 +3043,10 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_VINDEX (x)
|| (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
{
pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x))
abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x))
abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
}
continue;
}
@ -3772,8 +3810,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! SAME_FN (decl, base_fndecl))
{
tree base_context = DECL_CLASS_CONTEXT (base_fndecl);
tree binfo = NULL_TREE, these_virtuals;
tree binfo = NULL_TREE;
#if 0
tree these_virtuals;
unsigned HOST_WIDE_INT i
= (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
& (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1));

View File

@ -90,3 +90,13 @@ DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
TREE_CHAIN null
Other useful fields to be defined later. */
DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)
/* A thunk is a stub function.
Thunks are used to implement multiple inheritance:
At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree)
from the this pointer, and then jumps to DECL_INITIAL
(which is an ADDR_EXPR whose operand is a FUNCTION_DECL).
Other kinds of thunks may be defined later. */
DEFTREECODE (THUNK_DECL, "thunk_decl", "d", 0)

View File

@ -259,10 +259,10 @@ extern int flag_signed_bitfields;
extern int write_virtuals;
/* True if we want output of vtables to be controlled by whether
we seen the class's first non-inline virtual function.
/* True for more efficient but incompatible (not not fully tested)
vtable implementation (using thunks).
0 is old behavior; 1 is new behavior. */
extern flag_vtable_hack;
extern int flag_vtable_thunks;
/* INTERFACE_ONLY nonzero means that we are in an "interface"
section of the compiler. INTERFACE_UNKNOWN nonzero means
@ -339,10 +339,12 @@ enum languages { lang_c, lang_cplusplus };
/* Virtual function addresses can be gotten from a virtual function
table entry using this macro. */
#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY))))
(!flag_vtable_thunks ? \
TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) \
: TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? (ENTRY) \
: DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
(TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \
(((CODE) == TREE_CODE (NODE) \
@ -924,7 +926,8 @@ struct lang_decl_flags
unsigned mutable_flag : 1;
unsigned is_default_implementation : 1;
unsigned synthesized : 1;
unsigned dummy : 10;
unsigned saved_inline : 1;
unsigned dummy : 9;
tree access;
tree context;
@ -986,6 +989,11 @@ struct lang_decl
member function. */
#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
/* Nonzero for FUNCTION_DECL means that this decl is a member function
(static or non-static). */
#define DECL_FUNCTION_MEMBER_P(NODE) \
(TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE || DECL_STATIC_FUNCTION_P (NODE))
/* Nonzero for FUNCTION_DECL means that this member function
has `this' as const X *const. */
#define DECL_CONST_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.const_memfunc)
@ -1005,8 +1013,9 @@ struct lang_decl
/* Nonzero if allocated on permanent_obstack. */
#define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr)
/* The _TYPE context in which this _DECL appears. This field is used
only to compute access information. */
/* The _TYPE context in which this _DECL appears. This field holds the
class where a virtual function instance is actually defined, and the
lexical scope of a friend function defined in a class body. */
#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
/* For a FUNCTION_DECL: the chain through which the next method
@ -1029,6 +1038,10 @@ struct lang_decl
squirreled away. */
#define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info)
/* True if on the saved_inlines (see decl2.c) list. */
#define DECL_SAVED_INLINE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->decl_flags.saved_inline)
/* For a FUNCTION_DECL: if this function was declared inside a signature
declaration, this is the corresponding member function pointer that was
created for it. */
@ -1057,7 +1070,9 @@ struct lang_decl
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */
#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
#if 0 /* UNUSED */
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
#endif
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
For a FUNCTION_DECL, this is when the function is a virtual function.
@ -1165,8 +1180,8 @@ struct lang_decl
#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
/* Nonzero for VAR_DECL node means that `external' was specified in
its declaration. */
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was
specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
@ -1232,6 +1247,8 @@ struct lang_decl
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size)
/* ...and for unexpanded-parameterized-type nodes. */
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
#define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE))
@ -1293,6 +1310,7 @@ extern tree void_list_node;
extern tree void_zero_node;
extern tree default_function_type;
extern tree vtable_entry_type;
extern tree memptr_type;
extern tree sigtable_entry_type;
extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
extern tree Type_info_type_node;
@ -1790,6 +1808,7 @@ extern void print_binding_stack PROTO((void));
extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void));
extern void set_identifier_type_value PROTO((tree, tree));
extern void pop_everything PROTO((void));
extern tree make_type_decl PROTO((tree, tree));
extern void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void));
@ -1823,6 +1842,7 @@ extern void expand_static_init PROTO((tree, tree));
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 tree start_enum PROTO((tree));
@ -1928,7 +1948,6 @@ extern tree build_dynamic_cast PROTO((tree, tree));
/* in init.c */
extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree));
extern tree build_virtual_init PROTO((tree, tree, tree));
extern void init_vtbl_ptrs PROTO((tree, int, int));
extern void do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree));
@ -2000,6 +2019,16 @@ extern void dump_time_statistics PROTO((void));
extern void compiler_error_with_decl PROTO((tree, char *));
extern void yyerror PROTO((char *));
/* in errfn.c */
extern void cp_error ();
extern void cp_error_at ();
extern void cp_warning ();
extern void cp_warning_at ();
extern void cp_pedwarn ();
extern void cp_pedwarn_at ();
extern void cp_compiler_error ();
extern void cp_sprintf ();
/* in error.c */
extern void init_error PROTO((void));
extern char *fndecl_as_string PROTO((tree, tree, int));
@ -2059,7 +2088,7 @@ extern void push_memoized_context PROTO((tree, int));
extern void pop_memoized_context PROTO((int));
extern tree get_binfo PROTO((tree, tree, int));
extern int get_base_distance PROTO((tree, tree, int, tree *));
extern enum access_type check_access PROTO((tree, tree));
extern enum access_type compute_access PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
extern tree lookup_nested_field PROTO((tree, int));
extern tree lookup_fnfields PROTO((tree, tree, int));
@ -2071,7 +2100,7 @@ extern tree get_abstract_virtuals PROTO((tree));
extern tree get_baselinks PROTO((tree, tree, tree));
extern tree next_baselink PROTO((tree));
extern tree init_vbase_pointers PROTO((tree, tree));
extern tree build_vbase_vtables_init PROTO((tree, tree, tree, tree, int));
extern void expand_vbase_vtables_init PROTO((tree, tree, tree, tree, int));
extern void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree));
extern void build_mi_matrix PROTO((tree));
@ -2132,6 +2161,7 @@ extern tree virtual_member PROTO((tree, tree));
extern tree virtual_offset PROTO((tree, tree, tree));
extern void debug_binfo PROTO((tree));
extern int decl_list_length PROTO((tree));
extern int count_functions PROTO((tree));
extern tree decl_value_member PROTO((tree, tree));
extern int is_overloaded_fn PROTO((tree));
extern tree get_first_fn PROTO((tree));

View File

@ -285,22 +285,21 @@ build_up_reference (type, arg, flags, checkconst)
{
tree rval, targ;
int literal_flag = 0;
tree argtype = TREE_TYPE (arg), basetype = argtype;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
tree binfo = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
if (flags != 0
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
&& IS_AGGR_TYPE (argtype)
&& IS_AGGR_TYPE (target_type))
{
binfo = get_binfo (target_type, argtype, 1);
if ((flags & LOOKUP_PROTECT) && binfo == error_mark_node)
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype);
basetype = BINFO_TYPE (binfo);
}
/* Pass along const and volatile down into the type. */
@ -619,8 +618,8 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
register enum tree_code form = TREE_CODE (intype);
tree rval = NULL_TREE;
if (TREE_CODE(type) == ARRAY_TYPE)
type = build_pointer_type (TREE_TYPE(type));
if (TREE_CODE (type) == ARRAY_TYPE)
type = build_pointer_type (TREE_TYPE (type));
if (form == REFERENCE_TYPE)
intype = TREE_TYPE (intype);
intype = TYPE_MAIN_VARIANT (intype);
@ -639,10 +638,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
/* Section 13. */
if (flags & LOOKUP_COMPLAIN)
{
/* Since convert_for_initialization didn't call convert_for_assignment,
we have to do this checking here. FIXME: We should have a common
routine between here and convert_for_assignment. */
if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
/* Since convert_for_initialization didn't call
convert_for_assignment, we have to do this checking here.
FIXME: We should have a common routine between here and
convert_for_assignment. */
if (form == REFERENCE_TYPE)
{
register tree ttl = TREE_TYPE (reftype);
register tree ttr = TREE_TYPE (TREE_TYPE (expr));
@ -683,37 +683,52 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
then we don't need to convert it to reference type if
it is only being used to initialize DECL which is also
of the same aggregate type. */
if (form == REFERENCE_TYPE
|| (decl != NULL_TREE && decl != error_mark_node
&& IS_AGGR_TYPE (type)
&& TREE_CODE (expr) == CALL_EXPR
&& TYPE_MAIN_VARIANT (type) == intype))
if (decl != NULL_TREE && decl != error_mark_node
&& IS_AGGR_TYPE (type)
&& TREE_CODE (expr) == CALL_EXPR
&& TYPE_MAIN_VARIANT (type) == intype)
{
if (decl && decl != error_mark_node)
{
tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
tree e2;
tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
tree e2;
TREE_SIDE_EFFECTS (e1) = 1;
if (form == REFERENCE_TYPE)
e2 = build1 (NOP_EXPR, reftype, decl);
else
{
e2 = build_unary_op (ADDR_EXPR, decl, 0);
TREE_TYPE (e2) = reftype;
TREE_REFERENCE_EXPR (e2) = 1;
}
return build_compound_expr (tree_cons (NULL_TREE, e1,
build_tree_list (NULL_TREE, e2)));
TREE_SIDE_EFFECTS (e1) = 1;
if (form == REFERENCE_TYPE)
e2 = build1 (NOP_EXPR, reftype, decl);
else
{
e2 = build_unary_op (ADDR_EXPR, decl, 0);
TREE_TYPE (e2) = reftype;
TREE_REFERENCE_EXPR (e2) = 1;
}
expr = copy_node (expr);
TREE_TYPE (expr) = reftype;
return expr;
return build_compound_expr
(tree_cons (NULL_TREE, e1, build_tree_list (NULL_TREE, e2)));
}
else if (form == REFERENCE_TYPE)
{
rval = copy_node (expr);
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval);
TREE_TYPE (rval) = reftype;
return rval;
}
return build_up_reference (reftype, expr, flags, decl!=NULL_TREE);
}
if (decl == error_mark_node)
if (decl == NULL_TREE && lvalue_p (expr))
{
/* When casting an lvalue to a reference type, just convert into
a pointer to the new type and deference it. This is allowed
by San Diego WP section 5.2.8 paragraph 9, though perhaps it
should be done directly (jason). (int &)ri ---> *(int*)&ri */
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
if (rval != error_mark_node)
TREE_TYPE (rval) = reftype;
}
else if (decl == error_mark_node || decl == NULL_TREE)
{
tree rval_as_conversion = NULL_TREE;
tree rval_as_ctor = NULL_TREE;
@ -798,12 +813,12 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
my_friendly_assert (form != OFFSET_TYPE, 189);
if ((flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY)) == LOOKUP_COMPLAIN)
cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
else if (flags & LOOKUP_COMPLAIN)
cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);
return error_mark_node;
}
@ -1025,14 +1040,13 @@ convert_to_aggr (type, expr, msgp, protect)
*msgp = "only private conversions apply";
else if (saw_protected)
*msgp = "only protected conversions apply";
else
*msgp = "no appropriate conversion to type `%s'";
}
return error_mark_node;
}
/* NOTREACHED */
not_found:
if (msgp) *msgp = "no appropriate conversion to type `%s'";
return error_mark_node;
found:
if (access == access_private)
if (! can_be_private)
@ -1436,7 +1450,7 @@ convert_force (type, expr)
if (code == REFERENCE_TYPE)
return fold (convert_to_reference (0, type, e, NULL_TREE, -1,
NULL, -1, 0));
NULL, -1, LOOKUP_COMPLAIN));
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);

View File

@ -224,7 +224,7 @@ tree sizet_ftype_string;
tree int_ftype_cptr_cptr_sizet;
/* C++ extensions */
tree vtable_entry_type;
tree memptr_type, vtable_entry_type;
tree delta_type_node;
tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
@ -310,11 +310,6 @@ static tree named_label_uses;
in the TREE_PURPOSE slot. */
tree static_aggregates;
/* A list of functions which were declared inline, but later had their
address taken. Used only for non-virtual member functions, since we can
find other functions easily enough. */
tree pending_addressable_inlines;
/* A list of overloaded functions which we should forget ever
existed, such as functions declared in a function's scope,
once we leave that function's scope. */
@ -1682,6 +1677,26 @@ set_nested_typename (decl, classname, name, type)
DECL_NESTED_TYPENAME (decl) = name;
}
/* Pop off extraneous binding levels left over due to syntax errors. */
void
pop_everything ()
{
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
#endif
while (current_binding_level != global_binding_level
&& ! current_binding_level->pseudo_global)
{
if (class_binding_level)
pop_nested_class (1);
else
poplevel (0, 0, 0);
}
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX leaving pop_everything ()\n");
#endif
}
#if 0 /* not yet, should get fixed properly later */
/* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME.
Other routines shouldn't use build_decl directly; they'll produce
@ -1981,7 +1996,14 @@ decls_match (newdecl, olddecl)
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
types_match = compparms (p1, p2, 2);
{
if (DECL_LANGUAGE (olddecl) == lang_c
&& ! strict_prototypes_lang_c
&& p2 == NULL_TREE)
types_match = self_promoting_args_p (p1);
else
types_match = compparms (p1, p2, 1);
}
else
types_match = 0;
}
@ -2096,42 +2118,7 @@ duplicate_decls (newdecl, olddecl)
int new_defines_function;
tree previous_c_decl = NULL_TREE;
if (TREE_CODE (newdecl) == FUNCTION_DECL && is_overloaded_fn (olddecl))
{
olddecl = get_first_fn (olddecl);
while (olddecl)
{
if (DECL_LANGUAGE (olddecl) == lang_c)
previous_c_decl = olddecl;
/* Redeclaration. */
if (decls_match (newdecl, olddecl))
{
types_match = 1;
break;
}
/* Ambiguous overload. */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
break;
/* Attempt to define multiple C-binding fns. */
if (previous_c_decl)
break;
olddecl = DECL_CHAIN (olddecl);
}
if (!olddecl)
{
/* If we found no match, make this join the other
overloaded decls. */
DECL_OVERLOADED (newdecl) = 1;
return 1;
}
}
else
types_match = decls_match (newdecl, olddecl);
types_match = decls_match (newdecl, olddecl);
if (TREE_CODE (olddecl) != TREE_LIST)
olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl);
@ -2149,6 +2136,14 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL
&& ! DECL_TEMPLATE_IS_CLASS (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& TREE_CODE (newdecl) == TEMPLATE_DECL
&& ! DECL_TEMPLATE_IS_CLASS (newdecl)))
return 0;
cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
@ -2167,7 +2162,8 @@ duplicate_decls (newdecl, olddecl)
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl)
|| DECL_BUILT_IN_NONANSI (olddecl)))
|| DECL_BUILT_IN_NONANSI (olddecl))
&& DECL_ASSEMBLER_NAME (newdecl) == DECL_ASSEMBLER_NAME (olddecl))
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden,
@ -2195,101 +2191,34 @@ duplicate_decls (newdecl, olddecl)
return 0;
}
}
else if (!types_match && previous_c_decl
&& DECL_LANGUAGE (newdecl) == lang_c)
{
cp_error ("declaration of C function `%#D' conflicts with", newdecl);
cp_error_at ("previous declaration `%#D' here", previous_c_decl);
}
else if (!types_match && TREE_CODE (newdecl) == TEMPLATE_DECL)
return 0;
else if (!types_match)
{
tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl);
int give_error = 0;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
return 0;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c)
{
cp_error ("declaration of C function `%#D' conflicts with",
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
return 0;
}
/* Already complained about this, so don't do so again. */
if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
give_error = 1;
/* Since we're doing this before finish_struct can set the
line number on NEWDECL, we just do a regular error here. */
if (DECL_SOURCE_LINE (newdecl) == 0)
cp_error ("conflicting types for `%#D'", newdecl);
else
cp_error_at ("conflicting types for `%#D'", newdecl);
}
/* Check for function type mismatch
involving an empty arglist vs a nonempty one. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype), 1)
&& ((TYPE_ARG_TYPES (oldtype) == NULL_TREE
&& DECL_INITIAL (olddecl) == NULL_TREE)
|| (TYPE_ARG_TYPES (newtype) == NULL_TREE
&& DECL_INITIAL (newdecl) == NULL_TREE)))
{
/* Classify the problem further. */
register tree t = TYPE_ARG_TYPES (oldtype);
if (t == NULL_TREE)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
register tree type = TREE_VALUE (t);
if (TREE_CHAIN (t) == NULL_TREE && type != void_type_node)
{
give_error = 1;
error ("A parameter list with an ellipsis can't match");
error ("an empty parameter name list declaration.");
break;
}
if (TYPE_MAIN_VARIANT (type) == float_type_node
|| C_PROMOTING_INTEGER_TYPE_P (type))
{
give_error = 1;
error ("An argument type that has a default promotion");
error ("can't match an empty parameter name list declaration.");
break;
}
}
}
if (give_error)
cp_error_at ("previous declaration as `%#D'", olddecl);
/* There is one thing GNU C++ cannot tolerate: a constructor
which takes the type of object being constructed.
Farm that case out here. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (newdecl))
{
tree tmp = TREE_CHAIN (TYPE_ARG_TYPES (newtype));
if (tmp != NULL_TREE
&& (TYPE_MAIN_VARIANT (TREE_VALUE (tmp))
== TYPE_METHOD_BASETYPE (newtype)))
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (newdecl));
tree argtypes
= hash_tree_chain (build_reference_type (TREE_VALUE (tmp)),
TREE_CHAIN (tmp));
DECL_ARG_TYPE (parm)
= TREE_TYPE (parm)
= TYPE_REFERENCE_TO (TREE_VALUE (tmp));
TREE_TYPE (newdecl) = newtype
= build_cplus_method_type (TYPE_METHOD_BASETYPE (newtype),
TREE_TYPE (newtype), argtypes);
error ("constructor cannot take as argument the type being constructed");
SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl), current_class_type);
}
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
else
@ -2315,18 +2244,25 @@ duplicate_decls (newdecl, olddecl)
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
/* extern "C" int foo ();
int foo () { bar (); }
is OK. */
if (current_lang_stack == current_lang_base)
DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
cp_error ("conflicts with new declaration with %L linkage",
DECL_LANGUAGE (newdecl));
}
{
/* extern "C" int foo ();
int foo () { bar (); }
is OK. */
if (current_lang_stack == current_lang_base)
{
DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
if (TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
cp_error ("conflicts with new declaration with %L linkage",
DECL_LANGUAGE (newdecl));
}
}
/* These bits are logically part of the type. */
if (pedantic
@ -2386,10 +2322,6 @@ duplicate_decls (newdecl, olddecl)
#endif
}
if (TREE_CODE (olddecl) == TEMPLATE_DECL
&& DECL_TEMPLATE_INFO (olddecl)->length)
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
/* Special handling ensues if new decl is a function definition. */
new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != NULL_TREE);
@ -2463,8 +2395,13 @@ duplicate_decls (newdecl, olddecl)
TREE_THIS_VOLATILE (olddecl) = 1;
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == NULL_TREE)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
if (DECL_INITIAL (newdecl) == NULL_TREE
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
}
/* Keep the old rtl since we can safely use it, unless it's the
call to abort() used for abstract virtuals. */
if ((DECL_LANG_SPECIFIC (olddecl)
@ -2547,7 +2484,7 @@ duplicate_decls (newdecl, olddecl)
DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if (DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))
if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
/* Previously saved insns go together with
the function's previous definition. */
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
@ -2557,6 +2494,15 @@ duplicate_decls (newdecl, olddecl)
}
}
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (DECL_TEMPLATE_INFO (olddecl)->length)
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
DECL_TEMPLATE_INSTANTIATIONS (newdecl)
= DECL_TEMPLATE_INSTANTIATIONS (olddecl);
}
/* Now preserve various other info from the definition. */
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
@ -2706,7 +2652,10 @@ pushdecl (x)
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
if (TREE_CODE (t) != TREE_CODE (x))
if (TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c
&& is_overloaded_fn (t))
/* don't do anything just yet */;
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
{
@ -2723,39 +2672,47 @@ pushdecl (x)
else if (duplicate_decls (x, t))
{
#if 0
/* This is turned off until I have time to do it right (bpk). */
/* This is turned off until I have time to do it right (bpk). */
/* Also warn if they did a prototype with `static' on it, but
then later left the `static' off. */
else if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
{
if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
return t;
if (extra_warnings)
/* Also warn if they did a prototype with `static' on it, but
then later left the `static' off. */
if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
{
cp_warning ("`static' missing from declaration of `%D'", t);
warning_with_file_and_line (file, line,
"previous declaration of `%s'",
decl_as_string (t, 0));
if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
return t;
if (extra_warnings)
{
cp_warning ("`static' missing from declaration of `%D'", t);
warning_with_file_and_line (file, line,
"previous declaration of `%s'",
decl_as_string (t, 0));
}
/* Now fix things so it'll do what they expect. */
if (current_function_decl)
TREE_PUBLIC (current_function_decl) = 0;
}
/* Now fix things so it'll do what they expect. */
if (current_function_decl)
TREE_PUBLIC (current_function_decl) = 0;
}
#endif
/* Due to interference in memory reclamation (X may be
obstack-deallocated at this point), we must guard against
one really special case. */
one really special case. [jason: This should be handled
by start_function] */
if (current_function_decl == x)
current_function_decl = t;
#endif
return t;
}
}
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, 1);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
}
else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))
return push_overloaded_decl (x, 0);
/* If declaring a type as a typedef, and the type has no known
typedef name, install this TYPE_DECL as its typedef name. */
@ -2819,7 +2776,7 @@ pushdecl (x)
&& !DECL_BUILT_IN (decl))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%D'", decl);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
}
}
@ -3176,8 +3133,6 @@ push_overloaded_decl (decl, forgettable)
tree orig_name = DECL_NAME (decl);
tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
DECL_OVERLOADED (decl) = 1;
if (forgettable
&& ! flag_traditional
&& (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
@ -3187,18 +3142,6 @@ push_overloaded_decl (decl, forgettable)
if (glob)
{
if (DECL_LANGUAGE (decl) == lang_c)
{
tree decls = get_first_fn (glob);
while (decls && DECL_LANGUAGE (decls) == lang_cplusplus)
decls = DECL_CHAIN (decls);
if (decls)
{
cp_error_at ("C-language function `%#D'", decls);
cp_error ("overloaded as `%#D'", decl);
}
}
/* We cache the value of builtin functions as ADDR_EXPRs
in the name space. Convert it to some kind of _DECL after
remembering what to forget. */
@ -3210,7 +3153,7 @@ push_overloaded_decl (decl, forgettable)
tree tmp;
for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
if (decl == tmp)
if (decl == tmp || duplicate_decls (decl, tmp))
return decl;
}
else if (TREE_CODE (glob) == VAR_DECL)
@ -3219,40 +3162,26 @@ push_overloaded_decl (decl, forgettable)
cp_error ("conflicts with function declaration `%#D'", decl);
return error_mark_node;
}
else if (TREE_CODE (glob) == TYPE_DECL)
{
tree t = TREE_TYPE (glob);
if (IS_AGGR_TYPE (t) && warn_shadow)
cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
}
else if (is_overloaded_fn (glob))
{
tree name = DECL_ASSEMBLER_NAME (decl);
tree tmp;
for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
{
if (TREE_CODE (tmp) == FUNCTION_DECL
&& comptypes (TREE_TYPE (tmp), TREE_TYPE (decl), 2))
if (decl == tmp || duplicate_decls (decl, tmp))
return tmp;
if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2))
{
if (DECL_LANGUAGE (tmp) != DECL_LANGUAGE (decl))
{
if (current_lang_stack == current_lang_base)
{
DECL_LANGUAGE (decl) = DECL_LANGUAGE (tmp);
return tmp;
}
cp_error_at ("previous declaration of `%#D' with %L linkage",
tmp, DECL_LANGUAGE (tmp));
cp_error ("conflicts with new %L-language declaration",
DECL_LANGUAGE (decl));
}
else if (TREE_CODE (tmp) != TEMPLATE_DECL
&& DECL_ASSEMBLER_NAME (tmp) != name)
{
cp_error ("new declaration `%#D'", decl);
cp_error_at ("ambiguates old declaration `%#D'", tmp);
}
cp_error ("new declaration `%#D'", decl);
cp_error_at ("ambiguates old declaration `%#D'", tmp);
}
/* If we really have seen this before, then if it ambiguates
something, we've already given an error before. */
if (TREE_CODE (tmp) != TEMPLATE_DECL
&& DECL_ASSEMBLER_NAME (tmp) == name)
return decl;
}
}
}
@ -3335,7 +3264,7 @@ redeclaration_error_message (newdecl, olddecl)
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
if (comptypes (newdecl, olddecl, 0))
if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
return 0;
else
return "redefinition of `%#D'";
@ -3378,15 +3307,12 @@ redeclaration_error_message (newdecl, olddecl)
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
/* Reject two definitions. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
return "redefinition of `%#D'";
/* Now we have two tentative defs, or one tentative and one real def. */
/* Insist that the linkage match. */
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
return "conflicting declarations of `%#D'";
return 0;
/* Reject two definitions. */
return "redefinition of `%#D'";
}
else
{
@ -4114,6 +4040,9 @@ init_decl_processing ()
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
if (flag_ansi || pedantic)
strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
/* Initially, C. */
current_lang_name = lang_name_c;
@ -4418,6 +4347,21 @@ init_decl_processing ()
builtin_function ("__builtin_constant_p", int_ftype_int,
BUILT_IN_CONSTANT_P, NULL_PTR);
builtin_function ("__builtin_return_address",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
unsigned_type_node,
endlink)),
BUILT_IN_RETURN_ADDRESS, NULL_PTR);
builtin_function ("__builtin_frame_address",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
unsigned_type_node,
endlink)),
BUILT_IN_FRAME_ADDRESS, NULL_PTR);
builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
@ -4596,14 +4540,14 @@ init_decl_processing ()
pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
}
/* Simplify life by making a "vtable_entry_type". Give its
/* Simplify life by making a "memptr_type". Give its
fields names so that the debugger can use them. */
vtable_entry_type = make_lang_type (RECORD_TYPE);
memptr_type = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node);
finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2,
double_type_node);
/* Make this part of an invisible union. */
@ -4614,8 +4558,13 @@ init_decl_processing ()
DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[3]) = 0;
TREE_CHAIN (fields[2]) = fields[3];
vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
memptr_type = build_type_variant (memptr_type, 1, 0);
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, memptr_type);
if (flag_vtable_thunks)
vtable_entry_type = ptr_type_node;
else
vtable_entry_type = memptr_type;
#ifdef VTABLE_USES_MASK
/* This is primarily for virtual function definition. We
@ -5115,7 +5064,6 @@ start_decl (declarator, declspecs, initialized, raises)
DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
&& !(context && !DECL_THIS_EXTERN (decl)));
DECL_TEMPLATE_RESULT (d) = decl;
DECL_OVERLOADED (d) = 1;
decl = d;
}
@ -5227,25 +5175,7 @@ start_decl (declarator, declspecs, initialized, raises)
|| TREE_CODE (type) == LANG_TYPE)
tem = decl;
else
{
tem = pushdecl (decl);
if (is_overloaded_fn (tem))
{
tree tem2;
tem = get_first_fn (tem);
tem2 = decl_value_member (decl, tem);
if (tem2 != NULL_TREE)
tem = tem2;
else
{
while (tem && ! decls_match (decl, tem))
tem = DECL_CHAIN (tem);
if (tem == NULL_TREE)
tem = decl;
}
}
}
tem = pushdecl (decl);
/* Tell the back-end to use or not use .common as appropriate. */
DECL_COMMON (tem) = flag_conserve_space;
@ -5267,10 +5197,7 @@ start_decl (declarator, declspecs, initialized, raises)
}
#endif
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_OVERLOADED (decl))
/* @@ Also done in start_function. */
tem = push_overloaded_decl (tem, 1);
else if (TREE_CODE (decl) == TEMPLATE_DECL)
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
tree result = DECL_TEMPLATE_RESULT (decl);
if (DECL_CONTEXT (result) != NULL_TREE)
@ -5339,6 +5266,7 @@ start_decl (declarator, declspecs, initialized, raises)
return tem;
}
#if 0 /* unused */
static void
make_temporary_for_reference (decl, ctor_call, init, cleanupp)
tree decl, ctor_call, init;
@ -5397,6 +5325,7 @@ make_temporary_for_reference (decl, ctor_call, init, cleanupp)
if (TREE_STATIC (tmp))
preserve_initializer ();
}
#endif
/* Handle initialization of references.
These three arguments from from `finish_decl', and have the
@ -5559,7 +5488,6 @@ grok_reference_init (decl, type, init, cleanupp)
else
my_friendly_abort (1);
done:
/* ?? Can this be optimized in some cases to
hand back the DECL_INITIAL slot?? */
if (TYPE_SIZE (TREE_TYPE (type)))
@ -6140,6 +6068,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
#if 0
/* C++: Handle overloaded functions with default parameters. */
if (DECL_OVERLOADED (decl))
{
@ -6184,6 +6113,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
}
DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
}
#endif
}
else if (DECL_EXTERNAL (decl))
;
@ -6926,7 +6856,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
tree type, last = NULL_TREE;
tree last = NULL_TREE;
register tree decl = declarator;
name = NULL;
@ -8722,10 +8652,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& ! funcdef_flag
&& RIDBIT_NOTSETP (RID_STATIC, specbits)
&& RIDBIT_NOTSETP (RID_INLINE, specbits)));
if (TREE_CODE (type) == METHOD_TYPE)
publicp
|= (ctype && CLASSTYPE_INTERFACE_KNOWN (ctype))
|| (!funcdef_flag && RIDBIT_NOTSETP (RID_INLINE, specbits));
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, publicp);
@ -8852,25 +8778,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
int was_overloaded = 0;
tree original_name = declarator;
int publicp = 0;
if (! declarator)
return NULL_TREE;
if (RIDBIT_SETP (RID_AUTO, specbits)
|| RIDBIT_SETP (RID_REGISTER, specbits))
error ("invalid storage class for function `%s'", name);
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
error ("storage class `register' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (current_binding_level != global_binding_level
&& (RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits))
&& ! processing_template_decl
&& (RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits))
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
{
if (RIDBIT_SETP (RID_STATIC, specbits))
pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
else
pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
}
if (ctype == NULL_TREE)
{
if (virtualp)
@ -8887,11 +8820,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& IDENTIFIER_POINTER (original_name)[0] == '_'
&& IDENTIFIER_POINTER (original_name)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
{
/* Plain overloading: will not be grok'd by grokclassfn. */
declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
was_overloaded = 1;
}
/* Plain overloading: will not be grok'd by grokclassfn. */
declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
@ -8926,8 +8856,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_error_at ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1;
}
else if (! was_overloaded
&& ! ctype
else if (! ctype
&& IDENTIFIER_LENGTH (original_name) == 4
&& IDENTIFIER_POINTER (original_name)[0] == 'm'
&& ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
@ -8954,8 +8883,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{
tree last = tree_last (TYPE_ARG_TYPES (type));
if (! was_overloaded
&& ! ctype
if (! ctype
&& ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
error ("cannot inline function `main'");
else if (last && last != void_list_node)
@ -8971,8 +8899,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
pedwarn ("ANSI C++ does not permit `extern inline'");
}
}
if (was_overloaded)
DECL_OVERLOADED (decl) = 1;
}
else
{
@ -9012,6 +8938,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (RIDBIT_SETP (RID_REGISTER, specbits))
DECL_REGISTER (decl) = 1;
if (RIDBIT_SETP (RID_EXTERN, specbits))
DECL_THIS_EXTERN (decl) = 1;
/* Record constancy and volatility. */
if (constp)
@ -9753,7 +9682,7 @@ xref_tag (code_type_node, name, binfo, globalize)
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
if (t = IDENTIFIER_TYPE_VALUE(name))
if ((t = IDENTIFIER_TYPE_VALUE(name)))
{
if (TREE_CODE(t) != code) t = NULL_TREE;
}
@ -10000,7 +9929,7 @@ xref_tag (code_type_node, name, binfo, globalize)
base_binfo = make_binfo (integer_zero_node, basetype,
TYPE_BINFO_VTABLE (basetype),
TYPE_BINFO_VIRTUALS (basetype), 0);
TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
@ -10468,7 +10397,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
if ( !(DECL_VINDEX (decl1)
&& write_virtuals >= 2
&& CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
current_extern_inline = TREE_PUBLIC (decl1) && DECL_INLINE (decl1);
current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1);
raises = TYPE_RAISES_EXCEPTIONS (fntype);
@ -10585,73 +10514,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
/* Now see if this is the implementation of a declared function. */
if (ctype == NULL_TREE && current_lang_name == lang_name_cplusplus
&& !DECL_CONTEXT (decl1))
{
olddecl = lookup_name_current_level (DECL_NAME (decl1));
if (olddecl && TREE_CODE (olddecl) != FUNCTION_DECL)
olddecl = NULL_TREE;
if (olddecl && DECL_NAME (decl1) != DECL_NAME (olddecl))
{
/* Collision between user and internal naming scheme. */
olddecl = lookup_name_current_level (DECL_ASSEMBLER_NAME (decl1));
if (olddecl == NULL_TREE)
olddecl = decl1;
}
if (olddecl && olddecl != decl1
&& DECL_NAME (decl1) == DECL_NAME (olddecl))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& decls_match (decl1, olddecl))
{
olddecl = DECL_MAIN_VARIANT (olddecl);
/* The following copy is needed to handle forcing a function's
linkage to obey the linkage of the original decl. */
DECL_ASSEMBLER_NAME (decl1) = DECL_ASSEMBLER_NAME (olddecl);
DECL_OVERLOADED (decl1) = DECL_OVERLOADED (olddecl);
if (! DECL_BUILT_IN (olddecl) && DECL_INITIAL (olddecl))
redeclaration_error_message (decl1, olddecl);
if (duplicate_decls (decl1, olddecl))
decl1 = olddecl;
else
olddecl = NULL_TREE;
}
else
olddecl = NULL_TREE;
}
}
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
if (olddecl)
current_function_decl = olddecl;
else if (pre_parsed_p == 0)
if (pre_parsed_p == 0)
{
current_function_decl = pushdecl (decl1);
if (TREE_CODE (current_function_decl) == TREE_LIST
|| (DECL_ASSEMBLER_NAME (current_function_decl)
!= DECL_ASSEMBLER_NAME (decl1)))
{
/* @@ revert to modified original declaration. */
decl1 = DECL_MAIN_VARIANT (decl1);
current_function_decl = decl1;
}
else
{
decl1 = current_function_decl;
DECL_MAIN_VARIANT (decl1) = decl1;
}
current_function_decl = decl1 = pushdecl (decl1);
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
else
current_function_decl = decl1;
if (DECL_OVERLOADED (decl1))
decl1 = push_overloaded_decl (decl1, 1);
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
{
if (TREE_CODE (fntype) == METHOD_TYPE)
@ -10956,7 +10831,7 @@ store_return_init (return_id, init)
/* Give this error as many times as there are occurrences,
so that users can use Emacs compilation buffers to find
and fix all such places. */
error ("ANSI C++ does not permit named return values");
pedwarn ("ANSI C++ does not permit named return values");
if (return_id != NULL_TREE)
{
@ -11266,8 +11141,7 @@ finish_function (lineno, call_poplevel)
tables. */
init_vtbl_ptrs (binfo, 1, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
C_C_D, current_class_decl, 0));
expand_vbase_vtables_init (binfo, binfo, C_C_D, current_class_decl, 0);
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
@ -11604,6 +11478,12 @@ finish_function (lineno, call_poplevel)
rest_of_compilation (fndecl);
}
if (DECL_INLINE (fndecl)
&& !TREE_ASM_WRITTEN (fndecl) && DECL_FUNCTION_MEMBER_P (fndecl))
{
mark_inline_for_output (fndecl);
}
if (ctype && TREE_ASM_WRITTEN (fndecl))
note_debug_info_needed (ctype);
@ -11715,10 +11595,7 @@ start_method (declspecs, declarator, raises)
return void_type_node;
}
/* If we're expanding a template, a function must be explicitly declared
inline if we're to compile it now. If it isn't, we have to wait to see
whether it's needed, and whether an override exists. */
if (flag_default_inline && !processing_template_defn)
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
/* We read in the parameters on the maybepermanent_obstack,
@ -11777,7 +11654,6 @@ finish_method (decl)
{
register tree fndecl = decl;
tree old_initial;
tree context = DECL_CONTEXT (fndecl);
register tree link;

View File

@ -48,11 +48,6 @@ extern tree pending_statics;
in the TREE_PURPOSE slot. */
extern tree static_aggregates;
/* A list of functions which were declared inline, but later had their
address taken. Used only for non-virtual member functions, since we can
find other functions easily enough. */
extern tree pending_addressable_inlines;
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
extern int debug_bindings_indentation;

View File

@ -47,7 +47,9 @@ tree pending_vtables;
an initializer, and then initialized, staticly, outside the class. */
tree pending_statics;
extern tree pending_addressable_inlines;
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
static tree saved_inlines;
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
@ -129,9 +131,12 @@ int warn_implicit = 1;
int warn_ctor_dtor_privacy = 1;
/* True if we want output of vtables to be controlled by whether
/* True if we want to implement vtbvales using "thunks".
The default is off now, but will be on later.
Also causes output of vtables to be controlled by whether
we seen the class's first non-inline virtual function. */
int flag_vtable_hack = 0;
int flag_vtable_thunks = 0;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
@ -364,7 +369,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"ansi-overloading", &flag_ansi_overloading, 1},
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-hack", &flag_vtable_hack, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
};
/* Decode the string P as a language-specific option.
@ -609,6 +614,7 @@ grok_method_quals (ctype, function, quals)
return ctype;
}
#if 0 /* Not used. */
/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs.
It leaves DECL_ASSEMBLER_NAMEs with the correct value. */
/* This does not yet work with user defined conversion operators
@ -625,6 +631,7 @@ substitute_nice_name (decl)
DECL_NAME (decl) = get_identifier (n);
}
}
#endif
/* Warn when -fexternal-templates is used and #pragma
interface/implementation is not used all the times it should be,
@ -1071,7 +1078,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (doing_vec
&& TREE_CODE (type) == POINTER_TYPE
&& !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)))
doing_vec = 0;
{
doing_vec = 0;
use_global_delete = 1;
}
if (doing_vec)
return build_vec_delete (t, maxindex, elt_size, NULL_TREE,
@ -1093,7 +1103,6 @@ check_classfn (ctype, cname, function)
{
tree fn_name = DECL_NAME (function);
tree fndecl;
int need_quotes = 0;
tree method_vec = CLASSTYPE_METHOD_VEC (ctype);
tree *methods = 0;
tree *end = 0;
@ -1241,12 +1250,14 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
}
else if (pedantic)
{
#if 0
/* Already warned in grokdeclarator. */
if (DECL_NAME (value))
pedwarn ("ANSI C++ forbids initialization of member `%s'",
IDENTIFIER_POINTER (DECL_NAME (value)));
else
pedwarn ("ANSI C++ forbids initialization of fields");
#endif
init = NULL_TREE;
}
else
@ -1675,7 +1686,6 @@ grok_function_init (decl, init)
/* An initializer for a function tells how this function should
be inherited. */
tree type = TREE_TYPE (decl);
extern tree abort_fndecl;
if (TREE_CODE (type) == FUNCTION_TYPE)
cp_error ("initializer specified for non-member function `%D'", decl);
@ -1683,14 +1693,19 @@ grok_function_init (decl, init)
cp_error ("initializer specified for non-virtual method `%D'", decl);
else if (integer_zerop (init))
{
#if 0
/* Mark this function as being "defined". */
DECL_INITIAL (decl) = error_mark_node;
/* pure virtual destructors must be defined. */
/* pure virtual needs to be defined (as abort) only when put in
vtbl. For wellformed call, it should be itself. pr4737 */
if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
{
extern tree abort_fndecl;
/* Give this node rtl from `abort'. */
DECL_RTL (decl) = DECL_RTL (abort_fndecl);
}
#endif
DECL_ABSTRACT_VIRTUAL_P (decl) = 1;
}
else if (TREE_CODE (init) == OFFSET_REF
@ -1791,7 +1806,6 @@ tree
constructor_name_full (thing)
tree thing;
{
tree t;
if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)
return DECL_NAME (UPT_TEMPLATE (thing));
if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
@ -1898,6 +1912,9 @@ void
mark_inline_for_output (decl)
tree decl;
{
if (DECL_SAVED_INLINE (decl))
return;
DECL_SAVED_INLINE (decl) = 1;
if (DECL_PENDING_INLINE_INFO (decl) != 0
&& ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
{
@ -1917,8 +1934,7 @@ mark_inline_for_output (decl)
}
DECL_PENDING_INLINE_INFO (decl) = 0;
}
pending_addressable_inlines = perm_tree_cons (NULL_TREE, decl,
pending_addressable_inlines);
saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_inlines);
}
void
@ -2275,7 +2291,7 @@ coerce_delete_type (type)
}
static void
write_vtable_entries (decl)
mark_vtable_entries (decl)
tree decl;
{
tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)));
@ -2287,51 +2303,16 @@ write_vtable_entries (decl)
{
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
tree fn = TREE_OPERAND (fnaddr, 0);
if (! DECL_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn)
&& DECL_SAVED_INSNS (fn))
{
if (TREE_PUBLIC (DECL_CLASS_CONTEXT (fn)))
TREE_PUBLIC (fn) = 1;
TREE_ADDRESSABLE (fn) = 1;
temporary_allocation ();
output_inline_function (fn);
permanent_allocation (1);
}
else
assemble_external (fn);
TREE_ADDRESSABLE (fn) = 1;
}
}
/* Note even though prev is never used in here, walk_vtables
expects this to have two arguments, so concede. */
static void
finish_vtable_typedecl (prev, vars)
tree prev, vars;
{
tree decl = TYPE_BINFO_VTABLE (TREE_TYPE (vars));
/* If we are controlled by `+e2', obey. */
if (write_virtuals == 2)
{
tree binfo = value_member (DECL_NAME (vars), pending_vtables);
if (binfo)
TREE_PURPOSE (binfo) = void_type_node;
else
decl = NULL_TREE;
}
/* If this type has inline virtual functions, then
write those functions out now. */
if (decl && write_virtuals >= 0
&& ! DECL_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl)))
write_vtable_entries (decl);
}
static void
finish_vtable_vardecl (prev, vars)
tree prev, vars;
{
tree ctype = DECL_CONTEXT (vars);
if (flag_vtable_hack && !CLASSTYPE_INTERFACE_KNOWN (ctype))
if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype))
{
tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
@ -2339,6 +2320,8 @@ finish_vtable_vardecl (prev, vars)
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
TREE_PUBLIC (vars) = 1;
DECL_EXTERNAL (vars) = DECL_EXTERNAL (method);
break;
@ -2354,15 +2337,32 @@ finish_vtable_vardecl (prev, vars)
/* Stuff this virtual function table's size into
`pfn' slot of `the_null_vtable_entry'. */
tree nelts = array_type_nelts (TREE_TYPE (vars));
SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
if (flag_vtable_thunks)
TREE_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))) = nelts;
else
SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
/* Kick out the dossier before writing out the vtable. */
if (flag_dossier)
rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1);
/* Write it out. */
write_vtable_entries (vars);
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars));
store_init_value (vars, DECL_INITIAL (vars));
if (flag_vtable_thunks)
{
tree list = CONSTRUCTOR_ELTS (DECL_INITIAL (vars));
for (; list; list = TREE_CHAIN (list))
{
tree vfunc = TREE_VALUE (list);
if (TREE_CODE (vfunc) == ADDR_EXPR)
{
vfunc = TREE_OPERAND (vfunc, 0);
if (TREE_CODE (vfunc) == THUNK_DECL)
emit_thunk (vfunc);
}
}
}
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
@ -2394,7 +2394,7 @@ finish_vtable_vardecl (prev, vars)
rest_of_decl_compilation (vars, 0, 1, 1);
}
else if (TREE_USED (vars) && flag_vtable_hack)
else if (TREE_USED (vars) && flag_vtable_thunks)
assemble_external (vars);
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
@ -2679,23 +2679,6 @@ finish_file ()
parse_time -= this_time - start_time;
varconst_time += this_time - start_time;
/* Now write out inline functions which had their addresses taken
and which were not declared virtual and which were not declared
`extern inline'. */
while (pending_addressable_inlines)
{
tree decl = TREE_VALUE (pending_addressable_inlines);
if (! TREE_ASM_WRITTEN (decl)
&& ! DECL_EXTERNAL (decl)
&& DECL_SAVED_INSNS (decl))
{
temporary_allocation ();
output_inline_function (decl);
permanent_allocation (1);
}
pending_addressable_inlines = TREE_CHAIN (pending_addressable_inlines);
}
start_time = get_run_time ();
/* Now delete from the chain of variables all virtual function tables.
@ -2726,7 +2709,38 @@ finish_file ()
pushdecl (vars);
#endif
walk_vtables (finish_vtable_typedecl, finish_vtable_vardecl);
walk_vtables ((void (*)())0, finish_vtable_vardecl);
/* Now write out inline functions which had their addresses taken
and which were not declared virtual and which were not declared
`extern inline'. */
while (saved_inlines)
{
tree decl = TREE_VALUE (saved_inlines);
saved_inlines = TREE_CHAIN (saved_inlines);
if (TREE_ASM_WRITTEN (decl))
continue;
if (DECL_FUNCTION_MEMBER_P (decl) && !TREE_PUBLIC (decl))
{
tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (ctype);
}
}
if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl))
{
if (DECL_EXTERNAL (decl))
assemble_external (decl);
else
{
temporary_allocation ();
output_inline_function (decl);
permanent_allocation (1);
}
}
}
if (write_virtuals == 2)
{
@ -2839,8 +2853,11 @@ reparse_decl_as_expr1 (decl)
case BIT_NOT_EXPR:
return build_x_unary_op (BIT_NOT_EXPR,
reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
default:
my_friendly_abort (5);
return NULL_TREE;
}
my_friendly_abort (5);
}
/* This is something of the form `int (*a)++' that has turned out to be an
@ -2865,6 +2882,8 @@ tree
finish_decl_parsing (decl)
tree decl;
{
extern int current_class_depth;
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
@ -2878,5 +2897,12 @@ finish_decl_parsing (decl)
case BIT_NOT_EXPR:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
case SCOPE_REF:
push_nested_class (TREE_OPERAND (decl, 0), 3);
TREE_COMPLEXITY (decl) = current_class_depth;
return decl;
default:
my_friendly_abort (5);
return NULL_TREE;
}
}

View File

@ -112,7 +112,7 @@ cp_thing (errfn, atarg1, format, arglist)
if (*f == 'l')
++f;
function = cp_printers[*f];
function = cp_printers[(int)*f];
if (function)
{

View File

@ -92,9 +92,6 @@ init_error ()
scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
}
/* Counter to help build parameter names in case they were omitted. */
static int dummy_name;
enum pad { none, before, after };
static void
@ -505,8 +502,9 @@ ident_fndecl (t)
else if (TREE_CODE (n) == TREE_LIST
&& TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
return TREE_VALUE (n);
else
my_friendly_abort (66);
my_friendly_abort (66);
return NULL_TREE;
}
#ifndef NO_DOLLAR_IN_LABEL
@ -715,7 +713,6 @@ dump_function_decl (t, v)
tree fntype = TREE_TYPE (t);
tree parmtypes = TYPE_ARG_TYPES (fntype);
tree cname = NULL_TREE;
int spaces = 0;
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
if (DECL_CONTEXT (t))
@ -1335,6 +1332,7 @@ code_as_string (c, v)
char *
language_as_string (c, v)
enum languages c;
int v;
{
switch (c)
{
@ -1346,13 +1344,14 @@ language_as_string (c, v)
default:
my_friendly_abort (355);
return 0;
}
}
/* Return the proper printed version of a parameter to a C++ function. */
char *
parm_as_string (p, v)
int p;
int p, v;
{
if (p < 0)
return "`this'";
@ -1364,6 +1363,7 @@ parm_as_string (p, v)
char *
op_as_string (p, v)
enum tree_code p;
int v;
{
static char buf[] = "operator ";

View File

@ -211,6 +211,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
#endif
}
case THUNK_DECL:
return DECL_RTL (exp);
default:
break;
}

View File

@ -50,6 +50,7 @@ void expand_aggr_init ();
static void expand_aggr_init_1 ();
static void expand_recursive_init_1 ();
static void expand_recursive_init ();
static void expand_virtual_init PROTO((tree, tree, tree));
tree expand_vec_init ();
tree build_vec_delete ();
@ -60,7 +61,9 @@ static tree BIN, BID;
/* Cache the identifier nodes for the two magic field of a new cookie. */
static tree nc_nelts_field_id;
#if 0
static tree nc_ptr_2comp_field_id;
#endif
static tree minus_one;
@ -122,7 +125,7 @@ init_vtbl_ptrs (binfo, init_self, can_elide)
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
tree base_ptr = convert_pointer_to_real (binfo, current_class_decl);
expand_expr_stmt (build_virtual_init (binfo, binfo, base_ptr));
expand_virtual_init (binfo, binfo, base_ptr);
}
}
@ -345,13 +348,12 @@ emit_base_init (t, immediately)
{
extern tree in_charge_identifier;
tree member, decl, vbases;
tree init_list, member_init;
tree member, vbases;
tree init_list;
int pass, start;
tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree fields_to_unmark = NULL_TREE;
int have_init_list = 0, from_init_list;
if (! immediately)
@ -600,8 +602,8 @@ emit_base_init (t, immediately)
/* Initialize all the virtual function table fields that
do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_expr_stmt (build_vbase_vtables_init (t_binfo, t_binfo,
C_C_D, current_class_decl, 0));
expand_vbase_vtables_init (t_binfo, t_binfo,
C_C_D, current_class_decl, 0);
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
CLEAR_BINFO_BASEINIT_MARKED (vbases);
@ -610,8 +612,7 @@ emit_base_init (t, immediately)
init_vtbl_ptrs (t_binfo, 0, 1);
if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t,
current_class_decl));
expand_virtual_init (TYPE_BINFO (t), t, current_class_decl);
if (current_member_init_list)
{
@ -704,8 +705,8 @@ check_base_init (t)
BINFO is the exact type that DECL is supposed to be. In
multiple inheritance, this might mean "C's A" if C : A, B. */
tree
build_virtual_init (main_binfo, binfo, decl)
static void
expand_virtual_init (main_binfo, binfo, decl)
tree main_binfo, binfo;
tree decl;
{
@ -733,7 +734,6 @@ build_virtual_init (main_binfo, binfo, decl)
{
tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree result = NULL_TREE;
for (i = n_baselinks-1; i >= 0; i--)
{
@ -751,9 +751,9 @@ build_virtual_init (main_binfo, binfo, decl)
else
this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
decl, BINFO_OFFSET (base_binfo));
result = tree_cons (NULL_TREE, build_virtual_init (main_binfo, base_binfo, this_decl), result);
expand_virtual_init (main_binfo, base_binfo, this_decl);
}
return build_compound_expr (result);
return;
}
#endif
@ -779,11 +779,11 @@ build_virtual_init (main_binfo, binfo, decl)
decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node)
return error_mark_node;
return;
/* Have to convert VTBL since array sizes may be different. */
return build_modify_expr (vtbl_ptr, NOP_EXPR,
convert (TREE_TYPE (vtbl_ptr), vtbl));
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR,
convert (TREE_TYPE (vtbl_ptr), vtbl)));
}
/* Subroutine of `expand_aggr_vbase_init'.
@ -1304,8 +1304,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree addr = build_unary_op (ADDR_EXPR, exp, 0);
expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);
expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
exp, addr, 1));
expand_vbase_vtables_init (binfo, binfo, exp, addr, 1);
}
expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
return;
@ -1427,7 +1426,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
{
tree type = TREE_TYPE (exp);
tree init_type = NULL_TREE;
tree rval;
my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
@ -1716,13 +1714,13 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
if (TREE_VALUE (init_list))
{
/* We have to ensure that the second argment to
build_virtual_init is in binfo's hierarchy. */
expand_expr_stmt (build_virtual_init (binfo,
get_binfo (TREE_VALUE (init_list), binfo, 0),
addr));
expand_virtual_init is in binfo's hierarchy. */
expand_virtual_init (binfo,
get_binfo (TREE_VALUE (init_list), binfo, 0),
addr);
if (TREE_VALUE (init_list) == binfo
&& TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
expand_vbase_vtables_init (binfo,binfo, true_exp, addr, 1);
}
}
else
@ -1771,7 +1769,7 @@ expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
{
expand_aggr_vbase_init (binfo, exp, addr, init_list);
expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
expand_vbase_vtables_init (binfo, binfo, true_exp, addr, 1);
}
expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
@ -1858,8 +1856,6 @@ tree
get_type_value (name)
tree name;
{
tree type;
if (name == error_mark_node)
return NULL_TREE;
@ -1952,7 +1948,7 @@ build_member_call (cname, name, parmlist)
return build_method_call (decl, method_name, parmlist, basetype_path,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
&& (t = lookup_field (TYPE_BINFO (type), name, 1, 0)))
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
{
if (t == error_mark_node)
return error_mark_node;
@ -2525,8 +2521,10 @@ add_friend (type, decl)
{
if (decl == TREE_VALUE (friends))
{
cp_pedwarn_at ("`%D' is already a friend of class `%T'",
decl, type);
cp_pedwarn ("`%D' is already a friend of class `%T'",
decl, type);
cp_pedwarn_at ("previous friend declaration of `%D'",
TREE_VALUE (friends));
return;
}
}
@ -2606,9 +2604,9 @@ static void
xref_friend (type, decl, ctype)
tree type, decl, ctype;
{
tree typedecl = TYPE_NAME (type);
tree friend_decl = TYPE_NAME (ctype);
#if 0
tree typedecl = TYPE_NAME (type);
tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
DECL_UNDEFINED_FRIENDS (typedecl) = t;
@ -2841,18 +2839,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
make_decl_rtl (decl, NULL_PTR, 1);
add_friend (current_class_type, decl);
if (! TREE_OVERLOADED (declarator)
&& IDENTIFIER_GLOBAL_VALUE (declarator)
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (declarator)) == FUNCTION_DECL)
{
error ("friend `%s' implicitly overloaded",
IDENTIFIER_POINTER (declarator));
cp_error_at ("after declaration of non-overloaded `%D'", IDENTIFIER_GLOBAL_VALUE (declarator));
}
DECL_FRIEND_P (decl) = 1;
DECL_OVERLOADED (decl) = 1;
TREE_OVERLOADED (declarator) = 1;
decl = push_overloaded_decl (decl, 1);
}
else
{
@ -2973,7 +2961,7 @@ build_builtin_call (type, node, arglist)
Unless I am mistaken, a call to new () will return initialized
data regardless of whether the constructor itself is private or
not.
not. NOPE; new fails if the constructor is private (jcm).
Note that build_new does nothing to assure that any special
alignment requirements of the type are met. Rather, it leaves
@ -2990,8 +2978,8 @@ build_new (placement, decl, init, use_global_new)
int use_global_new;
{
tree type, true_type, size, rval;
tree init1 = NULL_TREE, nelts;
int has_call = 0, has_array = 0;
tree nelts;
int has_array = 0;
tree pending_sizes = NULL_TREE;
@ -3014,13 +3002,7 @@ build_new (placement, decl, init, use_global_new)
nelts = integer_one_node;
if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
{
/* probably meant to be a call */
has_call = 1;
init1 = TREE_OPERAND (absdcl, 1);
absdcl = TREE_OPERAND (absdcl, 0);
TREE_VALUE (decl) = absdcl;
}
my_friendly_abort (215);
while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
{
last_absdcl = absdcl;
@ -3047,7 +3029,7 @@ build_new (placement, decl, init, use_global_new)
error ("new of array type fails to specify size");
else
{
this_nelts = save_expr (this_nelts);
this_nelts = save_expr (convert (sizetype, this_nelts));
absdcl = TREE_OPERAND (absdcl, 0);
if (this_nelts == integer_zero_node)
{
@ -3068,25 +3050,12 @@ build_new (placement, decl, init, use_global_new)
TREE_VALUE (decl) = absdcl;
type = true_type = groktypename (decl);
if (! type || type == error_mark_node
|| true_type == error_mark_node)
if (! type || type == error_mark_node)
{
immediate_size_expand = old_immediate_size_expand;
return error_mark_node;
}
/* ``A reference cannot be created by the new operator. A reference
is not an object (8.2.2, 8.4.3), so a pointer to it could not be
returned by new.'' ARM 5.3.3 */
if (TREE_CODE (type) == REFERENCE_TYPE)
error ("new cannot be applied to a reference type");
type = TYPE_MAIN_VARIANT (type);
if (type == void_type_node)
{
error ("invalid type: `void []'");
return error_mark_node;
}
if (current_function_decl
&& DECL_CONSTRUCTOR_P (current_function_decl))
{
@ -3123,42 +3092,37 @@ build_new (placement, decl, init, use_global_new)
decl = TYPE_NAME (type);
}
if (TYPE_SIZE (type) == 0)
/* ``A reference cannot be created by the new operator. A reference
is not an object (8.2.2, 8.4.3), so a pointer to it could not be
returned by new.'' ARM 5.3.3 */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (type == void_type_node)
error ("invalid type for new: `void'");
else
incomplete_type_error (0, type);
return error_mark_node;
error ("new cannot be applied to a reference type");
type = true_type = TREE_TYPE (type);
}
if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
/* When the object being created is an array, the new-expression yields a
pointer to the initial element (if any) of the array. For example,
both new int and new int[10] return an int*. 5.3.4. */
if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0)
{
abstract_virtuals_error (NULL_TREE, type);
return error_mark_node;
nelts = array_type_nelts_top (type);
has_array = 1;
type = true_type = TREE_TYPE (type);
}
if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
{
signature_error (NULL_TREE, type);
return error_mark_node;
pedwarn ("const and volatile types cannot be created with operator new");
type = true_type = TYPE_MAIN_VARIANT (type);
}
/* If our base type is an array, then make sure we know how many elements
it has. */
while (TREE_CODE (true_type) == ARRAY_TYPE)
{
tree this_nelts = array_type_nelts_top (true_type);
if (nelts == integer_one_node)
{
has_array = 1;
nelts = this_nelts;
}
else
{
my_friendly_assert (has_array != 0, 216);
nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
}
nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
true_type = TREE_TYPE (true_type);
}
if (has_array)
@ -3167,8 +3131,27 @@ build_new (placement, decl, init, use_global_new)
else
size = size_in_bytes (type);
if (has_call)
init = init1;
if (TYPE_SIZE (true_type) == 0)
{
if (true_type == void_type_node)
error ("invalid type for new: `void'");
else
incomplete_type_error (0, true_type);
return error_mark_node;
}
if (TYPE_LANG_SPECIFIC (true_type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (true_type))
{
abstract_virtuals_error (NULL_TREE, true_type);
return error_mark_node;
}
if (TYPE_LANG_SPECIFIC (true_type) && IS_SIGNATURE (true_type))
{
signature_error (NULL_TREE, true_type);
return error_mark_node;
}
/* Get a little extra space to store a couple of things before the new'ed
array. */
@ -3182,7 +3165,8 @@ build_new (placement, decl, init, use_global_new)
/* Allocate the object. */
if (TYPE_LANG_SPECIFIC (true_type)
&& (TREE_GETS_NEW (true_type) || TREE_GETS_PLACED_NEW (true_type))
&& !use_global_new)
&& !use_global_new
&& !has_array)
rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
TYPE_POINTER_TO (true_type), size, placement);
else if (placement)
@ -3302,8 +3286,7 @@ build_new (placement, decl, init, use_global_new)
if (init == void_type_node)
goto done;
if (TYPE_NEEDS_CONSTRUCTING (type)
|| (has_call || init))
if (TYPE_NEEDS_CONSTRUCTING (type) || init)
{
if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
{
@ -3719,8 +3702,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (! TYPE_NEEDS_DESTRUCTOR (type))
{
tree virtual_size;
if (auto_delete == integer_zero_node)
return void_zero_node;
@ -4100,7 +4081,7 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_tree_list (NULL_TREE,
build_x_delete (ptr_type_node, base_tbd, 0,
build_x_delete (ptr_type_node, base_tbd, 1,
virtual_size));
body = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
@ -4112,7 +4093,7 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
body = tree_cons (NULL_TREE,
build_delete (ptype, tbase, auto_delete,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
body);
body = tree_cons (NULL_TREE,

View File

@ -21,10 +21,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file is the lexical analyzer for GNU C++. */
#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
#undef YYDEBUG
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
#endif
#include <sys/types.h>
#include <stdio.h>
@ -898,7 +896,6 @@ yyhook (yyn)
{
reduce_count[yyn] += 1;
}
#endif
static int
reduce_cmp (p, q)
@ -913,6 +910,7 @@ token_cmp (p, q)
{
return token_count[*q] - token_count[*p];
}
#endif
void
print_parse_statistics ()
@ -1829,7 +1827,7 @@ cons_up_default_function (type, name, fields, kind)
IDENTIFIER_POINTER (t), func_buf);
}
}
#endif /* DEBUG_DEFAULT_FUNCTIONS
#endif /* DEBUG_DEFAULT_FUNCTIONS */
DECL_CLASS_CONTEXT (fn) = type;
@ -1858,6 +1856,7 @@ largest_union_member (type)
/* We should always find one. */
my_friendly_abort (323);
return NULL_TREE;
}
/* Construct the body of a default assignment operator.
@ -1946,7 +1945,7 @@ default_assign_ref_body (bufp, lenp, type, fields)
{
tree binfo = TREE_VEC_ELT (bases, i);
tree btype, name;
char *s, *p;
char *s;
btype = BINFO_TYPE (binfo);
name = TYPE_NESTED_NAME (btype);
@ -1976,7 +1975,7 @@ default_assign_ref_body (bufp, lenp, type, fields)
{
if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
{
char *s, *p;
char *s;
tree x;
tree t = TREE_TYPE (f);
@ -2098,7 +2097,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
for (;;)
{
tree binfo, btype, name;
char *s, *p;
char *s;
if (v)
{
@ -2143,7 +2142,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
{
if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
{
char *s, *p;
char *s;
tree x;
tree t = TREE_TYPE (f);
@ -2469,9 +2468,6 @@ check_newline ()
if (impl_file_chain == 0)
{
char *filename;
tree fi;
/* If this is zero at this point, then we are
auto-implementing. */
if (main_input_filename == 0)
@ -2577,10 +2573,16 @@ check_newline ()
else
error ("`#pragma implementation' can only appear at top-level");
interface_only = 0;
#if 0
/* We make this non-zero so that we infer decl linkage
in the impl file only for variables first declared
in the interface file. */
interface_unknown = 1;
#else
/* We make this zero so that templates in the impl
file will be emitted properly. */
interface_unknown = 0;
#endif
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
}
@ -4679,7 +4681,8 @@ make_lang_type (code)
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
TYPE_BINFO (t) = make_binfo (integer_zero_node, t, 0, 0, 0);
TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
NULL_TREE);
CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
/* Make sure this is laid out, for ease of use later.

View File

@ -32,6 +32,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "class.h"
#include "obstack.h"
#include <ctype.h>
#include "rtl.h"
#include "expr.h"
#include "output.h"
#include "hard-reg-set.h"
#include "flags.h"
/* TREE_LIST of the current inline functions that need to be
processed. */
@ -495,7 +500,7 @@ build_overload_name (parmtypes, begin, end)
if (begin) OB_INIT ();
if (just_one = (TREE_CODE (parmtypes) != TREE_LIST))
if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST)))
{
parmtype = parmtypes;
goto only_one;
@ -1651,3 +1656,254 @@ build_component_type_expr (of, component, basetype_path, protect)
TREE_TYPE (name));
return error_mark_node;
}
static char *
thunk_printable_name (decl)
tree decl;
{
return "<thunk function>";
}
tree
make_thunk (function, delta)
tree function;
int delta;
{
char buffer[250];
tree thunk_fndecl;
tree thunk;
static int thunk_number = 0;
tree func_decl;
if (TREE_CODE (function) != ADDR_EXPR)
abort ();
func_decl = TREE_OPERAND (function, 0);
if (TREE_CODE (func_decl) != FUNCTION_DECL)
abort ();
sprintf (buffer, "__thunk_%d_%d", -delta, thunk_number++);
thunk = build_decl (THUNK_DECL, get_identifier (buffer),
TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, void_type_node);
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
return thunk;
}
void
emit_thunk (thunk_fndecl)
tree thunk_fndecl;
{
rtx insns;
char *fnname;
char buffer[250];
tree argp;
struct args_size stack_args_size;
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
int delta = THUNK_DELTA (thunk_fndecl);
int tem;
int failure = 0;
/* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER];
int need_use_count = 0;
/* rtx for the 'this' parameter. */
rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
char *(*save_decl_printable_name) () = decl_printable_name;
/* Data on reg parms scanned so far. */
CUMULATIVE_ARGS args_so_far;
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
decl_printable_name = thunk_printable_name;
if (current_function_decl)
abort ();
current_function_decl = thunk_fndecl;
init_function_start (thunk_fndecl, input_filename, lineno);
pushlevel (0);
expand_start_bindings (1);
/* Start updating where the next arg would go. */
INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX);
stack_args_size.constant = 0;
stack_args_size.var = 0;
/* SETUP for possible structure return address FIXME */
/* Now look through all the parameters, make sure that we
don't clobber any registers used for parameters.
Also, pick up an rtx for the first "this" parameter. */
for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
argp != NULL_TREE;
argp = TREE_CHAIN (argp))
{
tree passed_type = TREE_VALUE (argp);
register rtx entry_parm;
int named = 1; /* FIXME */
struct args_size stack_offset;
struct args_size arg_size;
if (passed_type == void_type_node)
break;
if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
&& contains_placeholder_p (TYPE_SIZE (passed_type)))
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
|| FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far,
TYPE_MODE (passed_type),
passed_type, named)
#endif
)
passed_type = build_pointer_type (passed_type);
entry_parm = FUNCTION_ARG (args_so_far,
TYPE_MODE (passed_type),
passed_type,
named);
if (entry_parm != 0)
need_use[need_use_count++] = entry_parm;
locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
#else
entry_parm != 0,
#endif
thunk_fndecl,
&stack_args_size, &stack_offset, &arg_size);
/* REGNO (entry_parm);*/
if (this_rtx == 0)
{
this_reg_rtx = entry_parm;
if (!entry_parm)
{
rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
rtx internal_arg_pointer, stack_parm;
if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
|| ! (fixed_regs[ARG_POINTER_REGNUM]
|| ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
else
internal_arg_pointer = virtual_incoming_args_rtx;
if (offset_rtx == const0_rtx)
entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
internal_arg_pointer);
else
entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
gen_rtx (PLUS, Pmode,
internal_arg_pointer,
offset_rtx));
}
this_rtx = entry_parm;
}
FUNCTION_ARG_ADVANCE (args_so_far,
TYPE_MODE (passed_type),
passed_type,
named);
}
fixed_this_rtx = plus_constant (this_rtx, delta);
if (this_rtx != fixed_this_rtx)
emit_move_insn (this_rtx, fixed_this_rtx);
if (this_reg_rtx)
emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx));
emit_indirect_jump (XEXP (DECL_RTL (function), 0));
while (need_use_count > 0)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 1);
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
The call to resume_temporary_allocation near the end of this function
goes back to the usual state of affairs. */
rtl_in_current_obstack ();
insns = get_insns ();
/* Copy any shared structure that should not be shared. */
unshare_all_rtl (insns);
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;
/* Now we choose between stupid (pcc-like) register allocation
(if we got the -noreg switch and not -opt)
and smart register allocation. */
if (optimize > 0) /* Stupid allocation probably won't work */
obey_regdecls = 0; /* if optimizations being done. */
regclass_init ();
regclass (insns, max_reg_num ());
if (obey_regdecls)
{
stupid_life_analysis (insns, max_reg_num (), NULL);
failure = reload (insns, 0, NULL);
}
else
{
/* Do control and data flow analysis,
and write some of the results to dump file. */
flow_analysis (insns, max_reg_num (), NULL);
local_alloc ();
failure = global_alloc (NULL);
}
reload_completed = 1;
#ifdef LEAF_REGISTERS
leaf_function = 0;
if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
leaf_function = 1;
#endif
/* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG
MACHINE_DEPENDENT_REORG (insns);
#endif
/* Now turn the rtl into assembler code. */
{
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
assemble_start_function (thunk_fndecl, fnname);
final (insns, asm_out_file, optimize, 0);
assemble_end_function (thunk_fndecl, fnname);
};
exit_rest_of_compilation:
reload_completed = 0;
/* Cancel the effect of rtl_in_current_obstack. */
resume_temporary_allocation ();
decl_printable_name = save_decl_printable_name;
current_function_decl = 0;
}

View File

@ -40,10 +40,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
*/
%{
#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
#undef YYDEBUG
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
#endif
#include "config.h"
@ -74,8 +72,6 @@ void yyerror ();
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
static void position_after_white_space ();
/* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword;
@ -338,6 +334,8 @@ asm_keyword:
lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); }
extdef
{ if (! global_bindings_p () && ! pseudo_global_level_p())
pop_everything (); }
;
extdef:
@ -1226,9 +1224,11 @@ unary_expr:
$$ = build_new ($2, typename, NULL_TREE, $$ != NULL_TREE);
}
| .scope new '(' type_id ')'
{ $$ = build_new ($2, $4, NULL_TREE, $$ != NULL_TREE); }
{ $$ = build_new ($2, groktypename ($4), NULL_TREE,
$$ != NULL_TREE); }
| .scope new '(' nonnull_exprlist ')' '(' type_id ')'
{ $$ = build_new ($4, $7, NULL_TREE, $$ != NULL_TREE); }
{ $$ = build_new ($4, groktypename ($7), NULL_TREE,
$$ != NULL_TREE); }
/* Unswallow a ':' which is probably meant for ?: expression. */
| .scope new TYPENAME_COLON
{ yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
@ -1347,8 +1347,8 @@ expr_no_commas:
{ $$ = build_modify_expr ($$, NOP_EXPR, $3); }
| expr_no_commas ASSIGN expr_no_commas
{ register tree rval;
if (rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
make_node ($2)))
if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
make_node ($2))))
$$ = rval;
else
$$ = build_modify_expr ($$, $2, $3); }
@ -1473,8 +1473,7 @@ primary:
$$ = require_complete_type ($$);
}
| primary '[' expr ']'
{ do_array:
$$ = grok_array_decl ($$, $3); }
{ $$ = grok_array_decl ($$, $3); }
| object identifier_or_opname %prec UNARY
{ $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
| object id_scope identifier_or_opname %prec UNARY
@ -1570,10 +1569,6 @@ primary:
| TYPEID '(' type_id ')'
{ tree type = groktypename ($3);
$$ = get_typeid (type); }
| SCOPE typespec '(' nonnull_exprlist ')'
{ $$ = build_functional_cast ($2, $4); }
| SCOPE typespec LEFT_RIGHT
{ $$ = build_functional_cast ($2, NULL_TREE); }
| SCOPE IDENTIFIER
{
do_scoped_id:
@ -1617,7 +1612,6 @@ primary:
{
if (TREE_CODE ($2) == IDENTIFIER_NODE)
goto do_scoped_id;
do_scoped_operator:
$$ = $2;
}
| id_scope identifier_or_opname %prec HYPERUNARY
@ -2040,6 +2034,13 @@ initdcl0:
{ current_declspecs = $<ttype>0;
if (TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
current_declspecs = decl_tree_cons
(NULL_TREE, get_identifier ("extern"),
current_declspecs);
used_extern_spec = 1;
}
$<itype>5 = suspend_momentary ();
$<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
cplus_decl_attributes ($<ttype>$, $4); }
@ -2052,6 +2053,13 @@ initdcl0:
current_declspecs = $<ttype>0;
if (TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
current_declspecs = decl_tree_cons
(NULL_TREE, get_identifier ("extern"),
current_declspecs);
used_extern_spec = 1;
}
$$ = suspend_momentary ();
d = start_decl ($<ttype>1, current_declspecs, 0, $2);
cplus_decl_attributes (d, $4);

View File

@ -87,7 +87,6 @@ process_template_parm (list, next)
if (!is_type)
{
tree tinfo = 0;
int idx = 0;
parm = TREE_PURPOSE (parm);
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
parm = TREE_VALUE (parm);
@ -281,19 +280,7 @@ end_template_decl (d1, d2, is_class, defn)
{
poplevel (0, 0, 0);
poplevel (0, 0, 0);
if (TREE_TYPE (decl))
{
/* Function template */
tree t = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl));
if (t && is_overloaded_fn (t))
for (t = get_first_fn (t); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == TEMPLATE_DECL
&& duplicate_decls (decl, t))
decl = t;
push_overloaded_decl (decl, 0);
}
else
pushdecl (decl);
pushdecl (decl);
}
lose:
#if 0 /* It happens sometimes, with syntactic or semantic errors.
@ -470,7 +457,6 @@ mangle_class_name_for_template (name, parms, arglist)
static struct obstack scratch_obstack;
static char *scratch_firstobj;
int i, nparms;
char ibuf[100];
if (!scratch_firstobj)
{
@ -492,8 +478,6 @@ mangle_class_name_for_template (name, parms, arglist)
#define advance
#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
#endif
#define icat(n) sprintf(ibuf,"%d",(n)); cat(ibuf)
#define xcat(n) sprintf(ibuf,"%ux",n); cat(ibuf)
cat (name);
ccat ('<');
@ -540,7 +524,9 @@ mangle_class_name_for_template (name, parms, arglist)
ccat ('\0');
return (char *) obstack_base (&scratch_obstack);
#if 0
too_long:
#endif
fatal ("out of (preallocated) string space creating template instantiation name");
/* NOTREACHED */
return NULL;
@ -619,7 +605,11 @@ push_template_decls (parmlist, arglist, class_level)
/* Don't want to push values into global context. */
if (!class_level)
pushlevel (0);
{
pushlevel (1);
declare_pseudo_global_level ();
}
nparms = TREE_VEC_LENGTH (parmlist);
for (i = 0; i < nparms; i++)
@ -669,8 +659,6 @@ push_template_decls (parmlist, arglist, class_level)
pushdecl (decl);
}
}
if (!class_level)
set_current_level_tags_transparency (1);
}
void
@ -1235,7 +1223,7 @@ tsubst (t, args, nargs, in_decl)
{
my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
282);
if (TREE_TYPE (method) != type)
if (! comptypes (type, TREE_TYPE (method), 1))
{
tree mtype = TREE_TYPE (method);
tree t1, t2;
@ -1348,7 +1336,6 @@ tsubst (t, args, nargs, in_decl)
{
got_it = 1;
r = val;
break;
}
}
@ -2186,7 +2173,7 @@ do_pending_expansions ()
tree t = i->fndecl;
int decision = 0;
#define DECIDE(N) if(1){decision=(N); goto decided;}else
#define DECIDE(N) do {decision=(N); goto decided;} while(0)
my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
|| TREE_CODE (t) == VAR_DECL, 294);

View File

@ -377,6 +377,7 @@ pop_memoized_context (use_old)
type_stack = (struct type_level *)type_stack->base.prev;
}
#if 0 /* unused */
/* This is the newer recursive depth first search routine. */
/* Return non-zero if PARENT is directly derived from TYPE. By directly
we mean it's only one step up the inheritance lattice. We check this
@ -402,6 +403,7 @@ immediately_derived (parent, type)
}
return 0;
}
#endif
/* Check whether the type given in BINFO is derived from PARENT. If
it isn't, return 0. If it is, but the derivation is MI-ambiguous
@ -459,7 +461,7 @@ get_binfo (parent, binfo, protect)
}
/* This is the newer depth first get_base_distance routine. */
static
static int
get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
rval_private_ptr, new_binfo_ptr, parent, path_ptr,
protect, via_virtual_ptr, via_virtual)
@ -583,10 +585,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
int protect;
tree *path_ptr;
{
int head, tail;
int is_private = 0;
int rval;
int depth = 0;
int rval_private = 0;
tree type;
tree new_binfo = NULL_TREE;
@ -1966,54 +1965,31 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
}
}
/* Return the list of virtual functions which are abstract in type TYPE.
This information is cached, and so must be built on a
non-temporary obstack. */
tree
get_abstract_virtuals (type)
tree type;
/* Return the list of virtual functions which are abstract in type TYPE
that come from non virtual base classes. See init_vtbl_ptrs for
the style of search we do. */
static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
tree binfo, abstract_virtuals;
int do_self;
{
/* For each layer of base class (i.e., the first base class, and each
virtual base class from that one), modify the virtual function table
of the derived class to contain the new virtual function.
A class has as many vfields as it has virtual base classes (total). */
tree vfields, vbases, base, tmp;
tree vfield = CLASSTYPE_VFIELD (type);
tree fcontext = vfield ? DECL_FCONTEXT (vfield) : NULL_TREE;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (vfields = CLASSTYPE_VFIELDS (type); vfields; vfields = TREE_CHAIN (vfields))
for (i = 0; i < n_baselinks; i++)
{
int normal;
/* This code is most likely wrong, and probably only works for single
inheritance or by accident. */
/* Find the right base class for this derived class, call it BASE. */
base = VF_BASETYPE_VALUE (vfields);
if (base == type)
continue;
/* We call this case NORMAL iff this virtual function table
pointer field has its storage reserved in this class.
This is normally the case without virtual baseclasses
or off-center multiple baseclasses. */
normal = (base == fcontext
&& (VF_BINFO_VALUE (vfields) == NULL_TREE
|| ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
if (normal)
tmp = TREE_CHAIN (TYPE_BINFO_VIRTUALS (type));
else
{
/* n.b.: VF_BASETYPE_VALUE (vfields) is the first basetype
that provides the virtual function table, whereas
VF_DERIVED_VALUE (vfields) is an immediate base type of TYPE
that dominates VF_BASETYPE_VALUE (vfields). The list of
vfields we want lies between these two values. */
tree binfo = get_binfo (VF_NORMAL_VALUE (vfields), type, 0);
tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
}
tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
abstract_virtuals
= get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
abstract_virtuals);
}
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
/* Get around dossier entry if there is one. */
if (flag_dossier)
@ -2028,6 +2004,23 @@ get_abstract_virtuals (type)
tmp = TREE_CHAIN (tmp);
}
}
return abstract_virtuals;
}
/* Return the list of virtual functions which are abstract in type TYPE.
This information is cached, and so must be built on a
non-temporary obstack. */
tree
get_abstract_virtuals (type)
tree type;
{
tree vbases, tmp;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
/* First get all from non-virtual bases. */
abstract_virtuals
= get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
{
if (! BINFO_VIRTUALS (vbases))
@ -2414,8 +2407,7 @@ dfs_init_vbase_pointers (binfo)
{
tree type = BINFO_TYPE (binfo);
tree fields = TYPE_FIELDS (type);
tree path, this_vbase_ptr;
int distance;
tree this_vbase_ptr;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
@ -2500,9 +2492,9 @@ init_vbase_pointers (type, decl_ptr)
offsets are valid to store vtables. When zero, we must store new
vtables through virtual baseclass pointers. */
tree
build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
use_computed_offsets)
void
expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
use_computed_offsets)
tree main_binfo, binfo;
tree true_exp, decl_ptr;
int use_computed_offsets;
@ -2512,7 +2504,6 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
int old_flag = flag_this_is_variable;
tree vtable_init_result = NULL_TREE;
tree vbases = CLASSTYPE_VBASECLASSES (type);
vbase_types = CLASSTYPE_VBASECLASSES (for_type);
@ -2538,7 +2529,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
tree addr;
tree vtbl = BINFO_VTABLE (vbases);
tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
if (!flag_vtable_hack)
if (!flag_vtable_thunks)
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
@ -2552,8 +2543,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
tree ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR),
BINFO_TYPE (vbases));
init = convert_force (TREE_TYPE (ref), init);
vtable_init_result = tree_cons (NULL_TREE, build_modify_expr (ref, NOP_EXPR, init),
vtable_init_result);
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR, init));
}
}
vbases = TREE_CHAIN (vbases);
@ -2562,10 +2552,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
flag_this_is_variable = old_flag;
if (vtable_init_result)
return build_compound_expr (vtable_init_result);
}
return error_mark_node;
}
void
@ -2586,7 +2573,7 @@ dfs_get_vbase_types (binfo)
{
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
{
vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (binfo),
vbase_types = make_binfo (integer_zero_node, binfo,
BINFO_VTABLE (binfo),
BINFO_VIRTUALS (binfo), vbase_types);
TREE_VIA_VIRTUAL (vbase_types) = 1;

View File

@ -46,9 +46,11 @@ struct token {
static int do_aggr ();
static struct token frob_identifier ();
static tree hack_more_ids ();
#if 0
static struct token hack_scope ();
static tree hack_ptype ();
static tree hack_more_ids ();
#endif
/* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in.
@ -70,8 +72,10 @@ static unsigned int yylex_ctr = 0;
static int debug_yychar ();
#endif
#if 0 /* Used by arbitrate_lookup */
static char follows_typename[END_OF_SAVED_INPUT+1];
static char follows_identifier[END_OF_SAVED_INPUT+1];
#endif
/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
* of the last template_type parsed in parse.y if it is followed by a
@ -84,6 +88,7 @@ tree template_type_seen_before_scope;
void
init_spew ()
{
#if 0 /* Used by arbitrate_lookup */
static char *chars_following_identifier = ".+-|/%^!?:";
short *ps;
static short toks_follow_ids[] =
@ -102,8 +107,6 @@ init_spew ()
TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
gcc_obstack_init(&token_obstack);
/* Initialize the arrays saying what tokens are definitely
(or possibly) valid following typenames and identifiers. */
while (*chars_following_identifier)
@ -112,6 +115,9 @@ init_spew ()
follows_identifier[*ps] = 1;
for (ps = toks_follow_types; *ps != -1; ps++)
follows_typename[*ps] = 1;
#endif
gcc_obstack_init(&token_obstack);
}
#ifdef SPEW_DEBUG

View File

@ -448,7 +448,7 @@ propagate_binfo_offsets (binfo, offset)
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, k)
= make_binfo (BINFO_OFFSET (base_base_binfo),
BINFO_TYPE (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
@ -563,7 +563,7 @@ layout_vbasetypes (rec, max)
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, j)
= make_binfo (BINFO_OFFSET (base_base_binfo),
BINFO_TYPE (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
@ -600,13 +600,15 @@ layout_basetypes (rec, binfos)
unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
#endif
/* Record size so far is CONST_SIZE + VAR_SIZE bits,
where CONST_SIZE is an integer
and VAR_SIZE is a tree expression.
If VAR_SIZE is null, the size is just CONST_SIZE.
Naturally we try to avoid using VAR_SIZE. */
register unsigned const_size = 0;
/* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is
an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null,
the size is just CONST_SIZE. Naturally we try to avoid using
VAR_SIZE. And so far, we've been sucessful. */
#if 0
register tree var_size = 0;
#endif
register unsigned const_size = 0;
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Handle basetypes almost like fields, but record their
@ -945,7 +947,9 @@ get_identifier_list (value)
|| TREE_VALUE (list) != value))
list = NULL_TREE;
else if (IDENTIFIER_HAS_TYPE_VALUE (value)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE
&& IDENTIFIER_TYPE_VALUE (value)
== TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value)))
{
tree type = IDENTIFIER_TYPE_VALUE (value);
@ -1052,6 +1056,11 @@ list_hash_lookup_or_cons (value)
OFFSET is the offset added to `this' to convert it to a pointer
of type `TYPE *'
BINFO is the base binfo to use, if we are deriving from one. This
is necessary, as we want specialized parent binfos from base
classes, so that the VTABLE_NAMEs of bases are for the most derived
type, instead of of the simple type.
VTABLE is the virtual function table with which to initialize
sub-objects of type TYPE.
@ -1060,47 +1069,35 @@ list_hash_lookup_or_cons (value)
CHAIN are more associations we must retain. */
tree
make_binfo (offset, type, vtable, virtuals, chain)
tree offset, type;
make_binfo (offset, binfo, vtable, virtuals, chain)
tree offset, binfo;
tree vtable, virtuals;
tree chain;
{
tree binfo = make_tree_vec (6);
tree old_binfo = TYPE_BINFO (type);
tree last;
tree new_binfo = make_tree_vec (6);
tree type;
TREE_CHAIN (binfo) = chain;
if (chain)
TREE_USED (binfo) = TREE_USED (chain);
TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (binfo) = offset;
BINFO_VTABLE (binfo) = vtable;
BINFO_VIRTUALS (binfo) = virtuals;
BINFO_VPTR_FIELD (binfo) = NULL_TREE;
last = binfo;
if (old_binfo != NULL_TREE
&& BINFO_BASETYPES (old_binfo) != NULL_TREE)
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
tree binfos = TYPE_BINFO_BASETYPES (type);
BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses);
for (i = 0; i < n_baseclasses; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree old_base_binfo = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0;
BINFO_BASETYPE (binfo, i) = base_binfo;
if (old_binfo)
{
TREE_VIA_PUBLIC (base_binfo) = TREE_VIA_PUBLIC (old_base_binfo);
TREE_VIA_PROTECTED (base_binfo) = TREE_VIA_PROTECTED (old_base_binfo);
TREE_VIA_VIRTUAL (base_binfo) = TREE_VIA_VIRTUAL (old_base_binfo);
}
}
type = binfo;
binfo = TYPE_BINFO (binfo);
}
return binfo;
TREE_CHAIN (new_binfo) = chain;
if (chain)
TREE_USED (new_binfo) = TREE_USED (chain);
TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
BINFO_VIRTUALS (new_binfo) = virtuals;
BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));
return new_binfo;
}
tree
@ -1320,6 +1317,18 @@ is_overloaded_fn (x)
return 0;
}
int
really_overloaded_fn (x)
tree x;
{
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
|| TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
return 1;
return 0;
}
tree
get_first_fn (from)
tree from;
@ -1336,13 +1345,27 @@ tree
fnaddr_from_vtable_entry (entry)
tree entry;
{
return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
if (flag_vtable_thunks)
{
tree func = entry;
if (TREE_CODE (func) == ADDR_EXPR)
func = TREE_OPERAND (func, 0);
if (TREE_CODE (func) == THUNK_DECL)
return DECL_INITIAL (func);
else
return entry;
}
else
return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
}
void
set_fnaddr_from_vtable_entry (entry, value)
tree entry, value;
{
if (flag_vtable_thunks)
abort ();
else
TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
}

View File

@ -41,9 +41,6 @@ extern void warning ();
int mark_addressable ();
static tree convert_for_assignment ();
/* static */ tree convert_for_initialization ();
int compparms ();
static int self_promoting_args_p ();
int comp_target_types ();
extern tree shorten_compare ();
extern void binary_op_error ();
static tree pointer_int_sum ();
@ -386,7 +383,7 @@ common_type (t1, t2)
if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
{
rval = build_function_type (valtype, p2);
if (raises = TYPE_RAISES_EXCEPTIONS (t2))
if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
rval = build_exception_variant (NULL_TREE, rval, raises);
return rval;
}
@ -606,7 +603,7 @@ comptypes (type1, type2, strict)
TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict)
&& comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
&& compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)),
TREE_CHAIN (TYPE_ARG_TYPES(t2)), strict));
TREE_CHAIN (TYPE_ARG_TYPES (t2)), strict));
case POINTER_TYPE:
case REFERENCE_TYPE:
t1 = TREE_TYPE (t1);
@ -678,7 +675,7 @@ comp_target_types (ttl, ttr, nptrs)
return comp_array_types (comp_target_types, ttl, ttr, 0);
else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 0))
switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1))
{
case 0:
return 0;
@ -797,10 +794,10 @@ compparms (parms1, parms2, strict)
/* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */
if (t1 == 0)
return self_promoting_args_p (t2);
if (t2 == 0)
return self_promoting_args_p (t1);
if (strict <= 0 && t1 == 0)
return self_promoting_args_p (t2);
if (strict < 0 && t2 == 0)
return self_promoting_args_p (t1);
while (1)
{
@ -956,7 +953,7 @@ comp_target_parms (parms1, parms2, strict)
/* Return 1 if PARMS specifies a fixed number of parameters
and none of their types is affected by default promotions. */
static int
int
self_promoting_args_p (parms)
tree parms;
{
@ -2111,7 +2108,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree e2;
tree e3;
tree aref, vtbl;
tree aux_delta;
/* convert down to the right base, before using the instance. */
instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
@ -2121,7 +2117,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
vtbl = convert_pointer_to (ptr_type_node, instance);
vtbl = build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
build_pointer_type (build_pointer_type (memptr_type)),
vtbl, convert (sizetype, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, size_binop (MINUS_EXPR,
@ -3602,7 +3598,7 @@ build_component_addr (arg, argtype, msg)
baseclasses. */
rval = build1 (NOP_EXPR, argtype,
convert_pointer_to (basetype, rval));
TREE_CONSTANT (rval) == TREE_CONSTANT (TREE_OPERAND (rval, 0));
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
}
else
/* This conversion is harmless. */
@ -4935,6 +4931,7 @@ build_c_cast (type, expr)
return value;
}
#if 0
/* Build an assignment expression of lvalue LHS from value RHS.
In C++, if the left hand side of the assignment is a REFERENCE_TYPE,
@ -4969,7 +4966,6 @@ get_base_ref (type, base_index, expr)
return ref;
}
#if 0
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value.
@ -5833,6 +5829,7 @@ language_lvalue_valid (exp)
static tree
get_delta_difference (from, to, force)
tree from, to;
int force;
{
tree delta = integer_zero_node;
tree binfo;
@ -5840,6 +5837,11 @@ get_delta_difference (from, to, force)
if (to == from)
return delta;
/* Should get_base_distance here, so we can check if any thing along the
path is virtual, and we need to make sure we stay
inside the real binfos when going through virtual bases.
Maybe we should replace virtual bases with
binfo_member (...CLASSTYPE_VBASECLASSES...)... (mrs) */
binfo = get_binfo (from, to, 1);
if (binfo == error_mark_node)
{
@ -5867,7 +5869,7 @@ get_delta_difference (from, to, force)
}
if (TREE_VIA_VIRTUAL (binfo))
{
warning ("pointer to member conversion from virtual base class will only work if your very careful");
warning ("pointer to member conversion to virtual base class will only work if your very careful");
}
return fold (size_binop (MINUS_EXPR,
integer_zero_node,
@ -6815,10 +6817,8 @@ c_expand_return (retval)
{
tree whats_returned = TREE_OPERAND (retval, 0);
if (TREE_CODE (whats_returned) == TREE_LIST)
whats_returned = TREE_VALUE (whats_returned);
if (DECL_NAME (whats_returned)
if (TREE_CODE (whats_returned) == VAR_DECL
&& DECL_NAME (whats_returned)
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
&& !TREE_STATIC (whats_returned))
cp_warning_at ("address of local variable `%D' returned", whats_returned);

View File

@ -60,7 +60,7 @@ binfo_or_else (parent_or_type, type)
tree binfo;
if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type))
return parent_or_type;
if (binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))
if ((binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0)))
{
if (binfo == error_mark_node)
return NULL_TREE;
@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 355. */
/* First used: 0 (reserved), Last used: 355. Free: 180. */
static int abortcount = 0;
@ -434,9 +434,10 @@ initializer_constant_valid_p (value)
return 2;
return 0;
}
}
return 0;
default:
return 0;
}
}
/* Perform appropriate conversions on the initial value of a variable,
@ -583,6 +584,9 @@ store_init_value (decl, init)
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value)
#if 0
/* A STATIC PUBLIC int variable doesn't have to be
run time inited when doing pic. (mrs) */
/* Since ctors and dtors are the only things that can
reference vtables, and they are always written down
the the vtable definition, we can leave the
@ -590,7 +594,10 @@ store_init_value (decl, init)
However, other initialized data cannot be initialized
this way. Instead a global file-level initializer
must do the job. */
|| (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))))
|| (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
#endif
))
return value;
else
{
@ -1283,7 +1290,7 @@ build_x_arrow (datum)
if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
{
while (rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE))
while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE)))
{
if (rval == error_mark_node)
return error_mark_node;