33rd Cygnus<->FSF merge

From-SVN: r7134
This commit is contained in:
Mike Stump 1994-04-21 23:30:18 +00:00
parent 0207efa210
commit 7177d104dd
18 changed files with 3544 additions and 1334 deletions

2846
gcc/cp/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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
{

View File

@ -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)

View File

@ -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];

View File

@ -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 '}'
{

View File

@ -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

View File

@ -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 ()
{

View File

@ -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:

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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;