parent
779c643ac3
commit
8926095fe7
|
@ -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)
|
||||
{
|
||||
|
|
141
gcc/cp/class.c
141
gcc/cp/class.c
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
96
gcc/cp/cvt.c
96
gcc/cp/cvt.c
|
@ -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);
|
||||
|
||||
|
|
550
gcc/cp/decl.c
550
gcc/cp/decl.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
170
gcc/cp/decl2.c
170
gcc/cp/decl2.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ";
|
||||
|
||||
|
|
|
@ -211,6 +211,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
|
|||
#endif
|
||||
}
|
||||
|
||||
case THUNK_DECL:
|
||||
return DECL_RTL (exp);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
177
gcc/cp/init.c
177
gcc/cp/init.c
|
@ -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,
|
||||
|
|
29
gcc/cp/lex.c
29
gcc/cp/lex.c
|
@ -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.
|
||||
|
|
258
gcc/cp/method.c
258
gcc/cp/method.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
33
gcc/cp/pt.c
33
gcc/cp/pt.c
|
@ -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);
|
||||
|
|
111
gcc/cp/search.c
111
gcc/cp/search.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
113
gcc/cp/tree.c
113
gcc/cp/tree.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue