summaryrefslogtreecommitdiffstats
path: root/contrib/gcc
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2000-05-27 02:25:28 +0000
committerobrien <obrien@FreeBSD.org>2000-05-27 02:25:28 +0000
commit2213994dde95f9976af97c2acabf8054049ba10a (patch)
tree09cae866f233ee92af84c7755922738bde568ea5 /contrib/gcc
parentea11d3cf1c7ee988db5b61368d225c6f4f943335 (diff)
parent890b30850f08010e6461f2af573cb7b53a82ef36 (diff)
downloadFreeBSD-src-2213994dde95f9976af97c2acabf8054049ba10a.zip
FreeBSD-src-2213994dde95f9976af97c2acabf8054049ba10a.tar.gz
This commit was generated by cvs2svn to compensate for changes in r60967,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/gcc')
-rw-r--r--contrib/gcc/ChangeLog57
-rw-r--r--contrib/gcc/c-typeck.c7
-rw-r--r--contrib/gcc/config/alpha/linux-elf.h2
-rw-r--r--contrib/gcc/config/elfos.h5
-rw-r--r--contrib/gcc/config/linux.h2
-rw-r--r--contrib/gcc/config/sparc/linux.h2
-rw-r--r--contrib/gcc/cp/ChangeLog114
-rw-r--r--contrib/gcc/cp/call.c51
-rw-r--r--contrib/gcc/cp/class.c354
-rw-r--r--contrib/gcc/cp/cp-tree.h72
-rw-r--r--contrib/gcc/cp/decl2.c95
-rw-r--r--contrib/gcc/cp/exception.cc4
-rw-r--r--contrib/gcc/cp/init.c234
-rw-r--r--contrib/gcc/cp/method.c221
-rw-r--r--contrib/gcc/cp/pt.c38
-rw-r--r--contrib/gcc/cp/rtti.c25
-rw-r--r--contrib/gcc/cp/search.c120
-rw-r--r--contrib/gcc/unroll.c12
18 files changed, 1339 insertions, 76 deletions
diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog
index f1364d1..61272bd 100644
--- a/contrib/gcc/ChangeLog
+++ b/contrib/gcc/ChangeLog
@@ -1,3 +1,60 @@
+Fri May 26 10:30:02 2000 Richard Earnshaw (rearnsha@arm.com)
+
+ * arm.md (negdi2): Add clobber of condition code register.
+
+Wed May 24 00:25:45 2000 Alexandre Oliva <oliva@lsd.ic.unicamp.br>
+
+ 2000-05-22 Richard Henderson <rth@cygnus.com>
+ * function.c (thread_prologue_and_epilogue_insns): Make sure
+ existing line number notes appear after the prologue.
+
+2000-05-16 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * sysv4.h (CPP_OS_LINUX_SPEC): Define __unix and __linux according
+ to given options.
+
+2000-05-14 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * rs6000/rs6000.md (nonlocal_goto_receiver): Add length attribute.
+
+Wed Apr 12 00:42:19 2000 Jeffrey A Law (law@cygnus.com)
+
+ 2000-02-19 Richard Henderson <rth@cygnus.com>
+ * c-typeck.c (add_pending_init): Don't abort for multiple
+ fields at the same offset.
+ (pending_init_member): Test the correct member.
+
+ Wed Apr 12 00:44:31 2000 Jeffrey A Law (law@cygnus.com)
+ * config/i386/freebsd-elf.h (DEFAULT_VTABLE_THUNKS): Changed to 2.
+
+ Tue Nov 9 17:14:40 1999 H.J. Lu <hjl@gnu.org>
+ * invoke.texi (-fvtable-thunks): Document that Linux/GNU uses
+ version 2 as default.
+
+ Tue Nov 9 10:16:55 1999 H.J. Lu <hjl@gnu.org>
+ * alpha/linux-elf.h (DEFAULT_VTABLE_THUNKS): Changed to 2.
+ * arm/linux-elf.h: Likewise.
+ * rs6000/linux.h: Likewise.
+ * sparc/linux.h: Likewise.
+
+ Mon Nov 8 14:41:34 1999 H.J. Lu <hjl@gnu.org>
+ * config/linux.h (DEFAULT_VTABLE_THUNKS): Changed to 2.
+
+ Sun May 2 08:49:27 1999 Martin von Löwis <loewis@informatik.hu-berlin.de>
+ * invoke.texi (-fvtable-thunks): Document numeric argument.
+
+2000-04-11 Alexandre Oliva <oliva@lsd.ic.unicamp.br>
+
+ * config/elfos.h (SELECT_SECTION): Decide whether to use a data or
+ const section to output a CONSTRUCTOR based on the same conditions
+ used for VAR_DECLs.
+
+Mon Apr 3 02:31:32 2000 Jeffrey A Law (law@cygnus.com)
+
+ 2000-01-20 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+ * unroll.c (loop_iterations): Don't abort if REG_USERVAR_P set
+ on iteration_var.
+
Wed Mar 22 13:11:54 2000 David Edelsohn <edelsohn@gnu.org>
* rs6000.c (reg_or_u_cint_operand): New function.
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c
index 154d830..d320307 100644
--- a/contrib/gcc/c-typeck.c
+++ b/contrib/gcc/c-typeck.c
@@ -5846,7 +5846,7 @@ add_pending_init (purpose, value)
p = *q;
if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left;
- else if (tree_int_cst_lt (p->purpose, purpose))
+ else if (p->purpose != purpose)
q = &p->right;
else
abort ();
@@ -5860,8 +5860,7 @@ add_pending_init (purpose, value)
if (tree_int_cst_lt (DECL_FIELD_BITPOS (purpose),
DECL_FIELD_BITPOS (p->purpose)))
q = &p->left;
- else if (tree_int_cst_lt (DECL_FIELD_BITPOS (p->purpose),
- DECL_FIELD_BITPOS (purpose)))
+ else if (p->purpose != purpose)
q = &p->right;
else
abort ();
@@ -6046,7 +6045,7 @@ pending_init_member (field)
{
while (p)
{
- if (tree_int_cst_equal (field, p->purpose))
+ if (field == p->purpose)
return 1;
else if (tree_int_cst_lt (field, p->purpose))
p = p->left;
diff --git a/contrib/gcc/config/alpha/linux-elf.h b/contrib/gcc/config/alpha/linux-elf.h
index fc07127..50bf230 100644
--- a/contrib/gcc/config/alpha/linux-elf.h
+++ b/contrib/gcc/config/alpha/linux-elf.h
@@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */
#ifndef USE_GNULIBC_1
#undef DEFAULT_VTABLE_THUNKS
-#define DEFAULT_VTABLE_THUNKS 1
+#define DEFAULT_VTABLE_THUNKS 2
#endif
#ifndef USE_GNULIBC_1
diff --git a/contrib/gcc/config/elfos.h b/contrib/gcc/config/elfos.h
index 6c10731..d482615 100644
--- a/contrib/gcc/config/elfos.h
+++ b/contrib/gcc/config/elfos.h
@@ -1,6 +1,6 @@
/* elfos.h -- operating system specific defines to be used when
targeting GCC for some generic ELF system
- Copyright (C) 1991, 1994, 1995, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1995, 1999, 2000 Free Software Foundation, Inc.
Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com).
This file is part of GNU CC.
@@ -426,7 +426,8 @@ do { \
else \
data_section (); \
} \
- else if (TREE_CODE (DECL) == VAR_DECL) \
+ else if (TREE_CODE (DECL) == VAR_DECL \
+ || TREE_CODE (DECL) == CONSTRUCTOR) \
{ \
if ((flag_pic && RELOC) \
|| !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
diff --git a/contrib/gcc/config/linux.h b/contrib/gcc/config/linux.h
index b619d01..46ce898 100644
--- a/contrib/gcc/config/linux.h
+++ b/contrib/gcc/config/linux.h
@@ -89,7 +89,7 @@ Boston, MA 02111-1307, USA. */
#ifndef USE_GNULIBC_1
#undef DEFAULT_VTABLE_THUNKS
-#define DEFAULT_VTABLE_THUNKS 1
+#define DEFAULT_VTABLE_THUNKS 2
#endif
#undef LIB_SPEC
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index d967b01..4069490 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */
#ifndef USE_GNULIBC_1
#undef DEFAULT_VTABLE_THUNKS
-#define DEFAULT_VTABLE_THUNKS 1
+#define DEFAULT_VTABLE_THUNKS 2
#endif
/* Use stabs instead of DWARF debug format. */
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 309d8e2..3f00533 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,3 +1,117 @@
+2000-03-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * exception.cc (__cp_pop_exception): Cleanup the original object.
+
+1999-11-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * rtti.c (get_tinfo_fn_unused): Split out from get_tinfo_fn.
+ * class.c (set_rtti_entry): Use it.
+
+Wed Apr 12 00:45:49 2000 Jeffrey A Law (law@cygnus.com)
+
+ 2000-02-03 <loewis@informatik.hu-berlin.de>
+ * call.c (add_function_candidate): Do not add vlist ctor into
+ candidates in compatibility mode.
+ (build_user_type_conversion_1): Add LOOKUP_HAS_VLIST when adding
+ vlist.
+ (convert_like): Likewise.
+ (build_over_call): Skip vlist only if it is mentioned in flags.
+ (build_new_method_call): Do not add vlist in compatibility mode,
+ except for dtors.
+ * cp-tree.h (flag_vtable_thunks): Has now four possible values.
+ (DECL_VLIST_CTOR_WRAPPER_P, DECL_VLIST_CTOR_WRAPPED): New macros.
+ (in_charge_identifier): Declare external.
+ * decl.c (xref_basetypes): Check for vtable_thunks >=2.
+ (finish_dtor): Use bit 2 of in_chrg.
+ (finish_function): Do not finish vlist ctor wrappers.
+ * decl2.c (flag_vtable_thunks_compat): New variable.
+ (lang_decode_option): Set it accordingly.
+ (maybe_retrofit_in_chrg): Call make_vlist_ctor_wrapper.
+ * init.c (build_base_dtor_call): Pass 4 in in_chrg.
+ (no_vlist_base_init): New function.
+ (expand_default_init): Do not pass vlist in compatibility mode.
+ Try to call old base ctor if new one was not generated.
+ (build_new_1): Do not pass vlist in compatibility mode.
+ * method.c (get_id_2): Do not put _Vlist into dtor name in
+ compatibility mode.
+ (make_vlist_ctor_wrapper, emit_vlist_ctor_wrapper): New functions.
+ (synthesize_method): Call emit_vlist_ctor_wrapper.
+ * pt.c (instantiate_class_template): Check for vtable_thunks >=2.
+
+ Sat Nov 13 15:48:59 1999 H.J. Lu <hjl@gnu.org>
+ * init.c (finish_dtor): Call mark_all_temps_used () before
+ declaring vlist.
+
+ Tue Nov 9 15:01:57 1999 H.J. Lu <hjl@gnu.org>
+ * init.c (construct_virtual_bases): Update.
+ (expand_cleanup_for_base): Update.
+
+ Tue Nov 9 08:25:04 1999 H.J. Lu <hjl@gnu.org>
+ * init.c (construct_virtual_bases): Update.
+ (expand_cleanup_for_base): Take vlist parameter.
+ (emit_base_init): Pass vlist to expand_cleanup_for_base.
+ (construct_virtual_bases): Likewise.
+
+ 1999-05-02 Martin von Löwis <loewis@informatik.hu-berlin.de>
+ * class.c (prepare_ctor_vtable, finish_one_ctor_vtable,
+ prepend_ctor_vfields_for_vbase, finish_ctor_vtables_for_vbases,
+ finish_ctor_vtables_1, prepend_vbase_vfields,
+ finish_ctor_vtables): New functions.
+ (finish_struct_1): Call finish_ctor_vtables.
+ * cp-tree.h (TYPE_USES_PVBASES): New macro.
+ (constructor_for_vbase_attr): Widen to two bits.
+ (CONSTRUCTOR_FOR_VBASE, CONSTRUCTOR_FOR_PVBASE,
+ DESTRUCTOR_FOR_PVBASE): New macros.
+ (DECL_CONSTRUCTOR_FOR_VBASE_P): Adopt to new enumeration.
+ (DECL_CONSTRUCTOR_FOR_VBASE): New macro.
+ (DECL_CONSTRUCTOR_FOR_PVBASE_P, DECL_DESTRUCTOR_FOR_PVBASE_P): New
+ macros.
+ (vlist_identifier, vlist_type_node, vlist_zero_node): Declare.
+ (VCTABLE_NAME, VLIST_NAME_FORMAT, VLIST_NAME, VLIST1_NAME,
+ VLIST_TYPE_NAME): New macros.
+ (LOOKUP_HAS_VLIST): New macro.
+ (build_base_dtor_call, init_vlist): Declare.
+ (build_destructor_name): Add int argument.
+ * decl.c (vlist_identifier, vlist_type_node, vlist_zero_node):
+ Define.
+ (init_decl_processing): Initialize them.
+ (grokdeclarator): Handle vlist argument.
+ (copy_args_p): Likewise.
+ (grok_ctor_properties): Don't try to skip initial int for
+ templates. Skip vlist if available.
+ (xref_basetypes): Set TYPE_USES_PVBASES.
+ (finish_dtor, finish_ctor): New functions, moved out of ...
+ (finish_function): ... here.
+ * decl2.c (lang_decode_option): Set flag_vtable_thunks explicitly.
+ (maybe_retrofit_in_chrg): Retrofit __vlist parameter.
+ (grokclassfn): Pass pvbase flag into mangled name.
+ * init.c (build_base_dtor_call): New function.
+ (build_partial_cleanup_for): Call it.
+ (pvbasecount, init_vlist, ): New functions.
+ (emit_base_init): Process vlist argument.
+ (expand_aggr_vbase_init_1): Likewise.
+ (expand_aggr_vbase_init): Likewise.
+ (expand_default_init): Likewise.
+ (build_new_1): Pass null vlist argument.
+ (build_delete): Likewise. Call build_base_dtor_call.
+ * method.c (process_overload_item): Mangle _Vlist specially.
+ (build_base_path, get_vlist_vtable_id): New functions.
+ (build_destructor_name): Potentially mangle _Vlist into it.
+ (do_build_copy_constructor): Skip vlist argument.
+ (synthesize_method): Likewise.
+ * pt.c (has_pvbases_p): New function.
+ (instantiate_class_template): Call it.
+ (tsubst_decl): Retrofit before mangling. Pass pvbase_p to
+ destructor mangling.
+ * search.c (expand_direct_vtbls_init_thunks): New function.
+ (expand_indirect_vtbls_init_thunks): New function.
+ (expand_indirect_vtbls_init): Call it.
+ * call.c (add_function_candidate): Process vlist argument.
+ (build_user_type_conversion_1): Add vlist argument.
+ (convert_like): Likewise.
+ (build_over_call): Likewise.
+ (build_new_method_call): Likewise.
+
2000-02-18 Martin von Loewis <loewis@informatik.hu-berlin.de>
* typeck2.c (my_friendly_abort): Use GCCBUGURL.
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index 094a345..a931500 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1065,8 +1065,8 @@ add_function_candidate (candidates, fn, arglist, flags)
tree parmnode, argnode;
int viable = 1;
- /* The `this' and `in_chrg' arguments to constructors are not considered
- in overload resolution. */
+ /* The `this', `in_chrg', and `vlist' arguments to constructors are
+ not considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
{
parmlist = TREE_CHAIN (parmlist);
@@ -1076,6 +1076,22 @@ add_function_candidate (candidates, fn, arglist, flags)
parmlist = TREE_CHAIN (parmlist);
arglist = TREE_CHAIN (arglist);
}
+ if ((flags & LOOKUP_HAS_VLIST)
+ && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn))
+ {
+ parmlist = TREE_CHAIN (parmlist);
+ arglist = TREE_CHAIN (arglist);
+ }
+ else if (!(flags & LOOKUP_HAS_VLIST)
+ && !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn))
+ /* Ok */;
+ else
+ {
+ /* The ctor expects a vlist and the arguments don't have
+ one, or vice versa, so fn is not even a candidate, since
+ the corresponding ctor would be the candidate. */
+ return candidates;
+ }
}
len = list_length (arglist);
@@ -2071,6 +2087,11 @@ build_user_type_conversion_1 (totype, expr, flags)
tree t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
args = build_scratch_list (NULL_TREE, expr);
+ if (TYPE_USES_PVBASES (totype) && !flag_vtable_thunks_compat)
+ {
+ args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args);
+ flags |= LOOKUP_HAS_VLIST;
+ }
if (TYPE_USES_VIRTUAL_BASECLASSES (totype))
args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
args = scratch_tree_cons (NULL_TREE, t, args);
@@ -3038,6 +3059,7 @@ convert_like (convs, expr)
= WRAPPER_PTR (TREE_OPERAND (convs, 1));
tree fn = cand->fn;
tree args;
+ int flags = LOOKUP_NORMAL;
if (DECL_CONSTRUCTOR_P (fn))
{
@@ -3045,13 +3067,19 @@ convert_like (convs, expr)
TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
args = build_scratch_list (NULL_TREE, expr);
+ if (TYPE_USES_PVBASES (DECL_CONTEXT (fn))
+ && !flag_vtable_thunks_compat)
+ {
+ args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args);
+ flags != LOOKUP_HAS_VLIST;
+ }
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
args = scratch_tree_cons (NULL_TREE, t, args);
}
else
args = build_this (expr);
- expr = build_over_call (cand, args, LOOKUP_NORMAL);
+ expr = build_over_call (cand, args, flags);
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
@@ -3260,6 +3288,13 @@ build_over_call (cand, args, flags)
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
}
+ if (flags & LOOKUP_HAS_VLIST)
+ {
+ converted_args = expr_tree_cons
+ (NULL_TREE, TREE_VALUE (arg), converted_args);
+ arg = TREE_CHAIN (arg);
+ parm = TREE_CHAIN (parm);
+ }
}
/* Bypass access control for 'this' parameter. */
else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
@@ -3369,6 +3404,8 @@ build_over_call (cand, args, flags)
arg = TREE_CHAIN (converted_args);
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
arg = TREE_CHAIN (arg);
+ if (flags & LOOKUP_HAS_VLIST)
+ arg = TREE_CHAIN (arg);
arg = TREE_VALUE (arg);
/* Pull out the real argument, disregarding const-correctness. */
@@ -3544,6 +3581,8 @@ build_new_method_call (instance, name, args, basetype_path, flags)
remove it for error reporting. */
if (flags & LOOKUP_HAS_IN_CHARGE)
user_args = TREE_CHAIN (args);
+ if (flags & LOOKUP_HAS_VLIST)
+ user_args = TREE_CHAIN (user_args);
args = resolve_args (args);
@@ -3616,6 +3655,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
&& ! (flags & LOOKUP_HAS_IN_CHARGE))
{
+ if (TYPE_USES_PVBASES(basetype)
+ && (!flag_vtable_thunks_compat || (name == dtor_identifier)))
+ {
+ args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args);
+ flags |= LOOKUP_HAS_VLIST;
+ }
flags |= LOOKUP_HAS_IN_CHARGE;
args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
}
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 400c67d..74808c5 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -102,8 +102,15 @@ static tree get_basefndecls PROTO((tree, tree));
static void set_rtti_entry PROTO((tree, tree, tree));
static tree build_vtable PROTO((tree, tree));
static void prepare_fresh_vtable PROTO((tree, tree));
+static tree prepare_ctor_vtable PROTO((tree, tree, tree));
static void fixup_vtable_deltas1 PROTO((tree, tree));
static void fixup_vtable_deltas PROTO((tree, int, tree));
+static tree finish_one_ctor_vtable PROTO((tree, tree, tree, tree));
+static tree prepend_ctor_vfields_for_vbase PROTO((tree, tree, tree, tree, int, tree));
+static tree finish_ctor_vtables_for_vbases PROTO((tree, tree, tree));
+static tree finish_ctor_vtables_1 PROTO((tree, tree));
+static tree prepend_vbase_vfields PROTO((tree, int, tree));
+static void finish_ctor_vtables PROTO((tree));
static void finish_vtbls PROTO((tree, int, tree));
static void modify_vtable_entry PROTO((tree, tree, tree));
static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT));
@@ -673,7 +680,7 @@ set_rtti_entry (virtuals, offset, type)
return;
if (flag_rtti)
- vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
+ vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn_unused (type));
else
vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);
TREE_CONSTANT (vfn) = 1;
@@ -922,6 +929,43 @@ prepare_fresh_vtable (binfo, for_type)
SET_BINFO_NEW_VTABLE_MARKED (binfo);
}
+/* Return a new vtable for use in initialization of the BASE subobject
+ of COMPLETE_TYPE. The vtable there goes into the vfield of the
+ VBASEBASE virtual subobject. */
+
+static tree
+prepare_ctor_vtable (complete_type, base, vbasebase)
+ tree complete_type, base, vbasebase;
+{
+ tree orig_decl = BINFO_VTABLE (vbasebase);
+ tree name = get_vlist_vtable_id (base, vbasebase);
+ tree new_decl;
+
+ new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
+ /* Remember which class this vtable is really for. */
+ DECL_CONTEXT (new_decl) = complete_type;
+
+ DECL_ARTIFICIAL (new_decl) = 1;
+ TREE_STATIC (new_decl) = 1;
+ new_decl = pushdecl_top_level (new_decl);
+ DECL_VIRTUAL_P (new_decl) = 1;
+#ifndef WRITABLE_VTABLES
+ /* Make them READONLY by default. (mrs) */
+ TREE_READONLY (new_decl) = 1;
+#endif
+ DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
+
+#ifdef GATHER_STATISTICS
+ n_vtables += 1;
+ n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
+#endif
+
+ /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
+ import_export_vtable (new_decl, complete_type, 0);
+
+ return new_decl;
+}
+
#if 0
/* Access the virtual function table entry that logically
contains BASE_FNDECL. VIRTUALS is the virtual function table's
@@ -1798,6 +1842,7 @@ finish_struct_bits (t, max_has_virtual)
TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t);
TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t);
TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);
+ TYPE_USES_PVBASES (variants) = TYPE_USES_PVBASES (t);
/* Copy whatever these are holding today. */
TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
@@ -2933,6 +2978,309 @@ warn_hidden (t)
}
}
+/* Generate one vtable for use in constructors or destructors of BASE
+ subobjects of COMPLETE_TYPE objects. The vtable belongs to the
+ vfield of the VBASEVASE subobject of the VBASE virtual base of
+ COMPLETE_TYPE (and BASE). */
+
+static tree
+finish_one_ctor_vtable (complete_type, base, vbase, vbasebase)
+ tree complete_type, base, vbase, vbasebase;
+{
+ tree virtuals;
+ tree newtable;
+ tree newvirtuals;
+ tree offset;
+ tree newvbase = binfo_member (BINFO_TYPE (vbase),
+ CLASSTYPE_VBASECLASSES (complete_type));
+
+ newtable = prepare_ctor_vtable (complete_type, base, vbasebase);
+ newvirtuals = copy_list (BINFO_VIRTUALS (vbasebase));
+
+ virtuals = newvirtuals;
+ /* Change the offset entry. First, delta between base an vbase. */
+ offset = ssize_binop (MINUS_EXPR, BINFO_OFFSET (newvbase),
+ BINFO_OFFSET (base));
+ /* Add delta between vbase and vbasebase. */
+ offset = ssize_binop (PLUS_EXPR, offset, BINFO_OFFSET (vbasebase));
+ offset = ssize_binop (MINUS_EXPR, offset, BINFO_OFFSET (vbase));
+ /* Finally, negate. */
+ offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);
+ offset = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (offset) = 1;
+ TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, offset);
+ virtuals = TREE_CHAIN (virtuals);
+
+ /* Skip the typeinfo function. */
+ virtuals = TREE_CHAIN (virtuals);
+
+ /* Iterate over all methods of this virtual base. */
+ for (; virtuals; virtuals = TREE_CHAIN (virtuals))
+ {
+ tree fndecl = TREE_VALUE (virtuals);
+ tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl);
+ fndecl = TREE_OPERAND (pfn, 0);
+ if (fndecl)
+ {
+ tree delta, newdelta, binfo_context;
+ tree context = DECL_CLASS_CONTEXT (fndecl);
+
+ /* If this method is implemented in a base of the vbase, the
+ thunk we have is correct. */
+ if (DERIVED_FROM_P (context, vbase))
+ continue;
+
+ binfo_context = binfo_value (context, base);
+ if (TREE_VIA_VIRTUAL (binfo_context))
+ binfo_context = binfo_member
+ (context, CLASSTYPE_VBASECLASSES (complete_type));
+ /* This is the delta from a complete C to a B subobject, or
+ more generally to the base subobject that implements the
+ virtual function for B. BASE already has the offset to
+ the complete type. */
+ delta = BINFO_OFFSET (binfo_context);
+ /* This is the delta from the A to the complete C. */
+ newdelta = BINFO_OFFSET (newvbase);
+ /* This is the delta from the A to the B subobject. */
+ newdelta = size_binop (MINUS_EXPR, newdelta, delta);
+ newdelta = ssize_binop (MINUS_EXPR, integer_zero_node,
+ newdelta);
+
+ modify_vtable_entry (virtuals,
+ build_vtable_entry (newdelta, pfn),
+ fndecl);
+ }
+ }
+ DECL_INITIAL (newtable) = build_nt (CONSTRUCTOR, NULL_TREE,
+ newvirtuals);
+ DECL_CONTEXT (newtable) = NULL_TREE;
+ cp_finish_decl (newtable, DECL_INITIAL (newtable), NULL_TREE, 0, 0);
+ DECL_CONTEXT (newtable) = complete_type;
+ return newtable;
+}
+
+/* Add all vtables into LIST for the VBASEBASE subobject and its bases
+ of VBASE virtual BASE of COMPLETE_TYPE for use in BASE
+ constructors. DO_SELF indicates whether this is the VBASEBASE that
+ has 'primary' vfield. Return the new LIST. */
+
+static tree
+prepend_ctor_vfields_for_vbase (complete_type, base, vbase, vbasebase,
+ do_self, list)
+ tree complete_type, base, vbase, vbasebase;
+ int do_self;
+ tree list;
+{
+ int i;
+ tree vtbl;
+ tree bases = BINFO_BASETYPES (vbasebase);
+ int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (vbasebase));
+
+ if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (vbasebase)))
+ {
+ vtbl = finish_one_ctor_vtable (complete_type, base, vbase, vbasebase);
+ vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
+ TREE_READONLY (vtbl) = 1;
+ TREE_CONSTANT (vtbl) = 1;
+ list = tree_cons (NULL_TREE, vtbl, list);
+ }
+
+ if (!bases)
+ return list;
+
+ for (i = 0; i < TREE_VEC_LENGTH (bases); i++)
+ {
+ tree vbasebase = TREE_VEC_ELT (bases, i);
+ if (TREE_VIA_VIRTUAL (vbasebase))
+ continue;
+ list = prepend_ctor_vfields_for_vbase
+ (complete_type, base, vbase, vbasebase, (i != vfp), list);
+ }
+
+ return list;
+}
+
+/* Iterate over all virtual bases of the BASE subobject of
+ COMPLETE_TYPE. This list is given in VBASES. Return the list of
+ vtables generated in the process. */
+
+static tree
+finish_ctor_vtables_for_vbases (vbases, base, complete_type)
+ tree vbases, base, complete_type;
+{
+ tree result = NULL_TREE;
+
+ for (; vbases; vbases = TREE_CHAIN (vbases))
+ result = prepend_ctor_vfields_for_vbase
+ (complete_type, base, vbases, vbases, 1, result);
+ return result;
+}
+
+/* Generate special vtables for virtual bases for use inside base
+ class ctors and dtors. Inside this function, we assume the
+ following scenario:
+ class A{virtual void foo();};
+ class B:virtual A{int member1;}
+ class C:B{int member2;}
+
+ BINFO is a base subject (e.g. B) of COMPLETE_TYPE. Returns the list
+ of virtual tables. */
+
+static tree
+finish_ctor_vtables_1 (binfo, complete_type)
+ tree binfo;
+ tree complete_type;
+{
+ int i;
+ tree binfos;
+ tree result = NULL_TREE;
+
+ binfos = BINFO_BASETYPES (binfo);
+ if (!binfos)
+ return result;
+
+ /* Iterate over all bases (i.e. B). */
+ for (i = 0; i < TREE_VEC_LENGTH (binfos); i++)
+ {
+ tree base = TREE_VEC_ELT (binfos, i);
+ tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (base));
+ if (!vbases)
+ /* This base class does not have virtual bases. */
+ continue;
+ if (TREE_VIA_VIRTUAL (base))
+ /* A virtual base class is initialized on in the most-derived
+ constructor. */
+ continue;
+ if (!TYPE_USES_PVBASES (BINFO_TYPE (base)))
+ /* Class has no polymorphic vbases. */
+ continue;
+ /* Prepend vtable list for base class. */
+ result = chainon (finish_ctor_vtables_1 (base, complete_type),
+ result);
+ /* Prepend our own vtable list. */
+ result = chainon
+ (finish_ctor_vtables_for_vbases (vbases, base, complete_type),
+ result);
+ }
+ return result;
+}
+
+/* Add the vtables of a virtual base BINFO in front of LIST, returning
+ the new list. DO_SELF indicates whether we have to return the
+ vtable of a vfield borrowed in a derived class. */
+
+static tree
+prepend_vbase_vfields (binfo, do_self, list)
+ tree binfo;
+ int do_self;
+ tree list;
+{
+ int i;
+ tree vtbl;
+ tree bases = BINFO_BASETYPES (binfo);
+ int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+
+ if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+ {
+ vtbl = BINFO_VTABLE (binfo);
+ vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
+ TREE_READONLY (vtbl) = 1;
+ TREE_CONSTANT (vtbl) = 1;
+ list = tree_cons (NULL_TREE, vtbl, list);
+ }
+
+ if (!bases)
+ return list;
+
+ for (i = 0; i < TREE_VEC_LENGTH (bases); i++)
+ {
+ tree base = TREE_VEC_ELT (bases, i);
+ if (TREE_VIA_VIRTUAL (base))
+ continue;
+ list = prepend_vbase_vfields (base, (i != vfp), list);
+ }
+
+ return list;
+}
+
+/* Wrapper around finish_ctor_vtables_1. Compute the vtable list for
+ type T. */
+
+static void
+finish_ctor_vtables (t)
+ tree t;
+{
+ tree veclist = NULL_TREE;
+ tree decl, type;
+ char *name;
+ tree vbase;
+ int len;
+
+ /* This is only good for vtable thunks. */
+ my_friendly_assert (flag_vtable_thunks, 990307);
+
+ /* Start with the list of most-derived vtables. */
+
+ for (vbase = CLASSTYPE_VBASECLASSES (t); vbase;
+ vbase = TREE_CHAIN (vbase))
+ veclist = prepend_vbase_vfields (vbase, 1, veclist);
+
+ /* Compute the list of vtables for the bases. */
+ veclist = chainon (veclist, finish_ctor_vtables_1 (TYPE_BINFO (t), t));
+
+ /* Finally, we initialize the virtual bases first. */
+ for (vbase = CLASSTYPE_VBASECLASSES (t); vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbase));
+ if (!vbases)
+ continue;
+ veclist = chainon (veclist,
+ finish_ctor_vtables_for_vbases (vbases, vbase, t));
+ veclist = chainon (veclist,
+ finish_ctor_vtables_1 (vbase, t));
+ }
+
+ veclist = nreverse (veclist);
+
+ /* Generate the name for the vtable list. */
+ name = alloca (strlen (VLIST_NAME_FORMAT)
+ + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2);
+ sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t));
+
+ /* Build the type of the list. */
+ len = list_length (veclist) - 1;
+ if (len < 0)
+ /* If this class has virtual bases without virtual methods, make a
+ single zero-entry in the array. This avoids zero-sized objects. */
+ len++;
+ type = build_cplus_array_type (vtbl_ptr_type_node,
+ build_index_type (size_int (len)));
+
+
+ /* Produce a new decl holding the list. */
+ decl = build_lang_decl (VAR_DECL, get_identifier (name), type);
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ decl = pushdecl_top_level (decl);
+ import_export_vtable (decl, t, 0);
+ DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, veclist);
+
+ DECL_ARTIFICIAL (decl) = 1;
+ /* This tells finish_file et.al. that this is related to virtual
+ tables. There is currently no way to distinguish between vtables
+ and vlists, other than the name of the decl. */
+ DECL_VIRTUAL_P (decl) = 1;
+
+ /* Output the array. */
+ cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
+
+ /* Set the class context after finishing, so that finish thinks this
+ is an unrelated global, and then finish_vtable_vardecl knows what
+ class this is related to. */
+ DECL_CONTEXT (decl) = t;
+}
+
/* Check for things that are invalid. There are probably plenty of other
things we should check for also. */
@@ -4069,6 +4417,10 @@ finish_struct_1 (t, warn_anon)
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (TYPE_BINFO (t), 1, t);
+ /* If we use thunks, and have virtual bases, we might need to emit
+ additional vtables. */
+ if (flag_vtable_thunks && TYPE_USES_PVBASES (t))
+ finish_ctor_vtables (t);
hack_incomplete_structures (t);
#if 0
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index 7180915..8c1e7df 100644
--- a/contrib/gcc/cp/cp-tree.h
+++ b/contrib/gcc/cp/cp-tree.h
@@ -52,7 +52,7 @@ Boston, MA 02111-1307, USA. */
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
- 5: Not used.
+ 5: TYPE_USES_PVBASES (in a class TYPE).
6: Not used.
Usage of TYPE_LANG_FLAG_?:
@@ -503,8 +503,9 @@ extern int write_virtuals;
/* True for more efficient but incompatible (not fully tested)
vtable implementation (using thunks).
- 0 is old behavior; 1 is new behavior. */
-extern int flag_vtable_thunks;
+ 0 is old behavior; 1 is new behavior; 3 adds vlist arguments;
+ 2 is 3 plus backwards-compatibility to 1. */
+extern int flag_vtable_thunks, flag_vtable_thunks_compat;
/* INTERFACE_ONLY nonzero means that we are in an "interface"
section of the compiler. INTERFACE_UNKNOWN nonzero means
@@ -889,6 +890,10 @@ struct lang_type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
+/* Nonzero means that this _CLASSTYPE uses polymorphic virtual bases.
+ This flag is set only when we use vtable thunks. */
+#define TYPE_USES_PVBASES(NODE) (TREE_LANG_FLAG_5(NODE))
+
/* Vector member functions defined in this class. Each element is
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
functions with the same name end up in the same slot. The first
@@ -965,7 +970,7 @@ struct lang_type
/* The number of virtual functions defined for this
_CLASSTYPE node. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
-/* The virtual base classes that this type uses. */
+/* The list of binfos of virtual base classes that this type uses. */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
/* The virtual function pointer fields that this type contains. */
#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
@@ -1165,22 +1170,21 @@ struct lang_decl_flags
unsigned static_function : 1;
unsigned const_memfunc : 1;
unsigned volatile_memfunc : 1;
-
unsigned abstract_virtual : 1;
unsigned permanent_attr : 1 ;
- unsigned constructor_for_vbase_attr : 1;
+
unsigned mutable_flag : 1;
unsigned is_default_implementation : 1;
unsigned saved_inline : 1;
unsigned use_template : 2;
-
unsigned nonconverting : 1;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned needs_final_overrider : 1;
unsigned bitfield : 1;
unsigned defined_in_class : 1;
- unsigned dummy : 4;
+ unsigned constructor_for_vbase_attr : 2;
+ unsigned dummy : 3;
tree access;
tree context;
@@ -1226,9 +1230,35 @@ struct lang_decl
#define DECL_CONV_FN_P(NODE) \
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE)))
-/* For FUNCTION_DECLs: nonzero means that this function is a constructor
+#define CONSTRUCTOR_FOR_VBASE 1
+#define CONSTRUCTOR_FOR_PVBASE 2
+#define DESTRUCTOR_FOR_PVBASE 3
+
+/* For FUNCTION_DECLs: nonzero means that this function is a con/destructor
for an object with virtual baseclasses. */
-#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
+#define DECL_CONSTRUCTOR_FOR_VBASE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
+
+/* Nonzero means that this function is a constructor for an object
+ with virtual baseclasses. */
+#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) \
+ (DECL_CONSTRUCTOR_FOR_VBASE (NODE) == CONSTRUCTOR_FOR_VBASE)
+
+/* Nonzero means that this function is a constructor for an object
+ with virtual baseclasses which have virtual functions. */
+#define DECL_CONSTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == CONSTRUCTOR_FOR_PVBASE)
+
+/* Nonzero means that this function is a destructor for an object
+ with virtual baseclasses which have virtual functions. */
+#define DECL_DESTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == DESTRUCTOR_FOR_PVBASE)
+
+/* Nonzero means that this function is a wrapper around a PVBASE ctor. */
+#define DECL_VLIST_CTOR_WRAPPER_P(NODE) \
+ (DECL_CONSTRUCTOR_FOR_VBASE_P (NODE) && DECL_VLIST_CTOR_WRAPPED (NODE)\
+ && TREE_CODE (DECL_VLIST_CTOR_WRAPPED (NODE)) == FUNCTION_DECL \
+ && DECL_CONSTRUCTOR_FOR_PVBASE_P (DECL_VLIST_CTOR_WRAPPED (NODE)))
+
+/* Refers to original function that NODE wraps. */
+#define DECL_VLIST_CTOR_WRAPPED(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
/* Non-zero for a FUNCTION_DECL that declares a type-info function. */
#define DECL_TINFO_FN_P(NODE) \
@@ -2168,6 +2198,7 @@ extern tree delta2_identifier;
extern tree pfn_or_delta2_identifier;
extern tree tag_identifier;
extern tree vt_off_identifier;
+extern tree in_charge_identifier;
/* A node that is a list (length 1) of error_mark_nodes. */
extern tree error_mark_list;
@@ -2177,6 +2208,8 @@ extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
extern tree unknown_type_node;
extern tree opaque_type_node, signature_type_node;
+extern tree vlist_identifier, vlist_type_node, vlist_zero_node;
+
/* Node for "pointer to (virtual) function".
This may be distinct from ptr_type_node so gdb can distinguish them. */
#define vfunc_ptr_type_node \
@@ -2292,6 +2325,8 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_FORMAT "_$tmp_%d"
#define VTABLE_BASE "$vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s")
+#define VCTABLE_NAME "__vc$"
+#define VLIST_NAME_FORMAT "__vl$%s"
#define VFIELD_BASE "$vf"
#define VFIELD_NAME "_vptr$"
#define VFIELD_NAME_FORMAT "_vptr$%s"
@@ -2314,6 +2349,8 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_FORMAT "_.tmp_%d"
#define VTABLE_BASE ".vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s")
+#define VCTABLE_NAME "__vc."
+#define VLIST_NAME_FORMAT "__vl.%s"
#define VFIELD_BASE ".vf"
#define VFIELD_NAME "_vptr."
#define VFIELD_NAME_FORMAT "_vptr.%s"
@@ -2346,6 +2383,8 @@ extern int current_function_parms_stored;
#define VTABLE_NAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \
sizeof (VTABLE_NAME) - 1))
+#define VCTABLE_NAME "__vc_"
+#define VLIST_NAME_FORMAT "__vl_%s"
#define VFIELD_BASE "__vfb"
#define VFIELD_NAME "__vptr_"
#define VFIELD_NAME_P(ID_NODE) \
@@ -2379,6 +2418,9 @@ extern int current_function_parms_stored;
#define DTOR_NAME "__dt"
#define IN_CHARGE_NAME "__in_chrg"
+#define VLIST_NAME "__vlist"
+#define VLIST1_NAME "__vlist1"
+#define VLIST_TYPE_NAME "6_Vlist"
#define VTBL_PTR_TYPE "__vtbl_ptr_type"
#define VTABLE_DELTA_NAME "__delta"
@@ -2556,6 +2598,8 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
as well as the space of member functions.
LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
in the parameter list.
+ LOOKUP_HAS_VLIST means that the "vlist" variable is already in
+ the parameter list.
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
DIRECT_BIND means that if a temporary is created, it should be created so
that it lives as long as the current variable bindings; otherwise it
@@ -2594,6 +2638,7 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
#define LOOKUP_PREFER_NAMESPACES (4096)
#define LOOKUP_PREFER_BOTH (6144)
#define LOOKUP_TEMPLATES_EXPECTED (8192)
+#define LOOKUP_HAS_VLIST (16384)
#define LOOKUP_NAMESPACES_ONLY(f) \
(((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES))
@@ -3051,6 +3096,8 @@ extern tree build_x_delete PROTO((tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
+extern tree build_base_dtor_call PROTO((tree, tree, tree));
+extern void init_vlist PROTO((tree));
/* in input.c */
@@ -3117,13 +3164,15 @@ extern tree build_decl_overload_real PROTO((tree, tree, tree, tree,
extern void set_mangled_name_for_decl PROTO((tree));
extern tree build_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree));
-extern tree build_destructor_name PROTO((tree));
+extern tree build_destructor_name PROTO((tree, int));
extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
extern tree hack_identifier PROTO((tree, tree));
extern tree make_thunk PROTO((tree, int));
extern void emit_thunk PROTO((tree));
extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree));
+extern tree get_vlist_vtable_id PROTO((tree, tree));
+
/* in pt.c */
extern void check_template_shadow PROTO ((tree));
@@ -3200,6 +3249,7 @@ extern tree get_tinfo_fn_dynamic PROTO((tree));
extern tree build_typeid PROTO((tree));
extern tree build_x_typeid PROTO((tree));
extern tree get_tinfo_fn PROTO((tree));
+extern tree get_tinfo_fn_unused PROTO((tree));
extern tree get_typeid PROTO((tree));
extern tree get_typeid_1 PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index bdeadb5..069aaaf 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -224,14 +224,21 @@ int warn_long_long = 1;
int warn_ctor_dtor_privacy = 1;
-/* True if we want to implement vtables using "thunks".
- The default is off. */
+/* 1 or 2 if we want to implement vtables using "thunks".
+ The default is off. Version 1 indicates "old" implementation;
+ Version 2 passes the __vlist argument in pvbase cases. */
#ifndef DEFAULT_VTABLE_THUNKS
#define DEFAULT_VTABLE_THUNKS 0
#endif
int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
+#if DEFAULT_VTABLE_THUNKS == 2
+int flag_vtable_thunks_compat = 1;
+#else
+int flag_vtable_thunks_compat = 0;
+#endif
+
/* True if we want to deal with repository information. */
int flag_use_repository;
@@ -633,6 +640,31 @@ lang_decode_option (argc, argv)
found = 1;
cp_deprecated ("-fexternal-templates");
}
+ else if (!strncmp (p, "vtable-thunks", 13))
+ {
+ if (p[13] == '=')
+ {
+ flag_vtable_thunks =
+ read_integral_parameter (p+14, p, 1);
+ }
+ else
+ {
+ /* If the machine file has a default setting, use that
+ for -fvtable-thunks. Otherwise, set it to version
+ 2. */
+#if DEFAULT_VTABLE_THUNKS
+ flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
+#else
+ flag_vtable_thunks = 1;
+#endif
+ }
+ if (flag_vtable_thunks == 2)
+ /* v2 is a compatibility mode between v1 and v3. */
+ flag_vtable_thunks_compat = 1;
+ else if(flag_vtable_thunks == 3)
+ flag_vtable_thunks_compat = 0;
+ found = 1;
+ }
else if (!strcmp (p, "handle-signatures"))
{
flag_handle_signatures = 1;
@@ -644,7 +676,7 @@ lang_decode_option (argc, argv)
flag_new_abi = 1;
flag_do_squangling = 1;
flag_honor_std = 1;
- flag_vtable_thunks = 1;
+ flag_vtable_thunks = 2;
}
else if (!strcmp (p, "no-new-abi"))
{
@@ -917,17 +949,27 @@ grok_x_components (specs)
This function adds the "in-charge" flag to member function FN if
appropriate. It is called from grokclassfn and tsubst.
- FN must be either a constructor or destructor. */
+ FN must be either a constructor or destructor.
+
+ For vtable thunks, types with polymorphic virtual bases need an
+ additional "vlist" argument which is an array of virtual tables.
+ In addition, if backwards-compatibility to v1 thunks is requested,
+ a wrapper constructor may be needed as well. */
void
maybe_retrofit_in_chrg (fn)
tree fn;
{
tree basetype, arg_types, parms, parm, fntype;
+ tree wrapper;
+
+ if (CLASSTYPE_IS_TEMPLATE (DECL_CLASS_CONTEXT (fn)))
+ /* Never retrofit arguments on template methods. */
+ return;
if (DECL_CONSTRUCTOR_P (fn)
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn))
- && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn))
+ && DECL_CONSTRUCTOR_FOR_VBASE (fn) == 0)
/* OK */;
else if (! DECL_CONSTRUCTOR_P (fn)
&& TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE)
@@ -936,7 +978,37 @@ maybe_retrofit_in_chrg (fn)
return;
if (DECL_CONSTRUCTOR_P (fn))
- DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
+ {
+ if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn)))
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE;
+ else
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE;
+ }
+ else if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn)))
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = DESTRUCTOR_FOR_PVBASE;
+
+ /* Retrieve the arguments, because it is potentially modified twice. */
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ basetype = TREE_TYPE (TREE_VALUE (arg_types));
+ arg_types = TREE_CHAIN (arg_types);
+
+ if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)
+ || DECL_DESTRUCTOR_FOR_PVBASE_P (fn))
+ {
+ /* Add the __vlist argument first. See __in_chrg below. */
+ tree id = vlist_identifier;
+ if (DECL_DESTRUCTOR_FOR_PVBASE_P (fn))
+ id = get_identifier (VLIST1_NAME);
+ parm = build_decl (PARM_DECL, id, vlist_type_node);
+ SET_DECL_ARTIFICIAL (parm);
+ DECL_ARG_TYPE (parm) = vlist_type_node;
+ parms = DECL_ARGUMENTS (fn);
+ /* Add it after 'this'. */
+ TREE_CHAIN (parm) = TREE_CHAIN (parms);
+ TREE_CHAIN (parms) = parm;
+
+ arg_types = hash_tree_chain (vlist_type_node, arg_types);
+ }
/* First add it to DECL_ARGUMENTS... */
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
@@ -949,15 +1021,17 @@ maybe_retrofit_in_chrg (fn)
TREE_CHAIN (parms) = parm;
/* ...and then to TYPE_ARG_TYPES. */
- arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
- basetype = TREE_TYPE (TREE_VALUE (arg_types));
- arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
+ arg_types = hash_tree_chain (integer_type_node, arg_types);
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
TREE_TYPE (fn) = fntype;
+
+ if (flag_vtable_thunks_compat
+ && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn))
+ make_vlist_ctor_wrapper (fn);
}
/* Classes overload their constituent function names automatically.
@@ -1042,7 +1116,8 @@ grokclassfn (ctype, function, flags, quals)
if (flags == DTOR_FLAG)
{
- DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
+ DECL_ASSEMBLER_NAME (function) =
+ build_destructor_name (ctype, DECL_DESTRUCTOR_FOR_PVBASE_P (function));
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
diff --git a/contrib/gcc/cp/exception.cc b/contrib/gcc/cp/exception.cc
index 8e8f35f..59342c6 100644
--- a/contrib/gcc/cp/exception.cc
+++ b/contrib/gcc/cp/exception.cc
@@ -247,10 +247,10 @@ __cp_pop_exception (cp_eh_info *p)
if (p->cleanup)
/* 2 is a magic value for destructors; see build_delete(). */
- p->cleanup (p->value, 2);
+ p->cleanup (p->original_value, 2); // value may have been adjusted.
if (! __is_pointer (p->type))
- __eh_free (p->original_value); // value may have been co-erced.
+ __eh_free (p->original_value); // value may have been adjusted.
__eh_free (p);
}
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 38bf248..aed1fde 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -59,7 +59,8 @@ static tree initializing_context PROTO((tree));
static void expand_vec_init_try_block PROTO((tree));
static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree));
static tree build_java_class_ref PROTO((tree));
-static void expand_cleanup_for_base PROTO((tree, tree));
+static void expand_cleanup_for_base PROTO((tree, tree, tree));
+static int pvbasecount PROTO((tree, int));
/* Cache the identifier nodes for the magic field of a new cookie. */
static tree nc_nelts_field_id;
@@ -478,6 +479,93 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
*vbase_ptr = vbases;
}
+/* Invoke a base-class destructor. REF is the object being destroyed,
+ BINFO is the base class, and DTOR_ARG indicates whether the base
+ class should invoke delete. */
+
+tree
+build_base_dtor_call (ref, binfo, dtor_arg)
+ tree ref, binfo, dtor_arg;
+{
+ tree args = NULL_TREE;
+ tree vlist = lookup_name (vlist_identifier, 0);
+ tree call, decr;
+
+ if (TYPE_USES_PVBASES (BINFO_TYPE (binfo)))
+ {
+ args = expr_tree_cons (NULL_TREE, vlist, args);
+ dtor_arg = build (BIT_IOR_EXPR, integer_type_node,
+ dtor_arg, build_int_2 (4, 0));
+ dtor_arg = fold (dtor_arg);
+ }
+ args = expr_tree_cons (NULL_TREE, dtor_arg, args);
+ call = build_scoped_method_call (ref, binfo, dtor_identifier, args);
+
+ if (!TYPE_USES_PVBASES (BINFO_TYPE (binfo)))
+ /* For plain inheritance, do not try to adjust __vlist. */
+ return call;
+
+ /* Now decrement __vlist by the number of slots consumed by the base
+ dtor. */
+ decr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0);
+ decr = build_binary_op (MINUS_EXPR, vlist, decr);
+ decr = build_modify_expr (vlist, NOP_EXPR, decr);
+
+ return build (COMPOUND_EXPR, void_type_node, call, decr);
+}
+
+/* Return the number of vlist entries needed to initialize TYPE,
+ depending on whether it is IN_CHARGE. */
+
+static int
+pvbasecount (type, in_charge)
+ tree type;
+ int in_charge;
+{
+ int i;
+ int result = 0;
+ tree vbase;
+
+ for (vbase = (CLASSTYPE_VBASECLASSES (type)); vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ result += list_length (CLASSTYPE_VFIELDS (BINFO_TYPE (vbase)));
+ if (in_charge)
+ result += pvbasecount (BINFO_TYPE (vbase), 0);
+ }
+
+ for (i=0; i < CLASSTYPE_N_BASECLASSES (type); i++)
+ {
+ tree base = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
+ if (TREE_VIA_VIRTUAL (base))
+ continue;
+ result += pvbasecount (BINFO_TYPE (base), 0);
+ }
+ return result;
+}
+
+void
+init_vlist (t)
+ tree t;
+{
+ char *name;
+ tree expr;
+ tree vlist = lookup_name (vlist_identifier, 0);
+
+ name = alloca (strlen (VLIST_NAME_FORMAT)
+ + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2);
+ sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t));
+
+ expr = get_identifier (name);
+ expr = lookup_name (expr, 0);
+ expr = build1 (ADDR_EXPR, TREE_TYPE (vlist), expr);
+ if (DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl))
+ /* Move to the end of the vlist. */
+ expr = build_binary_op (PLUS_EXPR, expr,
+ build_int_2 (pvbasecount (t, 1), 0));
+ expand_expr_stmt (build_modify_expr (vlist, NOP_EXPR, expr));
+}
+
/* Perform whatever initializations have yet to be done on the base
class of the class variable. These actions are in the global
variable CURRENT_BASE_INIT_LIST. Such an action could be
@@ -510,6 +598,7 @@ emit_base_init (t, immediately)
tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree expr = NULL_TREE;
+ tree vlist = lookup_name (vlist_identifier, 0);
if (! immediately)
{
@@ -581,7 +670,7 @@ emit_base_init (t, immediately)
free_temp_slots ();
}
- expand_cleanup_for_base (base_binfo, NULL_TREE);
+ expand_cleanup_for_base (base_binfo, vlist, NULL_TREE);
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
@@ -750,30 +839,39 @@ expand_virtual_init (binfo, decl)
destroyed. */
static void
-expand_cleanup_for_base (binfo, flag)
+expand_cleanup_for_base (binfo, vlist, flag)
tree binfo;
+ tree vlist;
tree flag;
{
tree expr;
- if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
- return;
+ if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
+ {
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
- /* All cleanups must be on the function_obstack. */
- push_obstacks_nochange ();
- resume_temporary_allocation ();
+ /* Call the destructor. */
+ expr = build_base_dtor_call (current_class_ref, binfo,
+ integer_zero_node);
+ if (flag)
+ expr = fold (build (COND_EXPR, void_type_node,
+ truthvalue_conversion (flag),
+ expr, integer_zero_node));
- /* Call the destructor. */
- expr = (build_scoped_method_call
- (current_class_ref, binfo, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node)));
- if (flag)
- expr = fold (build (COND_EXPR, void_type_node,
- truthvalue_conversion (flag),
- expr, integer_zero_node));
+ pop_obstacks ();
+ add_partial_entry (expr);
+ }
- pop_obstacks ();
- add_partial_entry (expr);
+ if (TYPE_USES_PVBASES (BINFO_TYPE (binfo)))
+ {
+ /* Increment vlist by number of base's vbase classes. */
+ expr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0);
+ expr = build_binary_op (PLUS_EXPR, vlist, expr);
+ expr = build_modify_expr (vlist, NOP_EXPR, expr);
+ expand_expr_stmt (expr);
+ }
}
/* Subroutine of `expand_aggr_vbase_init'.
@@ -813,6 +911,7 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
{
tree vbases;
tree result;
+ tree vlist = NULL_TREE;
/* If there are no virtual baseclasses, we shouldn't even be here. */
my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
@@ -820,6 +919,11 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
/* First set the pointers in our object that tell us where to find
our virtual baseclasses. */
expand_start_cond (flag, 0);
+ if (TYPE_USES_PVBASES (type))
+ {
+ init_vlist (type);
+ vlist = lookup_name (vlist_identifier, 0);
+ }
result = init_vbase_pointers (type, this_ptr);
if (result)
expand_expr_stmt (build_compound_expr (result));
@@ -851,7 +955,7 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
init_list);
expand_end_cond ();
- expand_cleanup_for_base (vbases, flag);
+ expand_cleanup_for_base (vbases, vlist, flag);
}
}
@@ -1146,6 +1250,44 @@ expand_aggr_init (exp, init, flags)
TREE_THIS_VOLATILE (exp) = was_volatile;
}
+static tree
+no_vlist_base_init (rval, exp, init, binfo, flags)
+ tree rval, exp, init, binfo;
+ int flags;
+{
+ tree nrval, func, parms;
+
+ /* Obtain the vlist-expecting ctor. */
+ func = rval;
+ my_friendly_assert (TREE_CODE (func) == CALL_EXPR, 20000131);
+ func = TREE_OPERAND (func, 0);
+ my_friendly_assert (TREE_CODE (func) == ADDR_EXPR, 20000132);
+
+ if (init == NULL_TREE
+ || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
+ {
+ parms = init;
+ if (parms)
+ init = TREE_VALUE (parms);
+ }
+ else
+ parms = build_expr_list (NULL_TREE, init);
+
+ flags &= ~LOOKUP_HAS_VLIST;
+
+ parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);
+ flags |= LOOKUP_HAS_IN_CHARGE;
+
+ nrval = build_method_call (exp, ctor_identifier,
+ parms, binfo, flags);
+
+ func = build (NE_EXPR, boolean_type_node,
+ func, null_pointer_node);
+ nrval = build (COND_EXPR, void_type_node,
+ func, rval, nrval);
+ return nrval;
+}
+
static void
expand_default_init (binfo, true_exp, exp, init, flags)
tree binfo;
@@ -1163,6 +1305,8 @@ expand_default_init (binfo, true_exp, exp, init, flags)
out, then look hard. */
tree rval;
tree parms;
+ tree vlist = NULL_TREE;
+ tree orig_init = init;
if (init && TREE_CODE (init) != TREE_LIST
&& (flags & LOOKUP_ONLYCONVERTING))
@@ -1206,6 +1350,21 @@ expand_default_init (binfo, true_exp, exp, init, flags)
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
+ if (TYPE_USES_PVBASES (type))
+ {
+ /* In compatibility mode, when not calling a base ctor,
+ we do not pass the vlist argument. */
+ if (true_exp == exp)
+ vlist = flag_vtable_thunks_compat? NULL_TREE : vlist_zero_node;
+ else
+ vlist = lookup_name (vlist_identifier, 0);
+
+ if (vlist)
+ {
+ parms = expr_tree_cons (NULL_TREE, vlist, parms);
+ flags |= LOOKUP_HAS_VLIST;
+ }
+ }
if (true_exp == exp)
parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
else
@@ -1215,6 +1374,10 @@ expand_default_init (binfo, true_exp, exp, init, flags)
rval = build_method_call (exp, ctor_identifier,
parms, binfo, flags);
+ if (vlist && true_exp != exp && flag_vtable_thunks_compat)
+ {
+ rval = no_vlist_base_init (rval, exp, orig_init, binfo, flags);
+ }
if (TREE_SIDE_EFFECTS (rval))
expand_expr_stmt (rval);
}
@@ -2408,6 +2571,12 @@ build_new_1 (exp)
if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
{
+ if (TYPE_USES_PVBASES (true_type)
+ && !flag_vtable_thunks_compat)
+ {
+ init = expr_tree_cons (NULL_TREE, vlist_zero_node, init);
+ flags |= LOOKUP_HAS_VLIST;
+ }
init = expr_tree_cons (NULL_TREE, integer_one_node, init);
flags |= LOOKUP_HAS_IN_CHARGE;
}
@@ -3123,9 +3292,21 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else
passed_auto_delete = auto_delete;
- expr = build_method_call
- (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
- NULL_TREE, flags);
+ /* Maybe pass vlist pointer to destructor. */
+ if (TYPE_USES_PVBASES (type))
+ {
+ /* Pass vlist_zero even if in backwards compatibility mode,
+ as the extra argument should not hurt if it is not used. */
+ expr = build_expr_list (NULL_TREE, vlist_zero_node);
+ flags |= LOOKUP_HAS_VLIST;
+ }
+ else
+ expr = NULL_TREE;
+
+ expr = expr_tree_cons (NULL_TREE, passed_auto_delete, expr);
+
+ expr = build_method_call (ref, dtor_identifier, expr,
+ NULL_TREE, flags);
if (do_delete)
expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
@@ -3181,14 +3362,13 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
tree this_auto_delete;
+ /* Should the base invoke delete? */
if (BINFO_OFFSET_ZEROP (base_binfo))
this_auto_delete = parent_auto_delete;
else
this_auto_delete = integer_zero_node;
- expr = build_scoped_method_call
- (ref, base_binfo, dtor_identifier,
- build_expr_list (NULL_TREE, this_auto_delete));
+ expr = build_base_dtor_call (ref, base_binfo, this_auto_delete);
exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
}
@@ -3200,9 +3380,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
- expr = build_scoped_method_call
- (ref, base_binfo, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node));
+ expr = build_base_dtor_call (ref, base_binfo, integer_zero_node);
exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
}
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index d4a667b..d60bfda 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "flags.h"
#include "toplev.h"
+#include "decl.h"
/* TREE_LIST of the current inline functions that need to be
processed. */
@@ -88,6 +89,8 @@ static int is_back_referenceable_type PROTO((tree));
static int check_btype PROTO((tree));
static void build_mangled_name_for_type PROTO((tree));
static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
+static tree build_base_path PROTO((tree, int));
+
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
@@ -1349,6 +1352,15 @@ process_overload_item (parmtype, extra_Gcode)
#endif
case POINTER_TYPE:
+ /* Even though the vlist_type_node is PPPFe (i.e. `int
+ (***)(...)'), it is different from the any other occurence of
+ the pointer type, because the underlying function type is
+ different. */
+ if (parmtype == vlist_type_node)
+ {
+ OB_PUTS (VLIST_TYPE_NAME);
+ return;
+ }
OB_PUTC ('P');
more:
build_mangled_name_for_type (TREE_TYPE (parmtype));
@@ -1809,14 +1821,64 @@ get_id_2 (name, name2)
return get_identifier (obstack_base (&scratch_obstack));
}
-/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
+/* Print a binfo path T, starting with the most derived class. If
+ OMIT_LAST is set, drop and return the most derived class. */
+
+static tree
+build_base_path (t, omit_last)
+ tree t;
+ int omit_last;
+{
+ tree ret = NULL_TREE;
+ if (BINFO_INHERITANCE_CHAIN (t))
+ ret = build_base_path (BINFO_INHERITANCE_CHAIN (t), omit_last);
+ else if (omit_last)
+ return t;
+ process_overload_item (BINFO_TYPE (t), 0);
+ return ret;
+}
+
+/* Return a mangled name for a vlist vtable, using the path of both
+ BASE and VBASE. */
+
+tree
+get_vlist_vtable_id (base, vbase)
+ tree base, vbase;
+{
+ tree last;
+ OB_INIT ();
+ OB_PUTS (VCTABLE_NAME);
+ build_base_path (base, 0);
+ OB_PUTC ('_');
+ /* Since the base path should end where the vbase path starts, we
+ can omit the most-derived class in the vbase path. Check below
+ that this really happens. */
+ last = build_base_path (vbase, 1);
+ my_friendly_assert (BINFO_TYPE (last) == BINFO_TYPE (base), 990402);
+ OB_FINISH ();
+ return get_identifier (obstack_base (&scratch_obstack));
+}
+
+/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. If
+ HAS_VLIST is set, also add the vlist argument. */
tree
-build_destructor_name (type)
+build_destructor_name (type, has_vlist)
tree type;
+ int has_vlist;
{
- return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX),
- type);
+ OB_INIT ();
+ OB_PUTS (DESTRUCTOR_DECL_PREFIX);
+ start_squangling ();
+ build_mangled_name_for_type (type);
+ /* If we need backwards compatibility, we can get aways by
+ not linking type-safely, as the dtor will check whether
+ the argument was provided. */
+ if (has_vlist && !flag_vtable_thunks_compat)
+ OB_PUTS (VLIST_TYPE_NAME);
+ OB_FINISH ();
+ end_squangling ();
+ return get_identifier (obstack_base (&scratch_obstack));
}
/* Given a tree_code CODE, and some arguments (at least one),
@@ -2178,6 +2240,136 @@ emit_thunk (thunk_fndecl)
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
+void
+make_vlist_ctor_wrapper (fn)
+ tree fn;
+{
+ tree fntype, decl;
+ tree arg_types, parms, parm, basetype, pbasetype;
+ tree t, ctors;
+
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ pbasetype = TREE_VALUE (arg_types);
+ basetype = TREE_TYPE (pbasetype);
+ parms = DECL_ARGUMENTS (fn);
+
+ /* Skip this, __in_chrg, and _vlist */
+ arg_types = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_types)));
+
+
+ /* Add __in_charge. */
+ arg_types = hash_tree_chain (integer_type_node, arg_types);
+
+ /* Don't add this to arg_types, as build_cplus_method_type does so. */
+
+ fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
+ arg_types);
+
+ decl = build_lang_decl (FUNCTION_DECL, DECL_NAME (fn), fntype);
+ DECL_LANG_SPECIFIC (decl)->decl_flags = DECL_LANG_SPECIFIC (fn)->decl_flags;
+ DECL_EXTERNAL (decl) = 0;
+ TREE_PUBLIC (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_CONSTRUCTOR_FOR_VBASE (decl) = CONSTRUCTOR_FOR_VBASE;
+ /* Claim that this is never a template instantiation. */
+ DECL_USE_TEMPLATE (decl) = 0;
+ DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+
+ /* Set up clone argument trees for the thunk. */
+ parms = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms)));
+ /* Add this */
+ t = build_decl (PARM_DECL, this_identifier, pbasetype);
+ SET_DECL_ARTIFICIAL (t);
+ DECL_ARG_TYPE (t) = pbasetype;
+ DECL_REGISTER (t) = 1;
+ /* Add __in_charge. */
+ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
+ SET_DECL_ARTIFICIAL (parm);
+ DECL_ARG_TYPE (parm) = integer_type_node;
+ TREE_CHAIN (parm) = t;
+ t = parm;
+
+ while (parms)
+ {
+ tree x = copy_node (parms);
+ TREE_CHAIN (x) = t;
+ DECL_CONTEXT (x) = decl;
+ t = x;
+ parms = TREE_CHAIN (parms);
+ }
+ parms = nreverse (t);
+ DECL_ARGUMENTS (decl) = parms;
+
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload (DECL_NAME (decl),
+ TYPE_ARG_TYPES (TREE_TYPE (decl)), 2);
+
+ ctors = CLASSTYPE_METHOD_VEC (basetype);
+ if (ctors)
+ ctors = TREE_VEC_ELT (ctors, 0);
+ for ( ; ctors; ctors = OVL_NEXT (ctors))
+ if (DECL_ASSEMBLER_NAME (OVL_CURRENT (ctors))
+ == DECL_ASSEMBLER_NAME (decl))
+ break;
+
+ if (!ctors)
+ {
+ add_method (basetype, 0, decl);
+ cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0);
+ }
+ else
+ decl = OVL_CURRENT (ctors);
+
+ /* Remember the original function. */
+ DECL_VLIST_CTOR_WRAPPED (decl) = fn;
+
+ /* When fn is declared, DECL_INITIAL is null. When it is defined,
+ DECL_INITIAL will be error_mark_node. */
+ if (DECL_INITIAL (fn) == error_mark_node)
+ {
+ /* Record that the ctor is being defined, so we also emit the
+ wrapper later. */
+ TREE_USED (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ DECL_INITIAL (decl) = NULL_TREE;
+ mark_inline_for_output (decl);
+ }
+}
+
+static void
+emit_vlist_ctor_wrapper (decl)
+ tree decl;
+{
+ tree t, parms, fn;
+
+ current_function_is_thunk = 1;
+
+ parms = DECL_ARGUMENTS (decl);
+ fn = DECL_VLIST_CTOR_WRAPPED (decl);
+ mark_used (fn);
+
+ /* Build up the call to the real function. */
+ t = NULL_TREE;
+ /* Push this, __in_charge. */
+ t = expr_tree_cons (NULL_TREE, parms, t);
+ parms = TREE_CHAIN (parms);
+ t = expr_tree_cons (NULL_TREE, parms, t);
+ parms = TREE_CHAIN (parms);
+ /* Push 0 as __vlist. */
+ t = expr_tree_cons (NULL_TREE, vlist_zero_node, t);
+ /* Push rest of arguments. */
+ while (parms)
+ {
+ t = expr_tree_cons (NULL_TREE, parms, t);
+ parms = TREE_CHAIN (parms);
+ }
+ t = nreverse (t);
+ t = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), t);
+ expand_expr_stmt (t);
+}
+
+
/* Code for synthesizing methods which have default semantics defined. */
/* For the anonymous union in TYPE, return the member that is at least as
@@ -2212,6 +2404,8 @@ do_build_copy_constructor (fndecl)
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm);
+ if (TYPE_USES_PVBASES (current_class_type))
+ parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
@@ -2408,6 +2602,16 @@ synthesize_method (fndecl)
int nested = (current_function_decl != NULL_TREE);
tree context = hack_decl_function_context (fndecl);
+ /* If this is a wrapper around a undefined vlist ctor, don't emit it
+ even if it is used. */
+ if (DECL_VLIST_CTOR_WRAPPER_P (fndecl))
+ {
+ tree orig_fn = DECL_VLIST_CTOR_WRAPPED (fndecl);
+ mark_used (orig_fn);
+ if (DECL_INITIAL (orig_fn) == NULL_TREE)
+ return;
+ }
+
if (at_eof)
import_export_decl (fndecl);
@@ -2429,7 +2633,11 @@ synthesize_method (fndecl)
tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);
if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl))
arg_chain = TREE_CHAIN (arg_chain);
- if (arg_chain != void_list_node)
+ else if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fndecl))
+ arg_chain = TREE_CHAIN (TREE_CHAIN (arg_chain));
+ if (DECL_VLIST_CTOR_WRAPPER_P (fndecl))
+ emit_vlist_ctor_wrapper (fndecl);
+ else if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
setup_vtbl_ptr ();
@@ -2443,3 +2651,6 @@ synthesize_method (fndecl)
else if (nested)
pop_cp_function_context (context);
}
+
+
+
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index ddbea0a..28c2956 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -161,6 +161,7 @@ static int coerce_template_template_parms PROTO((tree, tree, int,
static tree determine_specialization PROTO((tree, tree, tree *, int));
static int template_args_equal PROTO((tree, tree));
static void print_template_context PROTO((int));
+static int has_pvbases_p PROTO((tree, tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -4685,6 +4686,23 @@ tsubst_friend_class (friend_tmpl, args)
return friend_type;
}
+static int
+has_pvbases_p (t, pattern)
+ tree t, pattern;
+{
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (t))
+ return 0;
+
+ if (TYPE_USES_PVBASES (pattern))
+ return 1;
+
+ for (t = CLASSTYPE_VBASECLASSES (t); t; t = TREE_CHAIN (t))
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (t)))
+ return 1;
+
+ return 0;
+}
+
tree
instantiate_class_template (type)
tree type;
@@ -5035,6 +5053,13 @@ instantiate_class_template (type)
}
}
+ /* After we have calculated the bases, we can now compute whether we
+ have polymorphic vbases. This needs to happen before we
+ instantiate the methods, because the constructors may take
+ additional arguments. */
+ if (flag_vtable_thunks >= 2)
+ TYPE_USES_PVBASES (type) = has_pvbases_p (type, pattern);
+
/* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
for this instantiation. */
for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
@@ -5716,9 +5741,17 @@ tsubst_decl (t, args, type, in_decl)
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
+
+ if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+
/* Set the mangled name for R. */
if (DECL_DESTRUCTOR_P (t))
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ DECL_ASSEMBLER_NAME (r) =
+ build_destructor_name (ctx, DECL_DESTRUCTOR_FOR_PVBASE_P (r));
else
{
/* Instantiations of template functions must be mangled
@@ -5761,11 +5794,14 @@ tsubst_decl (t, args, type, in_decl)
in_decl);
}
+#if 0
+ /* This has now moved further up. */
if (DECL_CONSTRUCTOR_P (r))
{
maybe_retrofit_in_chrg (r);
grok_ctor_properties (ctx, r);
}
+#endif
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
index e0ce5cd..c8c1ba9 100644
--- a/contrib/gcc/cp/rtti.c
+++ b/contrib/gcc/cp/rtti.c
@@ -363,8 +363,19 @@ get_tinfo_var (type)
return tdecl;
}
+/* Returns the decl for a function which will return a type_info node for
+ TYPE. This version does not mark the function used, for use in
+ set_rtti_entry; for the vtable case, we'll get marked in
+ finish_vtable_vardecl, when we know that we want to be emitted.
+
+ We do this to avoid emitting the tinfo node itself, since we don't
+ currently support DECL_DEFER_OUTPUT for variables. Also, we don't
+ associate constant pools with their functions properly, so we would
+ emit string constants and such even though we don't emit the actual
+ function. When those bugs are fixed, this function should go away. */
+
tree
-get_tinfo_fn (type)
+get_tinfo_fn_unused (type)
tree type;
{
tree name;
@@ -393,13 +404,23 @@ get_tinfo_fn (type)
pushdecl_top_level (d);
make_function_rtl (d);
- mark_used (d);
mark_inline_for_output (d);
pop_obstacks ();
return d;
}
+/* Likewise, but also mark it used. Called by various EH and RTTI code. */
+
+tree
+get_tinfo_fn (type)
+ tree type;
+{
+ tree d = get_tinfo_fn_unused (type);
+ mark_used (d);
+ return d;
+}
+
tree
get_typeid_1 (type)
tree type;
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index 8760c6a..fb99f8f 100644
--- a/contrib/gcc/cp/search.c
+++ b/contrib/gcc/cp/search.c
@@ -151,6 +151,9 @@ static int protected_accessible_p PROTO ((tree, tree, tree, tree));
static int friend_accessible_p PROTO ((tree, tree, tree, tree));
static void setup_class_bindings PROTO ((tree, int));
static int template_self_reference_p PROTO ((tree, tree));
+static void expand_direct_vtbls_init_thunks PROTO((tree, tree, int));
+static void expand_indirect_vtbls_init_thunks PROTO((tree, tree, tree));
+
/* Allocate a level of searching. */
@@ -2626,6 +2629,117 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
}
}
+/* Emit initialization of vfields of BASE, where the complete object
+ is pointed to by decl_ptr. DO_SELF indicates we have to do our own
+ vfield, otherwise only proceed to our own direct non-virtual bases. */
+
+static void
+expand_direct_vtbls_init_thunks (base, decl_ptr, do_self)
+ tree base, decl_ptr;
+ int do_self;
+{
+ tree addr, expr;
+ tree type = BINFO_TYPE (base);
+ tree binfos = BINFO_BASETYPES (base);
+ int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree vlist = lookup_name (vlist_identifier, 0);
+ int in_dtor = DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl);
+
+ my_friendly_assert (vlist != NULL_TREE, 990320);
+
+ if (in_dtor)
+ /* In the destructor, we find the vfield pointers for the bases in
+ reverse order, before we find our own vfield pointer. */
+ for (i = n_baselinks - 1; i >= 0; i--)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (type);
+ if (! TREE_VIA_VIRTUAL (base_binfo))
+ expand_direct_vtbls_init_thunks (base_binfo, decl_ptr,
+ is_not_base_vtable);
+ }
+
+ if (do_self && CLASSTYPE_VFIELDS (type))
+ {
+ addr = build_vbase_path (PLUS_EXPR, build_pointer_type (type),
+ decl_ptr, base, 1);
+ addr = build_indirect_ref (addr, "vptr");
+ addr = build_vfield_ref (addr, type);
+
+ /* In a destructor, we decrease the vlist before we retrieve the
+ value. In a constructor, we increase the vlist after we
+ retrieve the value. */
+ if (in_dtor)
+ {
+ expr = build_binary_op (MINUS_EXPR, vlist, integer_one_node);
+ expr = build_modify_expr (vlist, NOP_EXPR, expr);
+ expand_expr_stmt (expr);
+ }
+
+ /* Store the next vptr into the vbase's vptr. */
+ expr = build_indirect_ref (vlist, "__vlist");
+ expr = convert_force (TREE_TYPE (addr), expr, 0);
+ expr = build_modify_expr (addr, NOP_EXPR, expr);
+ expand_expr_stmt (expr);
+
+ /* Advance the vlist. */
+ if (!in_dtor)
+ {
+ expr = build_binary_op (PLUS_EXPR, vlist, integer_one_node);
+ expr = build_modify_expr (vlist, NOP_EXPR, expr);
+ expand_expr_stmt (expr);
+ }
+ }
+
+ if (!in_dtor)
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ int is_not_base_vtable = i != CLASSTYPE_VFIELD_PARENT (type);
+ if (! TREE_VIA_VIRTUAL (base_binfo))
+ expand_direct_vtbls_init_thunks (base_binfo, decl_ptr,
+ is_not_base_vtable);
+ }
+}
+
+/* Like expand_indirect_vtbls_init below, but based on the vtable list
+ passed to the constructor. */
+
+static void
+expand_indirect_vtbls_init_thunks (binfo, true_exp, decl_ptr)
+ tree binfo;
+ tree true_exp, decl_ptr;
+{
+ tree type = BINFO_TYPE (binfo);
+ tree vbases = CLASSTYPE_VBASECLASSES (type);
+ struct vbase_info vi;
+
+ vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0)
+ : decl_ptr);
+ vi.vbase_types = vbases;
+
+ dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
+
+ /* Initialized with vtables of type TYPE. */
+ for (; vbases; vbases = TREE_CHAIN (vbases))
+ {
+ tree addr;
+
+ if (!CLASSTYPE_VFIELD (BINFO_TYPE (vbases)))
+ /* This vbase doesn't have a vptr of its own. */
+ /* FIXME: check */
+ continue;
+
+ addr = convert_pointer_to_vbase (TREE_TYPE (vbases), decl_ptr);
+ expand_direct_vtbls_init_thunks (TYPE_BINFO (BINFO_TYPE (vbases)),
+ addr, 1);
+
+ }
+
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
+}
+
/* 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. MAIN_BINFO is the binfo which determines
@@ -2657,6 +2771,12 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
mark_all_temps_used();
+ if (TYPE_USES_PVBASES (type))
+ {
+ expand_indirect_vtbls_init_thunks (binfo, true_exp, decl_ptr);
+ return;
+ }
+
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
rtx fixup_insns = NULL_RTX;
diff --git a/contrib/gcc/unroll.c b/contrib/gcc/unroll.c
index d6dbcf0..376bc99 100644
--- a/contrib/gcc/unroll.c
+++ b/contrib/gcc/unroll.c
@@ -3682,10 +3682,14 @@ loop_iterations (loop_start, loop_end, loop_info)
return 0;
}
- /* The only new registers that care created before loop iterations are
- givs made from biv increments, so this should never occur. */
-
- if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
+ /* The only new registers that are created before loop iterations
+ are givs made from biv increments or registers created by
+ load_mems. In the latter case, it is possible that try_copy_prop
+ will propagate a new pseudo into the old iteration register but
+ this will be marked by having the REG_USERVAR_P bit set. */
+
+ if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements
+ && ! REG_USERVAR_P (iteration_var))
abort ();
iteration_info (iteration_var, &initial_value, &increment,
OpenPOWER on IntegriCloud