parent
0207efa210
commit
7177d104dd
File diff suppressed because it is too large
Load Diff
|
@ -3810,7 +3810,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
|
||||
if (need_vtbl == needed)
|
||||
{
|
||||
function = build_vfn_ref (&TREE_VALUE (parms), instance, DECL_VINDEX (function));
|
||||
function = build_vfn_ref (&TREE_VALUE (parms), instance,
|
||||
DECL_VINDEX (function));
|
||||
TREE_TYPE (function) = build_pointer_type (fntype);
|
||||
}
|
||||
|
||||
|
@ -3975,7 +3976,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (! TREE_OVERLOADED (fnname))
|
||||
if (TREE_CODE (functions) == FUNCTION_DECL)
|
||||
{
|
||||
functions = DECL_MAIN_VARIANT (functions);
|
||||
if (final_cp)
|
||||
|
|
1172
gcc/cp/class.c
1172
gcc/cp/class.c
File diff suppressed because it is too large
Load Diff
|
@ -1071,11 +1071,11 @@ struct lang_decl
|
|||
or virtual baseclasses. */
|
||||
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/* 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))
|
||||
#define DECL_OVERLOADED(NODE) (NOTHING)
|
||||
#endif
|
||||
|
||||
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
|
||||
|
@ -1251,7 +1251,13 @@ 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)
|
||||
/* Macros for a DECL or TYPE generated from a template to indicate that it
|
||||
was explicitly instantiated. */
|
||||
#define DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_4 (NODE))
|
||||
#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \
|
||||
(DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE)))
|
||||
|
||||
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.u)
|
||||
|
||||
/* ...and for unexpanded-parameterized-type nodes. */
|
||||
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
|
||||
|
@ -1334,14 +1340,6 @@ extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
|
|||
extern tree exception_type_node, unknown_type_node;
|
||||
extern tree opaque_type_node, signature_type_node;
|
||||
|
||||
/* The largest size a virtual function table can be.
|
||||
Must be a (power of 2). */
|
||||
#ifndef VINDEX_MAX
|
||||
#define VINDEX_MAX ((unsigned)128)
|
||||
/* This is the integer ~ (vindex_max - 1). */
|
||||
#endif
|
||||
extern tree vtbl_mask;
|
||||
|
||||
/* Array type `(void *)[]' */
|
||||
extern tree vtbl_type_node;
|
||||
extern tree delta_type_node;
|
||||
|
@ -1952,7 +1950,7 @@ 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 void init_vtbl_ptrs PROTO((tree, int, int));
|
||||
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
|
||||
extern void do_member_init PROTO((tree, tree, tree));
|
||||
extern void expand_member_init PROTO((tree, tree, tree));
|
||||
extern void expand_aggr_init PROTO((tree, tree, int));
|
||||
|
@ -2101,12 +2099,12 @@ extern tree lookup_nested_tag PROTO((tree, tree));
|
|||
extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
|
||||
extern int tree_needs_constructor_p PROTO((tree, int));
|
||||
extern int tree_has_any_destructor_p PROTO((tree, int));
|
||||
extern tree get_first_matching_virtual PROTO((tree, tree, int));
|
||||
extern tree get_matching_virtual PROTO((tree, tree, int));
|
||||
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 void expand_vbase_vtables_init PROTO((tree, tree, tree, tree, int));
|
||||
extern void expand_indirect_vtbls_init PROTO((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));
|
||||
|
|
14
gcc/cp/cvt.c
14
gcc/cp/cvt.c
|
@ -706,10 +706,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
|
|||
|
||||
else if (form == REFERENCE_TYPE)
|
||||
{
|
||||
rval = copy_node (expr);
|
||||
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
|
||||
rval = build1 (NOP_EXPR,
|
||||
build_pointer_type (TREE_TYPE (TREE_TYPE (expr))),
|
||||
expr);
|
||||
rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval);
|
||||
TREE_TYPE (rval) = reftype;
|
||||
rval = build1 (NOP_EXPR, reftype, rval);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -734,7 +735,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
|
|||
if (rval != error_mark_node)
|
||||
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
|
||||
if (rval != error_mark_node)
|
||||
TREE_TYPE (rval) = reftype;
|
||||
rval = build1 (NOP_EXPR, reftype, rval);
|
||||
}
|
||||
else if (decl == error_mark_node || decl == NULL_TREE)
|
||||
{
|
||||
|
@ -1146,9 +1147,8 @@ convert_pointer_to_real (binfo, expr)
|
|||
but if it is, give them an error message that they can read. */
|
||||
if (distance < 0)
|
||||
{
|
||||
cp_error ("cannot convert a pointer of type `%T'",
|
||||
TREE_TYPE (intype));
|
||||
cp_error ("to a pointer of type `%T'", type);
|
||||
cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
|
||||
TREE_TYPE (intype), type);
|
||||
|
||||
if (distance == -2)
|
||||
cp_error ("because `%T' is an ambiguous base class", type);
|
||||
|
|
261
gcc/cp/decl.c
261
gcc/cp/decl.c
|
@ -235,9 +235,6 @@ tree opaque_type_node, signature_type_node;
|
|||
tree sigtable_entry_type;
|
||||
tree maybe_gc_cleanup;
|
||||
|
||||
/* Used for virtual function tables. */
|
||||
tree vtbl_mask;
|
||||
|
||||
/* Array type `vtable_entry_type[]' */
|
||||
tree vtbl_type_node;
|
||||
|
||||
|
@ -310,11 +307,6 @@ static tree named_label_uses;
|
|||
in the TREE_PURPOSE slot. */
|
||||
tree static_aggregates;
|
||||
|
||||
/* 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. */
|
||||
static tree overloads_to_forget;
|
||||
|
||||
/* -- end of C++ */
|
||||
|
||||
/* Two expressions that are constants with value zero.
|
||||
|
@ -340,6 +332,10 @@ int pending_invalid_xref_line;
|
|||
|
||||
static tree enum_next_value;
|
||||
|
||||
/* Nonzero means that there was overflow computing enum_next_value. */
|
||||
|
||||
static int enum_overflow;
|
||||
|
||||
/* Parsing a function declarator leaves a list of parameter names
|
||||
or a chain or parameter decls here. */
|
||||
|
||||
|
@ -535,6 +531,9 @@ struct binding_level
|
|||
/* Same, for IDENTIFIER_TYPE_VALUE. */
|
||||
tree type_shadowed;
|
||||
|
||||
/* Same, for IDENTIFIER_GLOBAL_VALUE for overloaded functions. */
|
||||
tree overloads_shadowed;
|
||||
|
||||
/* For each level (except not the global one),
|
||||
a chain of BLOCK nodes for all the levels
|
||||
that were entered and exited one level down. */
|
||||
|
@ -1026,6 +1025,9 @@ poplevel (keep, reverse, functionbody)
|
|||
for (link = current_binding_level->type_shadowed;
|
||||
link; link = TREE_CHAIN (link))
|
||||
IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
|
||||
for (link = current_binding_level->overloads_shadowed;
|
||||
link; link = TREE_CHAIN (link))
|
||||
IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
|
||||
|
||||
/* If the level being exited is the top level of a function,
|
||||
check over all the labels. */
|
||||
|
@ -1739,7 +1741,8 @@ pushtag (name, type, globalize)
|
|||
int globalize;
|
||||
{
|
||||
register struct binding_level *b;
|
||||
tree t_context = 0;
|
||||
tree context = 0;
|
||||
tree cdecl = 0;
|
||||
|
||||
b = inner_binding_level;
|
||||
while (b->tag_transparent
|
||||
|
@ -1753,9 +1756,12 @@ pushtag (name, type, globalize)
|
|||
|
||||
if (name)
|
||||
{
|
||||
t_context = type ? TYPE_CONTEXT(type) : NULL_TREE;
|
||||
if (!t_context && !globalize)
|
||||
t_context = current_class_type;
|
||||
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
|
||||
if (! context && ! globalize)
|
||||
context = current_scope ();
|
||||
if (context)
|
||||
cdecl = TREE_CODE (context) == FUNCTION_DECL
|
||||
? context : TYPE_NAME (context);
|
||||
|
||||
/* Record the identifier as the type's name if it has none. */
|
||||
if (TYPE_NAME (type) == NULL_TREE)
|
||||
|
@ -1774,8 +1780,7 @@ pushtag (name, type, globalize)
|
|||
|| TYPE_SIZE (current_class_type) != NULL_TREE)
|
||||
{
|
||||
if (current_lang_name == lang_name_cplusplus)
|
||||
d = lookup_nested_type (type,
|
||||
t_context ? TYPE_NAME (t_context) : NULL_TREE);
|
||||
d = lookup_nested_type (type, cdecl);
|
||||
else
|
||||
d = NULL_TREE;
|
||||
|
||||
|
@ -1849,29 +1854,27 @@ pushtag (name, type, globalize)
|
|||
}
|
||||
TYPE_NAME (type) = d;
|
||||
|
||||
if ((t_context == NULL_TREE
|
||||
&& current_function_decl == NULL_TREE)
|
||||
|| current_lang_name != lang_name_cplusplus)
|
||||
if (context == NULL_TREE || current_lang_name != lang_name_cplusplus)
|
||||
/* Non-nested class. */
|
||||
DECL_NESTED_TYPENAME (d) = name;
|
||||
else if (current_function_decl != NULL_TREE)
|
||||
else if (context && TREE_CODE (context) == FUNCTION_DECL)
|
||||
{
|
||||
/* Function-nested class. */
|
||||
set_nested_typename (d,
|
||||
DECL_ASSEMBLER_NAME (current_function_decl), name, type);
|
||||
set_nested_typename (d, DECL_ASSEMBLER_NAME (cdecl),
|
||||
name, type);
|
||||
/* This builds the links for classes nested in fn scope. */
|
||||
DECL_CONTEXT (d) = current_function_decl;
|
||||
DECL_CONTEXT (d) = context;
|
||||
}
|
||||
/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
|
||||
*/
|
||||
else if (t_context && TREE_CODE (t_context) == RECORD_TYPE)
|
||||
else if (context && TREE_CODE (context) == RECORD_TYPE)
|
||||
{
|
||||
/* Class-nested class. */
|
||||
set_nested_typename (d,
|
||||
DECL_NESTED_TYPENAME (TYPE_NAME (t_context)), name, type);
|
||||
set_nested_typename (d, DECL_NESTED_TYPENAME (cdecl),
|
||||
name, type);
|
||||
/* This builds the links for classes nested in type scope. */
|
||||
DECL_CONTEXT (d) = t_context;
|
||||
DECL_CLASS_CONTEXT (d) = t_context;
|
||||
DECL_CONTEXT (d) = context;
|
||||
DECL_CLASS_CONTEXT (d) = context;
|
||||
}
|
||||
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
|
||||
if (newdecl)
|
||||
|
@ -2315,6 +2318,7 @@ duplicate_decls (newdecl, olddecl)
|
|||
CLASSTYPE_FRIEND_CLASSES (newtype)
|
||||
= CLASSTYPE_FRIEND_CLASSES (oldtype);
|
||||
}
|
||||
#if 0
|
||||
/* why assert here? Just because debugging information is
|
||||
messed up? (mrs) */
|
||||
/* it happens on something like:
|
||||
|
@ -2323,7 +2327,6 @@ duplicate_decls (newdecl, olddecl)
|
|||
int x;
|
||||
} Thing;
|
||||
*/
|
||||
#if 0
|
||||
my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
|
||||
139);
|
||||
#endif
|
||||
|
@ -2709,7 +2712,9 @@ pushdecl (x)
|
|||
if (current_function_decl == x)
|
||||
current_function_decl = t;
|
||||
#endif
|
||||
|
||||
if (TREE_CODE (t) == TYPE_DECL)
|
||||
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -3088,6 +3093,31 @@ pushdecl_class_level (x)
|
|||
return x;
|
||||
}
|
||||
|
||||
/* This function is used to push the mangled decls for nested types into
|
||||
the appropriate scope. Previously pushdecl_top_level was used, but that
|
||||
is incorrect for members of local classes. */
|
||||
tree
|
||||
pushdecl_nonclass_level (x)
|
||||
tree x;
|
||||
{
|
||||
struct binding_level *b = current_binding_level;
|
||||
|
||||
#if 0
|
||||
/* Get out of class scope -- this isn't necessary, because class scope
|
||||
doesn't make it into current_binding_level. */
|
||||
while (b->parm_flag == 2)
|
||||
b = b->level_chain;
|
||||
#else
|
||||
my_friendly_assert (b->parm_flag != 2, 180);
|
||||
#endif
|
||||
|
||||
/* Get out of template binding levels */
|
||||
while (b->pseudo_global)
|
||||
b = b->level_chain;
|
||||
|
||||
pushdecl_with_scope (x, b);
|
||||
}
|
||||
|
||||
/* Make the declaration(s) of X appear in CLASS scope
|
||||
under the name NAME. */
|
||||
void
|
||||
|
@ -3142,13 +3172,6 @@ push_overloaded_decl (decl, forgettable)
|
|||
tree orig_name = DECL_NAME (decl);
|
||||
tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
|
||||
|
||||
if (forgettable
|
||||
&& ! flag_traditional
|
||||
&& (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
|
||||
&& !global_bindings_p ()
|
||||
&& !pseudo_global_level_p ())
|
||||
overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget);
|
||||
|
||||
if (glob)
|
||||
{
|
||||
/* We cache the value of builtin functions as ADDR_EXPRs
|
||||
|
@ -3197,6 +3220,16 @@ push_overloaded_decl (decl, forgettable)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forgettable
|
||||
&& ! flag_traditional
|
||||
&& (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
|
||||
&& !global_bindings_p ()
|
||||
&& !pseudo_global_level_p ())
|
||||
current_binding_level->overloads_shadowed
|
||||
= tree_cons (orig_name, glob,
|
||||
current_binding_level->overloads_shadowed);
|
||||
|
||||
if (glob || TREE_CODE (decl) == TEMPLATE_DECL)
|
||||
{
|
||||
if (glob && is_overloaded_fn (glob))
|
||||
|
@ -3832,7 +3865,6 @@ lookup_name (name, prefer_type)
|
|||
else
|
||||
val = lookup_field (got_scope, name, 0, 0);
|
||||
|
||||
got_scope = NULL_TREE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -4629,16 +4661,6 @@ init_decl_processing ()
|
|||
else
|
||||
vtable_entry_type = memptr_type;
|
||||
|
||||
#ifdef VTABLE_USES_MASK
|
||||
/* This is primarily for virtual function definition. We
|
||||
declare an array of `void *', which can later be
|
||||
converted to the appropriate function pointer type.
|
||||
To do pointers to members, we need a mask which can
|
||||
distinguish an index value into a virtual function table
|
||||
from an address. */
|
||||
vtbl_mask = build_int_2 (~((HOST_WIDE_INT) VINDEX_MAX - 1), -1);
|
||||
#endif
|
||||
|
||||
vtbl_type_node
|
||||
= build_array_type (vtable_entry_type, NULL_TREE);
|
||||
layout_type (vtbl_type_node);
|
||||
|
@ -6562,7 +6584,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
|
|||
if (check)
|
||||
check_classfn (ctype, declarator, decl);
|
||||
grok_ctor_properties (ctype, decl);
|
||||
if (check == 0)
|
||||
if (check == 0 && ! current_function_decl)
|
||||
{
|
||||
/* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
|
||||
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
|
||||
|
@ -6596,25 +6618,27 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
|
|||
if (ctype == NULL_TREE || check)
|
||||
return decl;
|
||||
|
||||
/* Now install the declaration of this function so that
|
||||
others may find it (esp. its DECL_FRIENDLIST).
|
||||
Pretend we are at top level, we will get true
|
||||
reference later, perhaps.
|
||||
|
||||
FIXME: This should only need to look at IDENTIFIER_GLOBAL_VALUE. */
|
||||
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
|
||||
if (tmp == NULL_TREE)
|
||||
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
|
||||
else if (TREE_CODE (tmp) != TREE_CODE (decl))
|
||||
cp_error ("inconsistent declarations for `%D'", decl);
|
||||
else
|
||||
/* Now install the declaration of this function so that others may
|
||||
find it (esp. its DECL_FRIENDLIST). Don't do this for local class
|
||||
methods, though. */
|
||||
if (! current_function_decl)
|
||||
{
|
||||
duplicate_decls (decl, tmp);
|
||||
decl = tmp;
|
||||
/* avoid creating circularities. */
|
||||
DECL_CHAIN (decl) = NULL_TREE;
|
||||
/* FIXME: this should only need to look at
|
||||
IDENTIFIER_GLOBAL_VALUE. */
|
||||
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
|
||||
if (tmp == NULL_TREE)
|
||||
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
|
||||
else if (TREE_CODE (tmp) != TREE_CODE (decl))
|
||||
cp_error ("inconsistent declarations for `%D'", decl);
|
||||
else
|
||||
{
|
||||
duplicate_decls (decl, tmp);
|
||||
decl = tmp;
|
||||
/* avoid creating circularities. */
|
||||
DECL_CHAIN (decl) = NULL_TREE;
|
||||
}
|
||||
make_decl_rtl (decl, NULL_PTR, 1);
|
||||
}
|
||||
make_decl_rtl (decl, NULL_PTR, 1);
|
||||
|
||||
/* If this declaration supersedes the declaration of
|
||||
a method declared virtual in the base class, then
|
||||
|
@ -6629,8 +6653,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
|
|||
if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
|
||||
|| flag_all_virtual == 1)
|
||||
{
|
||||
tmp = get_first_matching_virtual (base_binfo, decl,
|
||||
flags == DTOR_FLAG);
|
||||
tmp = get_matching_virtual (base_binfo, decl,
|
||||
flags == DTOR_FLAG);
|
||||
if (tmp)
|
||||
{
|
||||
/* If this function overrides some virtual in some base
|
||||
|
@ -6652,34 +6676,25 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
|
|||
}
|
||||
virtualp = 1;
|
||||
|
||||
#if 0
|
||||
/* Disable this as we want the most recent fndecl, not the most
|
||||
base fndecl. */
|
||||
if ((TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (base_binfo))
|
||||
|| TYPE_USES_MULTIPLE_INHERITANCE (ctype))
|
||||
&& BINFO_TYPE (base_binfo) != DECL_CONTEXT (tmp))
|
||||
tmp = get_first_matching_virtual (TYPE_BINFO (DECL_CONTEXT (tmp)),
|
||||
decl, flags == DTOR_FLAG);
|
||||
#endif
|
||||
if (value_member (tmp, DECL_VINDEX (decl)) == NULL_TREE)
|
||||
{
|
||||
/* The argument types may have changed... */
|
||||
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
||||
tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
|
||||
{
|
||||
/* The argument types may have changed... */
|
||||
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
||||
tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
|
||||
|
||||
argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
|
||||
TREE_CHAIN (argtypes));
|
||||
/* But the return type has not. */
|
||||
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
|
||||
if (raises)
|
||||
{
|
||||
type = build_exception_variant (ctype, type, raises);
|
||||
raises = TYPE_RAISES_EXCEPTIONS (type);
|
||||
}
|
||||
TREE_TYPE (decl) = type;
|
||||
DECL_VINDEX (decl)
|
||||
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
|
||||
}
|
||||
argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
|
||||
TREE_CHAIN (argtypes));
|
||||
/* But the return type has not. */
|
||||
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
|
||||
if (raises)
|
||||
{
|
||||
type = build_exception_variant (ctype, type, raises);
|
||||
raises = TYPE_RAISES_EXCEPTIONS (type);
|
||||
}
|
||||
TREE_TYPE (decl) = type;
|
||||
DECL_VINDEX (decl)
|
||||
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8852,9 +8867,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
|
|||
by the draft ANSI standard, though it appears to be in
|
||||
common practice. 12.6.2: The argument list is used to
|
||||
initialize the named nonstatic member.... This (or an
|
||||
aggregate) is the only way to initialize nonstatic const
|
||||
and reference members. */
|
||||
else
|
||||
initializer list) is the only way to initialize
|
||||
nonstatic const and reference members. */
|
||||
else if (pedantic || flag_ansi || ! constp)
|
||||
pedwarn ("ANSI C++ forbids initialization of %s `%s'",
|
||||
constp ? "const member" : "member",
|
||||
IDENTIFIER_POINTER (declarator));
|
||||
|
@ -9706,7 +9721,7 @@ xref_defn_tag (code_type_node, name, binfo)
|
|||
else
|
||||
n1 = current_class_name;
|
||||
*/
|
||||
n1 = TYPE_NAME(current_class_type);
|
||||
n1 = TYPE_NAME (current_class_type);
|
||||
if (n1)
|
||||
n1 = DECL_NESTED_TYPENAME(n1);
|
||||
else
|
||||
|
@ -9737,7 +9752,7 @@ xref_defn_tag (code_type_node, name, binfo)
|
|||
if (write_symbols == DWARF_DEBUG)
|
||||
DECL_IGNORED_P (type_decl) = 1;
|
||||
#endif /* DWARF_DEBUGGING_INFO */
|
||||
pushdecl_top_level (type_decl);
|
||||
pushdecl_nonclass_level (type_decl);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -10160,6 +10175,7 @@ start_enum (name)
|
|||
/* We copy this value because enumerated type constants
|
||||
are really of the type of the enumerator, not integer_type_node. */
|
||||
enum_next_value = copy_node (integer_zero_node);
|
||||
enum_overflow = 0;
|
||||
|
||||
GNU_xref_decl (current_function_decl, enumtype);
|
||||
return enumtype;
|
||||
|
@ -10299,7 +10315,11 @@ build_enumerator (name, value)
|
|||
to keep that from happening. */
|
||||
/* Default based on previous value. */
|
||||
if (value == NULL_TREE)
|
||||
value = enum_next_value;
|
||||
{
|
||||
value = enum_next_value;
|
||||
if (enum_overflow)
|
||||
cp_error ("overflow in enumeration values at `%D'", name);
|
||||
}
|
||||
|
||||
/* Remove no-op casts from the value. */
|
||||
if (value)
|
||||
|
@ -10322,26 +10342,8 @@ build_enumerator (name, value)
|
|||
|
||||
/* C++ associates enums with global, function, or class declarations. */
|
||||
|
||||
/* There are a number of cases we need to be aware of here:
|
||||
current_class_type current_function_decl
|
||||
* global enums NULL NULL
|
||||
* fn-local enum NULL SET
|
||||
* class-local enum SET NULL
|
||||
* class->fn->enum SET SET
|
||||
* fn->class->enum SET SET
|
||||
|
||||
Those last two make life interesting. If it's a fn-local enum which is
|
||||
itself inside a class, we need the enum to go into the fn's decls (our
|
||||
second case below). But if it's a class-local enum and the class itself
|
||||
is inside a function, we need that enum to go into the decls for the
|
||||
class. To achieve this last goal, we must see if, when both
|
||||
current_class_decl and current_function_decl are set, the class was
|
||||
declared inside that function. If so, we know to put the enum into
|
||||
the class's scope. */
|
||||
|
||||
if ((current_class_type && ! current_function_decl)
|
||||
|| (current_class_type && current_function_decl
|
||||
&& TYPE_CONTEXT (current_class_type) == current_function_decl))
|
||||
decl = current_scope ();
|
||||
if (decl && decl == current_class_type)
|
||||
{
|
||||
/* This enum declaration is local to the class, so we must put
|
||||
it in that class's list of decls. */
|
||||
|
@ -10366,6 +10368,8 @@ build_enumerator (name, value)
|
|||
/* Set basis for default for next value. */
|
||||
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
|
||||
integer_one_node, PLUS_EXPR);
|
||||
enum_overflow = tree_int_cst_lt (enum_next_value, value);
|
||||
|
||||
if (enum_next_value == integer_one_node)
|
||||
enum_next_value = copy_node (enum_next_value);
|
||||
|
||||
|
@ -10610,9 +10614,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
|
|||
if (interface_unknown == 0)
|
||||
{
|
||||
TREE_PUBLIC (decl1) = 1;
|
||||
DECL_EXTERNAL (decl1) = (interface_only
|
||||
|| (DECL_INLINE (decl1)
|
||||
&& ! flag_implement_inlines));
|
||||
DECL_EXTERNAL (decl1)
|
||||
= ((interface_only && !DECL_EXPLICITLY_INSTANTIATED (decl1))
|
||||
|| (DECL_INLINE (decl1) && ! flag_implement_inlines));
|
||||
}
|
||||
else
|
||||
/* This is a definition, not a reference.
|
||||
|
@ -11246,9 +11250,9 @@ finish_function (lineno, call_poplevel)
|
|||
/* Make all virtual function table pointers in non-virtual base
|
||||
classes point to CURRENT_CLASS_TYPE's virtual function
|
||||
tables. */
|
||||
init_vtbl_ptrs (binfo, 1, 0);
|
||||
expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
|
||||
expand_vbase_vtables_init (binfo, binfo, C_C_D, current_class_decl, 0);
|
||||
expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl, 0);
|
||||
if (! ok_to_optimize_dtor)
|
||||
{
|
||||
cond = build_binary_op (NE_EXPR,
|
||||
|
@ -11517,15 +11521,6 @@ finish_function (lineno, call_poplevel)
|
|||
else
|
||||
pop_memoized_context (1);
|
||||
|
||||
/* Forget about all overloaded functions defined in
|
||||
this scope which go away. */
|
||||
while (overloads_to_forget)
|
||||
{
|
||||
IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (overloads_to_forget))
|
||||
= TREE_VALUE (overloads_to_forget);
|
||||
overloads_to_forget = TREE_CHAIN (overloads_to_forget);
|
||||
}
|
||||
|
||||
/* Generate rtl for function exit. */
|
||||
expand_function_end (input_filename, lineno, 1);
|
||||
|
||||
|
|
|
@ -1381,6 +1381,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
|
|||
if (DECL_FRIEND_P (value))
|
||||
return void_type_node;
|
||||
|
||||
if (current_function_decl)
|
||||
cp_error ("method `%#D' of local class must be defined in class body",
|
||||
value);
|
||||
|
||||
DECL_IN_AGGR_P (value) = 1;
|
||||
return value;
|
||||
}
|
||||
|
@ -2307,6 +2311,37 @@ mark_vtable_entries (decl)
|
|||
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
|
||||
tree fn = TREE_OPERAND (fnaddr, 0);
|
||||
TREE_ADDRESSABLE (fn) = 1;
|
||||
if (DECL_ABSTRACT_VIRTUAL_P (fn))
|
||||
{
|
||||
extern tree abort_fndecl;
|
||||
TREE_OPERAND (fnaddr, 0) = abort_fndecl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
|
||||
based on TYPE and other static flags.
|
||||
|
||||
Note that anything public is tagged TREE_PUBLIC, whether
|
||||
it's public in this file or in another one. */
|
||||
|
||||
static void
|
||||
import_export_vtable (decl, type)
|
||||
tree decl, type;
|
||||
{
|
||||
if (write_virtuals >= 2)
|
||||
{
|
||||
if (CLASSTYPE_INTERFACE_KNOWN (type))
|
||||
{
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
|
||||
}
|
||||
}
|
||||
else if (write_virtuals != 0)
|
||||
{
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
if (write_virtuals < 0)
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2315,6 +2350,8 @@ finish_vtable_vardecl (prev, vars)
|
|||
tree prev, vars;
|
||||
{
|
||||
tree ctype = DECL_CONTEXT (vars);
|
||||
import_export_vtable (vars, ctype);
|
||||
|
||||
if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype))
|
||||
{
|
||||
tree method;
|
||||
|
@ -2578,6 +2615,10 @@ finish_file ()
|
|||
lineno = DECL_SOURCE_LINE (decl);
|
||||
emit_note (input_filename, lineno);
|
||||
|
||||
/* 9.5p5: The initializer of a static member of a class has
|
||||
the same acess rights as a member function. */
|
||||
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
|
||||
|
||||
if (init)
|
||||
{
|
||||
if (TREE_CODE (init) == VAR_DECL)
|
||||
|
@ -2615,19 +2656,7 @@ finish_file ()
|
|||
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|
||||
|| init == 0
|
||||
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
|
||||
{
|
||||
#if 0
|
||||
/* Set this up so is_friend() works properly on _GLOBAL_
|
||||
fns. */
|
||||
tree old_dcc = DECL_CLASS_CONTEXT (current_function_decl);
|
||||
if (old_dcc == NULL_TREE && IS_AGGR_TYPE (TREE_TYPE (decl)))
|
||||
DECL_CLASS_CONTEXT (current_function_decl) = TREE_TYPE (decl);
|
||||
expand_aggr_init (decl, init, 0);
|
||||
DECL_CLASS_CONTEXT (current_function_decl) = old_dcc;
|
||||
#else
|
||||
expand_aggr_init (decl, init, 0);
|
||||
#endif
|
||||
}
|
||||
expand_aggr_init (decl, init, 0);
|
||||
else if (TREE_CODE (init) == TREE_VEC)
|
||||
{
|
||||
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
|
||||
|
@ -2638,6 +2667,8 @@ finish_file ()
|
|||
}
|
||||
else
|
||||
expand_assignment (decl, init, 0, 0);
|
||||
|
||||
DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
|
||||
}
|
||||
else if (TREE_CODE (decl) == SAVE_EXPR)
|
||||
{
|
||||
|
|
|
@ -186,8 +186,7 @@ dump_type (t, v)
|
|||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
dump_readonly_or_volatile (t, after);
|
||||
OB_PUTID (DECL_NAME (t));
|
||||
dump_decl (t, v);
|
||||
break;
|
||||
|
||||
case INTEGER_TYPE:
|
||||
|
@ -553,6 +552,17 @@ dump_decl (t, v)
|
|||
OB_PUTS (" /* decl error */ ");
|
||||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
if (TYPE_NAME (TREE_TYPE (t)) != t)
|
||||
{
|
||||
if (v > 0)
|
||||
OB_PUTS ("typedef ");
|
||||
goto general;
|
||||
}
|
||||
|
||||
dump_type (TREE_TYPE (t), v);
|
||||
break;
|
||||
|
||||
case VAR_DECL:
|
||||
if (VTABLE_NAME_P (DECL_NAME (t)))
|
||||
{
|
||||
|
@ -563,10 +573,11 @@ dump_decl (t, v)
|
|||
/* else fall through */
|
||||
case FIELD_DECL:
|
||||
case PARM_DECL:
|
||||
general:
|
||||
if (v > 0)
|
||||
{
|
||||
dump_type_prefix (TREE_TYPE (t), v);
|
||||
OB_PUTC(' ');
|
||||
OB_PUTC (' ');
|
||||
}
|
||||
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
|
||||
if (TREE_CODE (t) == FIELD_DECL
|
||||
|
@ -574,13 +585,14 @@ dump_decl (t, v)
|
|||
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
|
||||
{
|
||||
dump_type (DECL_CONTEXT (t), 0);
|
||||
OB_PUTC2(':', ':');
|
||||
OB_PUTC2 (':', ':');
|
||||
}
|
||||
if (DECL_NAME (t))
|
||||
dump_decl (DECL_NAME (t), v);
|
||||
else
|
||||
OB_PUTS ("{anon}");
|
||||
if (v > 0) dump_type_suffix (TREE_TYPE (t), v);
|
||||
if (v > 0)
|
||||
dump_type_suffix (TREE_TYPE (t), v);
|
||||
break;
|
||||
|
||||
case ARRAY_REF:
|
||||
|
@ -598,10 +610,6 @@ dump_decl (t, v)
|
|||
dump_type (t, v);
|
||||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
dump_type (TREE_TYPE (t), v);
|
||||
break;
|
||||
|
||||
case TYPE_EXPR:
|
||||
my_friendly_abort (69);
|
||||
break;
|
||||
|
|
153
gcc/cp/init.c
153
gcc/cp/init.c
|
@ -50,7 +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));
|
||||
static void expand_virtual_init PROTO((tree, tree));
|
||||
tree expand_vec_init ();
|
||||
|
||||
static void add_friend (), add_friends ();
|
||||
|
@ -101,23 +101,40 @@ void init_init_processing ()
|
|||
virtual base classes. Initialize binfo's vtable pointer, if
|
||||
INIT_SELF is true. CAN_ELIDE is true when we know that all virtual
|
||||
function table pointers in all bases have been initialized already,
|
||||
probably because their constructors have just be run. */
|
||||
probably because their constructors have just be run. ADDR is the
|
||||
pointer to the object whos vtables we are going to initialize.
|
||||
|
||||
REAL_BINFO is usually the same as BINFO, except when addr is not of
|
||||
pointer to the type of the real derived type that we want to
|
||||
initialize for. This is the case when addr is a pointer to a sub
|
||||
object of a complete object, and we only want to do part of the
|
||||
complete object's initiailzation of vtable pointers. This is done
|
||||
for all virtual table pointers in virtual base classes. REAL_BINFO
|
||||
is used to find the BINFO_VTABLE that we initialize with. BINFO is
|
||||
used for conversions of addr to subobjects.
|
||||
|
||||
BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).
|
||||
|
||||
Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
|
||||
(addr))). */
|
||||
void
|
||||
init_vtbl_ptrs (binfo, init_self, can_elide)
|
||||
tree binfo;
|
||||
expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
|
||||
tree real_binfo, binfo, addr;
|
||||
int init_self, can_elide;
|
||||
{
|
||||
tree vfields;
|
||||
tree real_binfos = BINFO_BASETYPES (real_binfo);
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
|
||||
|
||||
for (i = 0; i < n_baselinks; i++)
|
||||
{
|
||||
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
|
||||
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))
|
||||
init_vtbl_ptrs (base_binfo, is_not_base_vtable, can_elide);
|
||||
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
|
||||
if (! TREE_VIA_VIRTUAL (real_base_binfo))
|
||||
expand_direct_vtbls_init (real_base_binfo, base_binfo,
|
||||
is_not_base_vtable, can_elide, addr);
|
||||
}
|
||||
#if 0
|
||||
/* Before turning this on, make sure it is correct. */
|
||||
|
@ -125,10 +142,10 @@ init_vtbl_ptrs (binfo, init_self, can_elide)
|
|||
return;
|
||||
#endif
|
||||
/* Should we use something besides CLASSTYPE_VFIELDS? */
|
||||
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
|
||||
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
|
||||
{
|
||||
tree base_ptr = convert_pointer_to_real (binfo, current_class_decl);
|
||||
expand_virtual_init (binfo, binfo, base_ptr);
|
||||
tree base_ptr = convert_pointer_to_real (binfo, addr);
|
||||
expand_virtual_init (real_binfo, base_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,17 +622,13 @@ 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_vbase_vtables_init (t_binfo, t_binfo,
|
||||
C_C_D, current_class_decl, 0);
|
||||
expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
|
||||
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
|
||||
CLEAR_BINFO_BASEINIT_MARKED (vbases);
|
||||
|
||||
/* Initialize all the virtual function table fields that
|
||||
do not come from virtual base classes. */
|
||||
init_vtbl_ptrs (t_binfo, 0, 1);
|
||||
|
||||
if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
|
||||
expand_virtual_init (TYPE_BINFO (t), t, current_class_decl);
|
||||
expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
|
||||
|
||||
if (current_member_init_list)
|
||||
{
|
||||
|
@ -709,84 +722,31 @@ 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. */
|
||||
static void
|
||||
expand_virtual_init (main_binfo, binfo, decl)
|
||||
tree main_binfo, binfo;
|
||||
tree decl;
|
||||
expand_virtual_init (binfo, decl)
|
||||
tree binfo, decl;
|
||||
{
|
||||
tree type;
|
||||
tree type = BINFO_TYPE (binfo);
|
||||
tree vtbl, vtbl_ptr;
|
||||
tree vtype, vtype_binfo;
|
||||
|
||||
if (TREE_CODE (binfo) == TREE_VEC)
|
||||
type = BINFO_TYPE (binfo);
|
||||
else if (TREE_CODE (binfo) == RECORD_TYPE)
|
||||
{
|
||||
type = binfo;
|
||||
binfo = TYPE_BINFO (type);
|
||||
}
|
||||
else
|
||||
my_friendly_abort (46);
|
||||
|
||||
/* This code is crusty. Should be simple, like:
|
||||
vtbl = BINFO_VTABLE (binfo);
|
||||
*/
|
||||
vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
|
||||
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
|
||||
#if 0
|
||||
/* This code suggests that it's time to rewrite how we handle
|
||||
replicated baseclasses in G++. */
|
||||
if (get_base_distance (vtype, TREE_TYPE (TREE_TYPE (decl)),
|
||||
0, (tree *) 0) == -2)
|
||||
{
|
||||
tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
for (i = n_baselinks-1; i >= 0; i--)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
tree this_decl;
|
||||
|
||||
if (get_base_distance (vtype, BINFO_TYPE (base_binfo), 0, 0) == -1)
|
||||
continue;
|
||||
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
this_decl = build_vbase_pointer (build_indirect_ref (decl, NULL_PTR), BINFO_TYPE (base_binfo));
|
||||
else if (BINFO_OFFSET_ZEROP (base_binfo))
|
||||
this_decl = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
|
||||
decl);
|
||||
else
|
||||
this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
|
||||
decl, BINFO_OFFSET (base_binfo));
|
||||
expand_virtual_init (main_binfo, base_binfo, this_decl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
#if 1
|
||||
#if 1
|
||||
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
|
||||
#else
|
||||
/* The below does not work when we have to step through the
|
||||
vfield, on our way down to the most base class for the
|
||||
vfield. */
|
||||
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)),
|
||||
BINFO_TYPE (main_binfo)));
|
||||
#endif
|
||||
#else
|
||||
my_friendly_assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo), 208);
|
||||
vtbl = BINFO_VTABLE (main_binfo);
|
||||
#endif /* 1 */
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
|
||||
}
|
||||
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
|
||||
if (!flag_vtable_thunks)
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
|
||||
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;
|
||||
|
||||
/* Have to convert VTBL since array sizes may be different. */
|
||||
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR,
|
||||
convert (TREE_TYPE (vtbl_ptr), vtbl)));
|
||||
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl);
|
||||
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
|
||||
}
|
||||
|
||||
/* Subroutine of `expand_aggr_vbase_init'.
|
||||
|
@ -1307,7 +1267,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_vbase_vtables_init (binfo, binfo, exp, addr, 1);
|
||||
expand_indirect_vtbls_init (binfo, exp, addr, 1);
|
||||
}
|
||||
expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
|
||||
return;
|
||||
|
@ -1716,14 +1676,16 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
|
|||
are initializing the ultimate users of those vtables. */
|
||||
if (TREE_VALUE (init_list))
|
||||
{
|
||||
/* We have to ensure that the second argment to
|
||||
/* We have to ensure that the first argment to
|
||||
expand_virtual_init is in binfo's hierarchy. */
|
||||
expand_virtual_init (binfo,
|
||||
get_binfo (TREE_VALUE (init_list), binfo, 0),
|
||||
/* Is it the case that this is exactly the right binfo? */
|
||||
/* If it is ok, then fixup expand_virtual_init, to make
|
||||
it much simpler. */
|
||||
expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0),
|
||||
addr);
|
||||
if (TREE_VALUE (init_list) == binfo
|
||||
&& TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
|
||||
expand_vbase_vtables_init (binfo,binfo, true_exp, addr, 1);
|
||||
expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1772,7 +1734,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_vbase_vtables_init (binfo, binfo, true_exp, addr, 1);
|
||||
expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
|
||||
}
|
||||
expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
|
||||
|
||||
|
@ -2202,14 +2164,6 @@ get_member_function (exp_addr_ptr, exp, member)
|
|||
/* Cast function to signed integer. */
|
||||
e0 = build1 (NOP_EXPR, integer_type_node, function);
|
||||
|
||||
#ifdef VTABLE_USES_MASK
|
||||
/* If we are willing to limit the number of
|
||||
virtual functions a class may have to some
|
||||
*small* number, then if, for a function address,
|
||||
we are passed some small number, we know that
|
||||
it is a virtual function index, and work from there. */
|
||||
e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);
|
||||
#else
|
||||
/* There is a hack here that takes advantage of
|
||||
twos complement arithmetic, and the fact that
|
||||
there are more than one UNITS to the WORD.
|
||||
|
@ -2224,7 +2178,6 @@ get_member_function (exp_addr_ptr, exp, member)
|
|||
e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
|
||||
build_tree_list (NULL_TREE, e1)));
|
||||
e1 = save_expr (e1);
|
||||
#endif
|
||||
|
||||
if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
|
||||
{
|
||||
|
@ -2830,7 +2783,9 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
|
|||
add_friend (current_class_type, decl);
|
||||
|
||||
DECL_FRIEND_P (decl) = 1;
|
||||
#if 0
|
||||
TREE_OVERLOADED (declarator) = 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1162,11 +1162,13 @@ do_pending_inlines ()
|
|||
/* Pass back a handle on the rest of the inline functions, so that they
|
||||
can be processed later. */
|
||||
yylval.ttype = build_tree_list ((tree) t, t->fndecl);
|
||||
#if 0
|
||||
if (flag_default_inline && t->fndecl
|
||||
/* If we're working from a template, don't change
|
||||
the `inline' state. */
|
||||
&& t->parm_vec == NULL_TREE)
|
||||
DECL_INLINE (t->fndecl) = 1;
|
||||
#endif
|
||||
DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
|
||||
}
|
||||
|
||||
|
@ -1215,11 +1217,13 @@ process_next_inline (t)
|
|||
input_filename = i->filename;
|
||||
yychar = PRE_PARSED_FUNCTION_DECL;
|
||||
yylval.ttype = build_tree_list ((tree) i, i->fndecl);
|
||||
#if 0
|
||||
if (flag_default_inline
|
||||
/* If we're working from a template, don't change
|
||||
the `inline' state. */
|
||||
&& i->parm_vec == NULL_TREE)
|
||||
DECL_INLINE (i->fndecl) = 1;
|
||||
#endif
|
||||
DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
|
||||
}
|
||||
if (i)
|
||||
|
@ -2577,7 +2581,7 @@ check_newline ()
|
|||
else
|
||||
error ("`#pragma implementation' can only appear at top-level");
|
||||
interface_only = 0;
|
||||
#if 0
|
||||
#if 1
|
||||
/* We make this non-zero so that we infer decl linkage
|
||||
in the impl file only for variables first declared
|
||||
in the interface file. */
|
||||
|
@ -4576,6 +4580,7 @@ build_lang_decl (code, name, type)
|
|||
if (current_lang_name == lang_name_cplusplus)
|
||||
{
|
||||
DECL_LANGUAGE (t) = lang_cplusplus;
|
||||
#if 0
|
||||
#ifndef NO_AUTO_OVERLOAD
|
||||
if (code == FUNCTION_DECL && name != 0
|
||||
&& ! (IDENTIFIER_LENGTH (name) == 4
|
||||
|
@ -4586,6 +4591,7 @@ build_lang_decl (code, name, type)
|
|||
&& IDENTIFIER_POINTER (name)[1] == '_'
|
||||
&& strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
|
||||
TREE_OVERLOADED (name) = 1;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else if (current_lang_name == lang_name_c)
|
||||
|
|
|
@ -111,8 +111,10 @@ do_inline_function_hair (type, friend_list)
|
|||
args = TREE_CHAIN (args);
|
||||
}
|
||||
|
||||
/* Allow this decl to be seen in global scope */
|
||||
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
|
||||
/* Allow this decl to be seen in global scope. Don't do this for
|
||||
local class methods, though. */
|
||||
if (! current_function_decl)
|
||||
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
|
||||
}
|
||||
method = TREE_CHAIN (method);
|
||||
}
|
||||
|
@ -1698,6 +1700,7 @@ emit_thunk (thunk_fndecl)
|
|||
int delta = THUNK_DELTA (thunk_fndecl);
|
||||
int tem;
|
||||
int failure = 0;
|
||||
extern int current_call_is_indirect; /* Needed for (at least) HPPA. */
|
||||
|
||||
/* Used to remember which regs we need to emit a USE rtx for. */
|
||||
rtx need_use[FIRST_PSEUDO_REGISTER];
|
||||
|
|
|
@ -779,8 +779,9 @@ identifier_defn:
|
|||
|
||||
explicit_instantiation:
|
||||
TEMPLATE aggr template_type
|
||||
{ do_type_instantiation ($3); }
|
||||
| TEMPLATE typed_declspecs declarator
|
||||
{ do_function_instantiation ($2, $3); }
|
||||
{ do_function_instantiation ($2, $3); }
|
||||
;
|
||||
|
||||
template_type:
|
||||
|
@ -844,6 +845,8 @@ template_instantiate_once:
|
|||
pop_obstacks ();
|
||||
pushdecl_top_level (decl);
|
||||
}
|
||||
/* Kludge; see instantiate_class_template. */
|
||||
TYPE_BEING_DEFINED (t) = 0;
|
||||
}
|
||||
left_curly opt.component_decl_list '}'
|
||||
{
|
||||
|
|
29
gcc/cp/pt.c
29
gcc/cp/pt.c
|
@ -1013,6 +1013,8 @@ instantiate_class_template (classname, setup_parse)
|
|||
/* Get interface/implementation back in sync. */
|
||||
extract_interface_info ();
|
||||
overload_template_name (classname, 0);
|
||||
/* Kludge so that we don't get screwed by our own base classes. */
|
||||
TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;
|
||||
yychar = PRE_PARSED_CLASS_DECL;
|
||||
yylval.ttype = classname;
|
||||
processing_template_defn++;
|
||||
|
@ -2187,6 +2189,10 @@ do_pending_expansions ()
|
|||
|| TREE_CODE (t) == VAR_DECL, 294);
|
||||
if (TREE_ASM_WRITTEN (t))
|
||||
DECIDE (0);
|
||||
|
||||
if (DECL_EXPLICITLY_INSTANTIATED (t))
|
||||
DECIDE (1);
|
||||
|
||||
/* If it's a method, let the class type decide it.
|
||||
@@ What if the method template is in a separate file?
|
||||
Maybe both file contexts should be taken into account?
|
||||
|
@ -2311,8 +2317,29 @@ do_function_instantiation (declspecs, declarator)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
if (! result)
|
||||
cp_error ("no matching template for `%D' found", decl);
|
||||
|
||||
DECL_EXPLICITLY_INSTANTIATED (result) = 1;
|
||||
}
|
||||
|
||||
void
|
||||
do_type_instantiation (name)
|
||||
tree name;
|
||||
{
|
||||
tree t = TREE_TYPE (name);
|
||||
|
||||
CLASSTYPE_EXPLICITLY_INSTANTIATED (t) = 1;
|
||||
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
|
||||
|
||||
/* this should really be done by instantiate_member_templates */
|
||||
{
|
||||
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
|
||||
for (; method; method = TREE_CHAIN (method))
|
||||
DECL_EXPLICITLY_INSTANTIATED (method) = 1;
|
||||
}
|
||||
|
||||
/* and data member templates, too */
|
||||
}
|
||||
|
||||
tree
|
||||
|
|
165
gcc/cp/search.c
165
gcc/cp/search.c
|
@ -687,6 +687,22 @@ lookup_field_1 (type, name)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* There are a number of cases we need to be aware of here:
|
||||
current_class_type current_function_decl
|
||||
* global NULL NULL
|
||||
* fn-local NULL SET
|
||||
* class-local SET NULL
|
||||
* class->fn SET SET
|
||||
* fn->class SET SET
|
||||
|
||||
Those last two make life interesting. If we're in a function which is
|
||||
itself inside a class, we need decls to go into the fn's decls (our
|
||||
second case below). But if we're in a class and the class itself is
|
||||
inside a function, we need decls to go into the decls for the class. To
|
||||
achieve this last goal, we must see if, when both current_class_decl and
|
||||
current_function_decl are set, the class was declared inside that
|
||||
function. If so, we know to put the decls into the class's scope. */
|
||||
|
||||
tree
|
||||
current_scope ()
|
||||
{
|
||||
|
@ -1842,14 +1858,14 @@ int tree_has_any_destructor_p (binfo, i)
|
|||
return TYPE_NEEDS_DESTRUCTOR (type);
|
||||
}
|
||||
|
||||
/* Given a class type TYPE, and a function decl FNDECL,
|
||||
look for the first function the TYPE's hierarchy which
|
||||
FNDECL could match as a virtual function.
|
||||
/* Given a class type TYPE, and a function decl FNDECL, look for a
|
||||
virtual function in TYPE's hierarchy which FNDECL could match as a
|
||||
virtual function. It doesn't matter which one we find.
|
||||
|
||||
DTORP is nonzero if we are looking for a destructor. Destructors
|
||||
need special treatment because they do not match by name. */
|
||||
tree
|
||||
get_first_matching_virtual (binfo, fndecl, dtorp)
|
||||
get_matching_virtual (binfo, fndecl, dtorp)
|
||||
tree binfo, fndecl;
|
||||
int dtorp;
|
||||
{
|
||||
|
@ -1863,22 +1879,11 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
|
|||
tmp = get_virtual_destructor (binfo, -1);
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
if (get_base_distance (DECL_CONTEXT (tmp),
|
||||
DECL_CONTEXT (fndecl), 0, 0) > 0)
|
||||
DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
|
||||
return tmp;
|
||||
}
|
||||
return tmp;
|
||||
|
||||
tmp = (tree) breadth_first_search (binfo,
|
||||
(pfi) get_virtual_destructor,
|
||||
tree_has_any_destructor_p);
|
||||
if (tmp)
|
||||
{
|
||||
if (get_base_distance (DECL_CONTEXT (tmp),
|
||||
DECL_CONTEXT (fndecl), 0, 0) > 0)
|
||||
DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
else
|
||||
|
@ -1931,33 +1936,20 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
|
|||
}
|
||||
if (tmp)
|
||||
{
|
||||
/* If this is ambiguous, we will warn about it later. */
|
||||
if (best)
|
||||
{
|
||||
if (get_base_distance (DECL_CLASS_CONTEXT (best),
|
||||
DECL_CLASS_CONTEXT (tmp), 0, 0) > 0)
|
||||
best = tmp;
|
||||
}
|
||||
else
|
||||
best = tmp;
|
||||
best = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (best == NULL_TREE && warn_overloaded_virtual)
|
||||
cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl);
|
||||
|
||||
if (best)
|
||||
{
|
||||
if (get_base_distance (DECL_CONTEXT (best),
|
||||
DECL_CONTEXT (fndecl), 0, 0) > 0)
|
||||
DECL_CONTEXT (fndecl) = DECL_CONTEXT (best);
|
||||
}
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/* Return the list of virtual functions which are abstract in type
|
||||
TYPE that come from non virtual base classes. See
|
||||
expand_direct_vtbls_init for the style of search we do. */
|
||||
static tree
|
||||
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
|
||||
tree binfo, abstract_virtuals;
|
||||
|
@ -2364,7 +2356,9 @@ dfs_debug_mark (binfo)
|
|||
}
|
||||
|
||||
/* Attach to the type of the virtual base class, the pointer to the
|
||||
virtual base class, given the global pointer vbase_decl_ptr. */
|
||||
virtual base class, given the global pointer vbase_decl_ptr.
|
||||
|
||||
We use the global vbase_types. ICK! */
|
||||
static void
|
||||
dfs_find_vbases (binfo)
|
||||
tree binfo;
|
||||
|
@ -2471,32 +2465,32 @@ init_vbase_pointers (type, decl_ptr)
|
|||
|
||||
/* Build a COMPOUND_EXPR which when expanded will generate the code
|
||||
needed to initialize all the virtual function table slots of all
|
||||
the virtual baseclasses. FOR_TYPE is the type which determines the
|
||||
virtual baseclasses to use; TYPE is the type of the object to which
|
||||
the initialization applies. TRUE_EXP is the true object we are
|
||||
initializing, and DECL_PTR is the pointer to the sub-object we
|
||||
the virtual baseclasses. MAIN_BINFO is the binfo which determines
|
||||
the virtual baseclasses to use; TYPE is the type of the object to
|
||||
which the initialization applies. TRUE_EXP is the true object we
|
||||
are initializing, and DECL_PTR is the pointer to the sub-object we
|
||||
are initializing.
|
||||
|
||||
When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
|
||||
object was laidout by a top-level contructor and the computed
|
||||
offsets are valid to store vtables. When zero, we must store new
|
||||
vtables through virtual baseclass pointers. */
|
||||
vtables through virtual baseclass pointers.
|
||||
|
||||
We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
|
||||
ICK! */
|
||||
|
||||
void
|
||||
expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
|
||||
use_computed_offsets)
|
||||
tree main_binfo, binfo;
|
||||
expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
|
||||
tree binfo;
|
||||
tree true_exp, decl_ptr;
|
||||
int use_computed_offsets;
|
||||
{
|
||||
tree for_type = BINFO_TYPE (main_binfo);
|
||||
tree type = BINFO_TYPE (binfo);
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
|
||||
{
|
||||
int old_flag = flag_this_is_variable;
|
||||
tree vbases = CLASSTYPE_VBASECLASSES (type);
|
||||
|
||||
vbase_types = CLASSTYPE_VBASECLASSES (for_type);
|
||||
vbase_types = vbases;
|
||||
vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
|
||||
vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
|
||||
|
||||
|
@ -2504,38 +2498,25 @@ expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
|
|||
{
|
||||
/* This is an object of type IN_TYPE, */
|
||||
flag_this_is_variable = -2;
|
||||
dfs_walk (main_binfo, dfs_find_vbases, unmarked_new_vtablep);
|
||||
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
|
||||
}
|
||||
|
||||
/* Initialized with vtables of type TYPE. */
|
||||
while (vbases)
|
||||
{
|
||||
/* This time through, not every class's vtable
|
||||
is going to be initialized. That is, we only initialize
|
||||
the "last" vtable pointer. */
|
||||
tree addr;
|
||||
if (use_computed_offsets)
|
||||
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
|
||||
else
|
||||
addr = convert_pointer_to (vbases, vbase_decl_ptr);
|
||||
if (addr == error_mark_node)
|
||||
continue;
|
||||
|
||||
if (CLASSTYPE_VSIZE (BINFO_TYPE (vbases)))
|
||||
{
|
||||
tree addr;
|
||||
tree vtbl = BINFO_VTABLE (vbases);
|
||||
tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
|
||||
if (!flag_vtable_thunks)
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
|
||||
if (use_computed_offsets)
|
||||
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
|
||||
else
|
||||
addr = convert_pointer_to (vbases, vbase_decl_ptr);
|
||||
|
||||
if (addr)
|
||||
{
|
||||
tree ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR),
|
||||
BINFO_TYPE (vbases));
|
||||
init = convert_force (TREE_TYPE (ref), init);
|
||||
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR, init));
|
||||
}
|
||||
}
|
||||
/* Do all vtables from this virtual base. */
|
||||
/* This assumes that virtual bases can never serve as parent
|
||||
binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
|
||||
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
|
||||
1, 0, addr);
|
||||
vbases = TREE_CHAIN (vbases);
|
||||
}
|
||||
|
||||
|
@ -3114,46 +3095,6 @@ pop_class_decls (type)
|
|||
search_stack = pop_search_level (search_stack);
|
||||
}
|
||||
|
||||
static int
|
||||
bfs_unmark_finished_struct (binfo, i)
|
||||
tree binfo;
|
||||
int i;
|
||||
{
|
||||
if (i >= 0)
|
||||
binfo = BINFO_BASETYPE (binfo, i);
|
||||
|
||||
if (BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
{
|
||||
tree decl, context;
|
||||
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
binfo = binfo_member (BINFO_TYPE (binfo),
|
||||
CLASSTYPE_VBASECLASSES (current_class_type));
|
||||
|
||||
decl = BINFO_VTABLE (binfo);
|
||||
context = DECL_CONTEXT (decl);
|
||||
DECL_CONTEXT (decl) = 0;
|
||||
if (write_virtuals >= 0
|
||||
&& DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
|
||||
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
|
||||
BINFO_VIRTUALS (binfo));
|
||||
finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
|
||||
DECL_CONTEXT (decl) = context;
|
||||
}
|
||||
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
|
||||
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
unmark_finished_struct (type)
|
||||
tree type;
|
||||
{
|
||||
tree binfo = TYPE_BINFO (type);
|
||||
bfs_unmark_finished_struct (binfo, -1);
|
||||
breadth_first_search (binfo, bfs_unmark_finished_struct, bfs_marked_vtable_pathp);
|
||||
}
|
||||
|
||||
void
|
||||
print_search_statistics ()
|
||||
{
|
||||
|
|
|
@ -311,7 +311,8 @@ yylex()
|
|||
if (lastiddecl != trrr)
|
||||
{
|
||||
lastiddecl = trrr;
|
||||
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
|
||||
if (got_scope)
|
||||
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
|
||||
}
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
|
@ -326,6 +327,7 @@ yylex()
|
|||
}
|
||||
else
|
||||
lastiddecl = trrr;
|
||||
got_scope = NULL_TREE;
|
||||
/* and fall through to... */
|
||||
case TYPENAME:
|
||||
case PTYPENAME:
|
||||
|
|
|
@ -585,6 +585,9 @@ layout_vbasetypes (rec, max)
|
|||
|
||||
Offsets for immediate nonvirtual baseclasses are also computed here.
|
||||
|
||||
TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine
|
||||
creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS.
|
||||
|
||||
Returns list of virtual base classes in a FIELD_DECL chain. */
|
||||
tree
|
||||
layout_basetypes (rec, binfos)
|
||||
|
|
|
@ -662,6 +662,8 @@ comp_target_types (ttl, ttr, nptrs)
|
|||
ttr = TYPE_MAIN_VARIANT (ttr);
|
||||
if (ttl == ttr)
|
||||
return 1;
|
||||
if (TREE_CODE (ttr) == TEMPLATE_TYPE_PARM)
|
||||
return 1;
|
||||
|
||||
if (TREE_CODE (ttr) != TREE_CODE (ttl))
|
||||
return 0;
|
||||
|
@ -877,6 +879,9 @@ comp_target_parms (parms1, parms2, strict)
|
|||
p2 = TREE_VALUE (t2);
|
||||
if (p1 == p2)
|
||||
continue;
|
||||
if (TREE_CODE (p2) == TEMPLATE_TYPE_PARM)
|
||||
continue;
|
||||
|
||||
if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
|
||||
|| (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
|
||||
{
|
||||
|
@ -885,6 +890,9 @@ comp_target_parms (parms1, parms2, strict)
|
|||
== TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (p2)) == TEMPLATE_TYPE_PARM)
|
||||
continue;
|
||||
|
||||
/* The following is wrong for contravariance,
|
||||
but many programs depend on it. */
|
||||
if (TREE_TYPE (p1) == void_type_node)
|
||||
|
@ -4591,24 +4599,28 @@ build_conditional_expr (ifexp, op1, op2)
|
|||
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
|
||||
{
|
||||
if (!integer_zerop (op2))
|
||||
warning ("pointer/integer type mismatch in conditional expression");
|
||||
pedwarn ("pointer/integer type mismatch in conditional expression");
|
||||
else
|
||||
{
|
||||
op2 = null_pointer_node;
|
||||
#if 0 /* Sez who? */
|
||||
if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
|
||||
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
|
||||
#endif
|
||||
}
|
||||
result_type = type1;
|
||||
}
|
||||
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
|
||||
{
|
||||
if (!integer_zerop (op1))
|
||||
warning ("pointer/integer type mismatch in conditional expression");
|
||||
pedwarn ("pointer/integer type mismatch in conditional expression");
|
||||
else
|
||||
{
|
||||
op1 = null_pointer_node;
|
||||
#if 0 /* Sez who? */
|
||||
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
|
||||
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
|
||||
#endif
|
||||
}
|
||||
result_type = type2;
|
||||
op1 = null_pointer_node;
|
||||
|
@ -6186,19 +6198,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
|
|||
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
|
||||
{
|
||||
if (fndecl)
|
||||
cp_warning ("passing `%T' as argument %P of `%D' discards const",
|
||||
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
|
||||
rhstype, parmnum, fndecl);
|
||||
else
|
||||
cp_warning ("%s to `%T' from `%T' discards const",
|
||||
cp_pedwarn ("%s to `%T' from `%T' discards const",
|
||||
errtype, type, rhstype);
|
||||
}
|
||||
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
|
||||
{
|
||||
if (fndecl)
|
||||
cp_warning ("passing `%T' as argument %P of `%D' discards volatile",
|
||||
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
|
||||
rhstype, parmnum, fndecl);
|
||||
else
|
||||
cp_warning ("%s to `%T' from `%T' discards volatile",
|
||||
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
|
||||
errtype, type, rhstype);
|
||||
}
|
||||
}
|
||||
|
@ -6244,19 +6256,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
|
|||
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
|
||||
{
|
||||
if (fndecl)
|
||||
cp_warning ("passing `%T' as argument %P of `%D' discards const",
|
||||
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
|
||||
rhstype, parmnum, fndecl);
|
||||
else
|
||||
cp_warning ("%s to `%T' from `%T' discards const",
|
||||
cp_pedwarn ("%s to `%T' from `%T' discards const",
|
||||
errtype, type, rhstype);
|
||||
}
|
||||
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
|
||||
{
|
||||
if (fndecl)
|
||||
cp_warning ("passing `%T' as argument %P of `%D' discards volatile",
|
||||
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
|
||||
rhstype, parmnum, fndecl);
|
||||
else
|
||||
cp_warning ("%s to `%T' from `%T' discards volatile",
|
||||
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
|
||||
errtype, type, rhstype);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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. Free: 180. */
|
||||
/* First used: 0 (reserved), Last used: 357. Free: */
|
||||
|
||||
static int abortcount = 0;
|
||||
|
||||
|
@ -707,56 +707,6 @@ digest_init (type, init, tail)
|
|||
return element;
|
||||
}
|
||||
|
||||
/* Check for initializing a union by its first field.
|
||||
Such an initializer must use braces. */
|
||||
|
||||
if (code == UNION_TYPE)
|
||||
{
|
||||
tree result, field = TYPE_FIELDS (type);
|
||||
|
||||
/* Find the first named field. ANSI decided in September 1990
|
||||
that only named fields count here. */
|
||||
while (field && DECL_NAME (field) == 0)
|
||||
field = TREE_CHAIN (field);
|
||||
|
||||
if (field == 0)
|
||||
{
|
||||
error ("union with no named members cannot be initialized");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (raw_constructor && !TYPE_NEEDS_CONSTRUCTING (type))
|
||||
{
|
||||
result = process_init_constructor (type, init, NULL_PTR);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (! raw_constructor)
|
||||
{
|
||||
error ("type mismatch in initialization");
|
||||
return error_mark_node;
|
||||
}
|
||||
if (element == 0)
|
||||
{
|
||||
if (!TYPE_NEEDS_CONSTRUCTING (type))
|
||||
{
|
||||
error ("union initializer requires one element");
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Take just the first element from within the constructor
|
||||
and it should match the type of the first element. */
|
||||
element = digest_init (TREE_TYPE (field), element, (tree *) 0);
|
||||
result = build (CONSTRUCTOR, type, 0, build_tree_list (field, element));
|
||||
TREE_CONSTANT (result) = TREE_CONSTANT (element);
|
||||
TREE_STATIC (result) = (initializer_constant_valid_p (element)
|
||||
&& TREE_CONSTANT (element));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialization of an array of chars from a string constant
|
||||
optionally enclosed in braces. */
|
||||
|
||||
|
@ -834,7 +784,8 @@ digest_init (type, init, tail)
|
|||
|
||||
if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
|
||||
{
|
||||
error ("variable-sized object may not be initialized");
|
||||
cp_error ("variable-sized object of type `%T' may not be initialized",
|
||||
type);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
|
@ -1097,6 +1048,12 @@ process_init_constructor (type, init, elts)
|
|||
if (!win)
|
||||
TREE_VALUE (tail) = error_mark_node;
|
||||
}
|
||||
else if (field == 0)
|
||||
{
|
||||
cp_error ("union `%T' with no named members cannot be initialized",
|
||||
type);
|
||||
TREE_VALUE (tail) = error_mark_node;
|
||||
}
|
||||
|
||||
if (TREE_VALUE (tail) != 0)
|
||||
{
|
||||
|
@ -1105,7 +1062,7 @@ process_init_constructor (type, init, elts)
|
|||
next1 = digest_init (TREE_TYPE (field),
|
||||
TREE_VALUE (tail), &tail1);
|
||||
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
|
||||
abort ();
|
||||
my_friendly_abort (357);
|
||||
tail = tail1;
|
||||
}
|
||||
else
|
||||
|
@ -1129,7 +1086,7 @@ process_init_constructor (type, init, elts)
|
|||
/* If arguments were specified as a constructor,
|
||||
complain unless we used all the elements of the constructor. */
|
||||
else if (tail)
|
||||
warning ("excess elements in aggregate initializer");
|
||||
pedwarn ("excess elements in aggregate initializer");
|
||||
|
||||
if (erroneous)
|
||||
return error_mark_node;
|
||||
|
|
Loading…
Reference in New Issue