diff options
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 128 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/tree.c | 22 |
5 files changed, 122 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 04ee628..8fe890e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2000-01-17 Mark Mitchell <mark@codesourcery.com> + * cp-tree.h (build_shared_int_cst): New function. + * call.c (build_over_call): Use DECL_VIRTUAL_CONTEXT, for clarity. + * class.c (modify_vtable_entry): Likewise. + (add_virtual_function): Split out code to generated shared + INTEGER_CSTs to build_share_int_cst. + (modify_all_vtables): Handle all the overridden functions here. + Add overridden functions from non-primary virtual bases to the + primary vtable. + (finish_struct_1): Adjust call to modify_all_vtables. Add + overridden functions from non-primary bases to the vtable. + * tree.c (build_shared_int_cst): New function. + * cp-tree.h (scratchalloc): Remove. (build_scratch_list): Likewise. * call.c (convert_class_to_reference): Replace build_scratch_list diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7114d02..f526abf 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4126,7 +4126,7 @@ build_over_call (cand, args, flags) { tree t, *p = &TREE_VALUE (converted_args); tree binfo = get_binfo - (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); + (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); *p = convert_pointer_to_real (binfo, *p); if (TREE_SIDE_EFFECTS (*p)) *p = save_expr (*p); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 6d221eb..5539176 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -103,7 +103,7 @@ static tree dfs_get_class_offset PROTO((tree, void *)); static tree get_class_offset PROTO((tree, tree, tree, tree)); static void modify_one_vtable PROTO((tree, tree, tree)); static tree dfs_modify_vtables PROTO((tree, void *)); -static void modify_all_vtables PROTO((tree, tree)); +static tree modify_all_vtables PROTO((tree, int *, tree)); static void determine_primary_base PROTO((tree, int *)); static void finish_struct_methods PROTO((tree)); static void maybe_warn_about_overly_private_class PROTO ((tree)); @@ -1107,7 +1107,7 @@ modify_vtable_entry (old_entry_in_list, new_offset, fndecl) if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) { DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); - DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl); + DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl); } } @@ -1166,8 +1166,6 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p, tree fndecl; tree t; /* Structure type. */ { - my_friendly_assert (DECL_CONTEXT (fndecl) == t, 20000116); - /* If this function doesn't override anything from a base class, we can just assign it a new DECL_VINDEX now. Otherwise, if it does override something, we keep it around and assign its DECL_VINDEX @@ -1185,25 +1183,10 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p, start_vtable (t, has_virtual); - /* Build a new INT_CST for this DECL_VINDEX. */ - { - static tree index_table[256]; - tree idx; - /* We skip a slot for the offset/tdesc entry. */ - int i = (*has_virtual)++; - - if (i >= 256 || index_table[i] == 0) - { - idx = build_int_2 (i, 0); - if (i < 256) - index_table[i] = idx; - } - else - idx = index_table[i]; + /* Now assign virtual dispatch information. */ + DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++); + DECL_VIRTUAL_CONTEXT (fndecl) = t; - /* Now assign virtual dispatch information. */ - DECL_VINDEX (fndecl) = idx; - } /* Save the state we've computed on the NEW_VIRTUALS list. */ *new_virtuals_p = tree_cons (integer_zero_node, fndecl, @@ -2752,17 +2735,81 @@ dfs_modify_vtables (binfo, data) return NULL_TREE; } -static void -modify_all_vtables (t, fndecl) +/* Update all of the primary and secondary vtables for T. Create new + vtables as required, and initialize their RTTI information. Each + of the functions in OVERRIDDEN_VIRTUALS overrides a virtual + function from a base class; find and modify the appropriate entries + to point to the overriding functions. Returns a list, in + declaration order, of the functions that are overridden in this + class, but do not appear in the primary base class vtable, and + which should therefore be appended to the end of the vtable for T. */ + +static tree +modify_all_vtables (t, has_virtual_p, overridden_virtuals) tree t; - tree fndecl; + int *has_virtual_p; + tree overridden_virtuals; { - tree list; + tree fns; + tree binfo; - list = build_tree_list (t, fndecl); - dfs_walk (TYPE_BINFO (t), dfs_modify_vtables, - dfs_unmarked_real_bases_queue_p, list); - dfs_walk (TYPE_BINFO (t), dfs_unmark, dfs_marked_real_bases_queue_p, t); + binfo = TYPE_BINFO (t); + + /* Even if there are no overridden virtuals, we want to go through + the hierarchy updating RTTI information. */ + if (!overridden_virtuals && TYPE_CONTAINS_VPTR_P (t) && flag_rtti) + overridden_virtuals = build_tree_list (NULL_TREE, NULL_TREE); + + /* Iterate through each of the overriding functions, updating the + base vtables. */ + for (fns = overridden_virtuals; fns; fns = TREE_CHAIN (fns)) + { + tree list; + list = build_tree_list (t, TREE_VALUE (fns)); + dfs_walk (binfo, dfs_modify_vtables, + dfs_unmarked_real_bases_queue_p, list); + dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t); + } + + /* If we should include overriding functions for secondary vtables + in our primary vtable, add them now. */ + if (all_overridden_vfuns_in_vtables_p ()) + { + tree *fnsp = &overridden_virtuals; + + while (*fnsp) + { + tree fn = TREE_VALUE (*fnsp); + + if (BINFO_VIRTUALS (binfo) + && !value_member (fn, BINFO_VIRTUALS (binfo))) + { + /* We know we need a vtable for this class now. */ + start_vtable (t, has_virtual_p); + /* Set the vtable index. */ + DECL_VINDEX (fn) + = build_shared_int_cst ((*has_virtual_p)++); + /* We don't need to convert to a base class when calling + this function. */ + DECL_VIRTUAL_CONTEXT (fn) = t; + /* We don't need to adjust the `this' pointer when + calling this function. */ + TREE_PURPOSE (*fnsp) = integer_zero_node; + + /* This is an overridden function not already in our + vtable. Keep it. */ + fnsp = &TREE_CHAIN (*fnsp); + } + else + /* We've already got an entry for this function. Skip + it. */ + *fnsp = TREE_CHAIN (*fnsp); + } + } + else + overridden_virtuals = NULL_TREE; + + return overridden_virtuals; } /* Fixup all the delta entries in this one vtable that need updating. */ @@ -4818,22 +4865,15 @@ finish_struct_1 (t) TYPE_VFIELD (t) = vfield; } - if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !overridden_virtuals) - modify_all_vtables (t, NULL_TREE); + overridden_virtuals + = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals)); - for (overridden_virtuals = nreverse (overridden_virtuals); - overridden_virtuals; - overridden_virtuals = TREE_CHAIN (overridden_virtuals)) - modify_all_vtables (t, TREE_VALUE (overridden_virtuals)); - if (TYPE_USES_VIRTUAL_BASECLASSES (t)) { tree vbases; /* Now fixup any virtual function entries from virtual bases that have different deltas. This has to come after we do the - pending hard virtuals, as we might have a function that comes - from multiple virtual base instances that is only overridden - by a hard virtual above. */ + overridden virtuals. */ vbases = CLASSTYPE_VBASECLASSES (t); while (vbases) { @@ -4851,6 +4891,7 @@ finish_struct_1 (t) /* If necessary, create the vtable for this class. */ if (new_virtuals + || overridden_virtuals || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())) { new_virtuals = nreverse (new_virtuals); @@ -4859,7 +4900,8 @@ finish_struct_1 (t) { if (! CLASSTYPE_COM_INTERFACE (t)) { - /* The second slot is for the tdesc pointer when thunks are used. */ + /* The second slot is for the tdesc pointer when thunks + are used. */ if (flag_vtable_thunks) new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals); @@ -4918,6 +4960,10 @@ finish_struct_1 (t) followed by entries for new functions unique to this class. */ TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), new_virtuals); + /* Finally, add entries for functions that override virtuals + from non-primary bases. */ + TYPE_BINFO_VIRTUALS (t) + = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals); } /* Now lay out the virtual function table. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 366181d..e0e2948 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4199,6 +4199,7 @@ extern tree cp_build_qualified_type_real PROTO((tree, int, int)); extern void remap_save_expr PROTO((tree *, splay_tree, tree, int *)); #define cp_build_qualified_type(TYPE, QUALS) \ cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1) +extern tree build_shared_int_cst PROTO((int)); /* in typeck.c */ extern int string_conv_p PROTO((tree, tree, int)); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 3c342d5..3bf874a 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1,5 +1,5 @@ /* Language-dependent node constructors for parse phase of GNU compiler. - Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92-98, 1999, 2000 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -1710,6 +1710,26 @@ build_min VPROTO((enum tree_code code, tree tt, ...)) return t; } +/* Returns an INTEGER_CST (of type `int') corresponding to I. + Multiple calls with the same value of I may or may not yield the + same node; therefore, callers should never modify the node + returned. */ + +tree +build_shared_int_cst (i) + int i; +{ + static tree cache[256]; + + if (i >= 256) + return build_int_2 (i, 0); + + if (!cache[i]) + cache[i] = build_int_2 (i, 0); + + return cache[i]; +} + tree get_type_decl (t) tree t; |