summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog91
-rw-r--r--gcc/cp/Make-lang.in62
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/class.c94
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/cp-tree.h112
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/cxxfilt.c304
-rw-r--r--gcc/cp/decl.c16
-rw-r--r--gcc/cp/decl2.c39
-rw-r--r--gcc/cp/dump.c21
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/expr.c2
-rw-r--r--gcc/cp/friend.c2
-rw-r--r--gcc/cp/g++spec.c2
-rw-r--r--gcc/cp/init.c41
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/mangle.c87
-rw-r--r--gcc/cp/method.c319
-rw-r--r--gcc/cp/optimize.c39
-rw-r--r--gcc/cp/parse.y2
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/ptree.c2
-rw-r--r--gcc/cp/repo.c2
-rw-r--r--gcc/cp/rtti.c46
-rw-r--r--gcc/cp/search.c141
-rw-r--r--gcc/cp/semantics.c75
-rw-r--r--gcc/cp/spew.c9
-rw-r--r--gcc/cp/tree.c56
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/cp/typeck2.c2
32 files changed, 1093 insertions, 489 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 096b906a633..ceafa26e3a7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2002-12-14 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (simplify_aggr_init_exprs_r): Also prepend the
+ return slot for normal functions. Set CALL_EXPR_HAS_RETURN_SLOT_ADDR.
+ * tree.c (build_cplus_new): If the type isn't TREE_ADDRESSABLE,
+ don't bother with an AGGR_INIT_EXPR.
+ (cp_copy_res_decl_for_inlining): If the type isn't TREE_ADDRESSABLE,
+ just generate a new decl normally. Take return slot parm.
+ * cp-tree.h: Adjust prototype.
+
2002-12-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
PR C++/8031
@@ -9,6 +19,13 @@
* cp-tree.h: Have the multiple-include guards around
the entire file.
+2002-12-10 David Edelsohn <edelsohn@gnu.org>
+
+ * cp/spew.c (feed_input): Change limit to last_pos and pos to cur_pos
+ for SPEW_DEBUG.
+ (snarf_method): Same.
+ (snarf_defarg): Same.
+
2002-12-10 Mark Mitchell <mark@codesourcery.com>
PR c++/8372
@@ -42,6 +59,37 @@
* error.c (dump_expr): Don't ever try to dump a non-existent
expression.
+2002-12-03 Nathan Sidwell <nathan@codesourcery.com>
+
+ Implement covariant returns.
+ * cp-tree.h (IS_AGGR_TYPE_2): Remove.
+ (struct lang_decl_flags): Add this_thunk_p flag.
+ Rename vcall_offset to virtual_offset.
+ (struct lang_decl): Rename delta to fixed_offset.
+ (DECL_THIS_THUNK_P, DECL_RESULT_THUNK_P): New #defines.
+ (SET_DECL_THUNK_P): Add THIS_ADJUSTING arg.
+ (THUNK_DELTA, THUNK_VCALL_OFFSET): Rename to ...
+ (THUNK_FIXED_OFFSET, THUNK_VIRTUAL_OFFSET): ... here.
+ (make_thunk): Add this_adjusting arg.
+ (finish_thunk): Declare.
+ (mangle_thunk): Add this_adjusting arg.
+ * class.c (get_vcall_index): Use base function for lookup.
+ (update_vtable_entry_for_fn): Generate covariant thunk.
+ (finish_struct_1): Set DECL_VINDEX to NULL for thunks.
+ (build_vtbl_initializer): Use base function for lookup.
+ Finish covariant thunk here. Adjust thunk generation.
+ * dump.c (cp_dump_tree): Simplify DECL_GLOBAL_[CD]TOR_P handling.
+ Adjust thunk dumping.
+ * mangle.c (mangle_call_offset): New function.
+ (mangle_thunk): Adjust for covariant thunks.
+ * method.c (make_thunk): Adjust. Do not set name here.
+ (finish_thunk): New function. Set name here.
+ (use_thunk): Generate covariant thunks too.
+ (thunk_adjust): New function.
+ * search.c (covariant_return_p): Remove. Fold into ...
+ (check_final_overrider): ... here. Simplify.
+ * semantics.c (emit_associated_thunks): Walk covariant thunk lists.
+
2002-12-03 Jason Merrill <jason@redhat.com>
PR c++/8674
@@ -104,6 +152,15 @@
* decl2.c (coerce_new_type): Likewise.
* except.c (do_allocate_exception): Likewise.
+2002-11-30 Zack Weinberg <zack@codesourcery.com>
+
+ * call.c, class.c, cp-lang.c, cvt.c, cxxfilt.c, decl.c, decl2.c,
+ dump.c, error.c, except.c, expr.c, friend.c, g++spec.c, init.c,
+ lex.c, mangle.c, method.c, optimize.c, parse.y, pt.c, ptree.c,
+ repo.c, rtti.c, search.c, semantics.c, spew.c, tree.c, typeck.c,
+ typeck2.c: Include coretypes.h and tm.h.
+ * Make-lang.in: Update dependencies.
+
2002-11-30 Mark Mitchell <mark@codesourcery.com>
PR c++/8227
@@ -150,6 +207,11 @@
(template_parms_equal): Remove prototype.
* typeck.c (buuld_indirect_ref): Reformat.
+2002-11-25 Jason Merrill <jason@redhat.com>
+
+ * init.c (build_vec_init): Use a FOR_STMT instead of an IF_STMT
+ and a DO_STMT.
+
2002-11-25 Mark Mitchell <mark@codesourcery.com>
* tree.c (cp_build_qualified_type_real): Correct handling of
@@ -171,6 +233,27 @@
* rtti.c (qualifier_flags): Fix thinko.
+2002-11-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ Remove traditional C constructs 1/n.
+ * cp-tree.h (init_method, set_mangled_name_for_decl,
+ build_opfncall, hack_identifier, make_thunk, use_thunk,
+ synthesize_method, implicitly_declare_fn,
+ skip_artificial_parms_for, optimize_function, calls_setjmp_p,
+ maybe_clone_body): Remove use of PARAMS.
+
+ * method.c (do_build_assign_ref, do_build_copy_constructor,
+ synthesize_exception_spec, locate_dtor, locate_ctor, locate_copy):
+ Likewise.
+ (synthesize_method): Use 'bool' type and constants instead of
+ 'int'.
+ (locate_copy): Likewise.
+ (implicitly_declare_fn): Likewise.
+
+ * optimize.c (calls_setjmp_r, update_cloned_parm, dump_function):
+ Remove old-style declaration.
+ (maybe_clone_body): Use 'bool' type and constants.
+
2002-11-21 Glen Nakamura <glen@imodulo.com>
PR c++/8342
@@ -1030,6 +1113,14 @@
* decl.c (start_cleanup_fn): Clear interface_only before
start_function, restore it afterwards.
+2002-09-02 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (finish_builtin_type): Remove.
+ * decl2.c (finish_builtin_type): Move to common code.
+ * decl.c (build_ptrmemfunc_type): Adjust.
+ * rtti.c (create_pseudo_type_info): Adjust.
+ (create_tinfo_types): Adjust.
+
2002-08-31 Jason Merrill <jason@redhat.com>
* cp-lang.c (cp_expr_size): Allow initialization from a
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 42656e7933d..6c7a6753165 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -57,7 +57,7 @@ C++ c++: cc1plus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: C++ c++
-g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) $(GCC_H) $(CONFIG_H)
+g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) $(CONFIG_H)
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
@@ -219,60 +219,60 @@ c++.stage4: stage4-start
#
# .o: .h dependencies.
CXX_TREE_H = $(TREE_H) cp/cp-tree.h c-common.h cp/cp-tree.def c-common.def \
- function.h varray.h $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \
+ function.h varray.h $(SYSTEM_H) coretypes.h $(CONFIG_H) $(TARGET_H) \
$(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h
-cp/spew.o: cp/spew.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+cp/spew.o: cp/spew.c $(CXX_TREE_H) $(TM_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
toplev.h gt-cp-spew.h
-cp/lex.o: cp/lex.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
c-pragma.h toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h \
cp/operators.def $(TM_P_H)
-cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h $(LANGHOOKS_DEF_H) \
- c-common.h
-cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
+cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
+ $(LANGHOOKS_DEF_H) c-common.h
+cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(GGC_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
debug.h gt-cp-decl.h gtype-cp.h
-cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
+cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h gt-cp-decl2.h
-cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
+cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
-cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
+cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h
-cp/class.o: cp/class.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
-cp/call.o: cp/call.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
+cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
+cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
$(GGC_H) diagnostic.h gt-cp-call.h
-cp/friend.o: cp/friend.c $(CXX_TREE_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
-cp/init.o: cp/init.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
+cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
+cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
$(GGC_H) except.h
-cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
+cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
$(TM_P_H) $(TARGET_H)
-cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
-cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
-cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
+cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
+cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H)
+cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
-cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
-cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
-cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
+cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
+cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h
+cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.h \
cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
-cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
+cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h $(srcdir)/cp/parse.h cp/lex.h \
+cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h $(srcdir)/cp/parse.h cp/lex.h \
toplev.h $(GGC_H) $(RTL_H) except.h tree-inline.h gt-cp-pt.h
-cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h \
+cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h flags.h real.h \
$(LANGHOOKS_DEF_H)
-cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h \
+cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) diagnostic.h \
gt-cp-repo.h
-cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
+cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
-cp/dump.o: cp/dump.c $(CXX_TREE_H) tree-dump.h
-cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
+cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
+cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
input.h $(PARAMS_H) debug.h tree-inline.h
-cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h real.h
+cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h
-cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
- cp/decl.h $(SYSTEM_H) toplev.h $(GGC_H) gt-cp-parse.h
+cp/parse.o: cp/parse.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h except.h output.h \
+ cp/decl.h toplev.h $(GGC_H) gt-cp-parse.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
$(srcdir)/cp/parse.c $(OUTPUT_OPTION)
#
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 072fbe64515..f766092f339 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -26,6 +26,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "output.h"
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 06d09681e6f..9f95c994703 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
@@ -2326,6 +2328,9 @@ get_vcall_index (tree fn, tree type)
{
tree v;
+ if (DECL_RESULT_THUNK_P (fn))
+ fn = TREE_OPERAND (DECL_INITIAL (fn), 0);
+
for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
|| same_signature_p (fn, TREE_PURPOSE (v)))
@@ -2373,10 +2378,53 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
if (overrider == error_mark_node)
return;
+ {
+ /* Check for adjusting covariant return types. */
+ tree over_return = TREE_TYPE (TREE_TYPE (TREE_PURPOSE (overrider)));
+ tree base_return = TREE_TYPE (TREE_TYPE (fn));
+
+ if (POINTER_TYPE_P (over_return)
+ && TREE_CODE (over_return) == TREE_CODE (base_return)
+ && CLASS_TYPE_P (TREE_TYPE (over_return))
+ && CLASS_TYPE_P (TREE_TYPE (base_return)))
+ {
+ tree binfo;
+ base_kind kind;
+
+ binfo = lookup_base (TREE_TYPE (over_return), TREE_TYPE (base_return),
+ ba_check | ba_quiet, &kind);
- /* Check for unsupported covariant returns again now that we've
- calculated the base offsets. */
- check_final_overrider (TREE_PURPOSE (overrider), fn);
+ if (binfo && (kind == bk_via_virtual || !BINFO_OFFSET_ZEROP (binfo)))
+ {
+ tree fixed_offset = BINFO_OFFSET (binfo);
+ tree virtual_offset = NULL_TREE;
+ tree thunk;
+
+ if (kind == bk_via_virtual)
+ {
+ while (!TREE_VIA_VIRTUAL (binfo))
+ binfo = BINFO_INHERITANCE_CHAIN (binfo);
+
+ /* If the covariant type is within the class hierarchy
+ we are currently laying out, the vbase index is not
+ yet known, so we have to remember the virtual base
+ binfo for the moment. The thunk will be finished
+ in build_vtbl_initializer, where we'll know the
+ vtable index of the virtual base. */
+ virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo), t);
+ }
+
+ /* Replace the overriding function with a covariant thunk.
+ We will emit the overriding function in its own slot
+ as well. */
+ thunk = make_thunk (TREE_PURPOSE (overrider), /*this_adjusting=*/0,
+ fixed_offset, virtual_offset);
+ TREE_PURPOSE (overrider) = thunk;
+ if (!virtual_offset && !DECL_NAME (thunk))
+ finish_thunk (thunk, fixed_offset, NULL_TREE);
+ }
+ }
+ }
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
@@ -5261,8 +5309,17 @@ finish_struct_1 (t)
fn = TREE_CHAIN (fn),
vindex += (TARGET_VTABLE_USES_DESCRIPTORS
? TARGET_VTABLE_USES_DESCRIPTORS : 1))
- if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
- DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
+ {
+ tree fndecl = BV_FN (fn);
+
+ if (DECL_THUNK_P (fndecl))
+ /* A thunk. We should never be calling this entry directly
+ from this vtable -- we'd use the entry for the non
+ thunk base function. */
+ DECL_VINDEX (fndecl) = NULL_TREE;
+ else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
+ DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);
+ }
/* Add this class to the list of dynamic classes. */
dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
@@ -7684,11 +7741,24 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
{
tree delta;
tree vcall_index;
- tree fn;
+ tree fn, fn_original;
tree init = NULL_TREE;
fn = BV_FN (v);
-
+ fn_original = (DECL_RESULT_THUNK_P (fn)
+ ? TREE_OPERAND (DECL_INITIAL (fn), 0)
+ : fn);
+ /* Finish an unfinished covariant thunk. */
+ if (DECL_RESULT_THUNK_P (fn) && !DECL_NAME (fn))
+ {
+ tree binfo = THUNK_VIRTUAL_OFFSET (fn);
+ tree fixed_offset = size_int (THUNK_FIXED_OFFSET (fn));
+ tree virtual_offset = BINFO_VPTR_FIELD (binfo);
+
+ fixed_offset = size_diffop (fixed_offset, BINFO_OFFSET (binfo));
+ finish_thunk (fn, fixed_offset, virtual_offset);
+ }
+
/* If the only definition of this function signature along our
primary base chain is from a lost primary, this vtable slot will
never be used, so just zero it out. This is important to avoid
@@ -7702,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
for (b = binfo; ; b = get_primary_binfo (b))
{
/* We found a defn before a lost primary; go ahead as normal. */
- if (look_for_overrides_here (BINFO_TYPE (b), fn))
+ if (look_for_overrides_here (BINFO_TYPE (b), fn_original))
break;
/* The nearest definition is from a lost primary; clear the
@@ -7726,10 +7796,14 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
/* You can't call an abstract virtual function; it's abstract.
So, we replace these functions with __pure_virtual. */
- if (DECL_PURE_VIRTUAL_P (fn))
+ if (DECL_PURE_VIRTUAL_P (fn_original))
fn = abort_fndecl;
else if (!integer_zerop (delta) || vcall_index)
- fn = make_thunk (fn, delta, vcall_index);
+ {
+ fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index);
+ if (!DECL_NAME (fn))
+ finish_thunk (fn, delta, THUNK_VIRTUAL_OFFSET (fn));
+ }
/* Take the address of the function, considering it to be of an
appropriate generic type. */
init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index a7f2d85966e..42b2da0c130 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -21,6 +21,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "c-common.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3b50ffec48a..9176eba7d49 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1001,9 +1001,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
(IS_AGGR_TYPE_CODE (TREE_CODE (T)) && IS_AGGR_TYPE (T))
#define IS_AGGR_TYPE_CODE(T) ((T) == RECORD_TYPE || (T) == UNION_TYPE)
-#define IS_AGGR_TYPE_2(TYPE1, TYPE2) \
- (TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
- && IS_AGGR_TYPE (TYPE1) && IS_AGGR_TYPE (TYPE2))
#define TAGGED_TYPE_P(T) \
(CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE)
#define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T)
@@ -1741,7 +1738,7 @@ struct lang_decl_flags GTY(())
unsigned u1sel : 1;
unsigned u2sel : 1;
unsigned can_be_full : 1;
- unsigned unused : 1; /* One unused bit. */
+ unsigned this_thunk_p : 1;
union lang_decl_u {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
@@ -1760,8 +1757,8 @@ struct lang_decl_flags GTY(())
int discriminator;
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
- THUNK_VCALL_OFFSET. */
- tree GTY((tag ("2"))) vcall_offset;
+ THUNK_VIRTUAL_OFFSET. */
+ tree GTY((tag ("2"))) virtual_offset;
} GTY ((desc ("%1.u2sel"))) u2;
};
@@ -1777,15 +1774,18 @@ struct lang_decl GTY(())
/* For a non-virtual FUNCTION_DECL, this is
DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which
- DECL_THUNK_P does not hold, this is DECL_THUNKS. */
+ DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both
+ this pointer and result pointer adjusting thunks are
+ chained here. This pointer thunks to return pointer thunks
+ will be chained on the return pointer thunk. */
tree context;
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function;
/* In a FUNCTION_DECL for which THUNK_P holds, this is
- THUNK_DELTA. */
- HOST_WIDE_INT delta;
+ THUNK_FIXED_OFFSET. */
+ HOST_WIDE_INT fixed_offset;
/* In an overloaded operator, this is the value of
DECL_OVERLOADED_OPERATOR_P. */
@@ -2067,8 +2067,7 @@ struct lang_decl GTY(())
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider)
-/* The thunks associated with NODE, a FUNCTION_DECL that is not itself
- a thunk. */
+/* The thunks associated with NODE, a FUNCTION_DECL. */
#define DECL_THUNKS(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.context)
@@ -2077,6 +2076,14 @@ struct lang_decl GTY(())
(TREE_CODE (NODE) == FUNCTION_DECL \
&& DECL_LANG_FLAG_7 (NODE))
+/* Nonzero if NODE is a this pointer adjusting thunk. */
+#define DECL_THIS_THUNK_P(NODE) \
+ (DECL_THUNK_P (NODE) && DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p)
+
+/* Nonzero if NODE is a result pointer adjusting thunk. */
+#define DECL_RESULT_THUNK_P(NODE) \
+ (DECL_THUNK_P (NODE) && !DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p)
+
/* Nonzero if NODE is a FUNCTION_DECL, but not a thunk. */
#define DECL_NON_THUNK_FUNCTION_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL && !DECL_THUNK_P (NODE))
@@ -2090,9 +2097,10 @@ struct lang_decl GTY(())
(DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE))
/* Set DECL_THUNK_P for node. */
-#define SET_DECL_THUNK_P(NODE) \
+#define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \
(DECL_LANG_FLAG_7 (NODE) = 1, \
- DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1)
+ DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \
+ DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING))
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
@@ -2922,33 +2930,42 @@ struct lang_decl GTY(())
A thunk is an alternate entry point for an ordinary FUNCTION_DECL.
The address of the ordinary FUNCTION_DECL is given by the
DECL_INITIAL, which is always an ADDR_EXPR whose operand is a
- FUNCTION_DECL. The job of the thunk is to adjust the `this'
- pointer before transferring control to the FUNCTION_DECL.
-
+ FUNCTION_DECL. The job of the thunk is to either adjust the this
+ pointer before transferring control to the FUNCTION_DECL, or call
+ FUNCTION_DECL and then adjust the result value. Note, the result
+ pointer adjusting thunk must perform a call to the thunked
+ function, (or be implemented via passing some invisible parameter
+ to the thunked function, which is modified to perform the
+ adjustment just before returning).
+
A thunk may perform either, or both, of the following operations:
- o Adjust the `this' pointer by a constant offset.
- o Adjust the `this' pointer by looking up a vcall-offset
+ o Adjust the this or result pointer by a constant offset.
+ o Adjust the this or result pointer by looking up a vcall or vbase offset
in the vtable.
- If both operations are performed, then the constant adjument to
- `this' is performed first.
+ A this pointer adjusting thunk converts from a base to a derived
+ class, and hence adds the offsets. A result pointer adjusting thunk
+ converts from a derived class to a base, and hence subtracts the
+ offsets. If both operations are performed, then the constant
+ adjument is performed first for this pointer adjustment and last
+ for the result pointer adjustment.
- The constant adjustment is given by THUNK_DELTA. If the
- vcall-offset is required, the index into the vtable is given by
- THUNK_VCALL_OFFSET. */
+ The constant adjustment is given by THUNK_FIXED_OFFSET. If the
+ vcall or vbase offset is required, the index into the vtable is given by
+ THUNK_VIRTUAL_OFFSET. */
/* An integer indicating how many bytes should be subtracted from the
- `this' pointer when this function is called. */
-#define THUNK_DELTA(DECL) \
- (DECL_LANG_SPECIFIC (DECL)->u.f.delta)
+ this or result pointer when this function is called. */
+#define THUNK_FIXED_OFFSET(DECL) \
+ (DECL_LANG_SPECIFIC (DECL)->u.f.fixed_offset)
-/* A tree indicating how many bytes should be subtracted from the
- vtable for the `this' pointer to find the vcall offset. (The vptr
- is always located at offset zero from the f `this' pointer.) If
- NULL, then there is no vcall offset. */
-#define THUNK_VCALL_OFFSET(DECL) \
- (LANG_DECL_U2_CHECK (DECL, 0)->vcall_offset)
+/* A tree indicating how many bytes should be added to the
+ vtable for the this or result pointer to find the vcall or vbase
+ offset. (The vptr is always located at offset zero from the
+ this or result pointer.) If NULL, then there is no virtual adjust. */
+#define THUNK_VIRTUAL_OFFSET(DECL) \
+ (LANG_DECL_U2_CHECK (DECL, 0)->virtual_offset)
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
@@ -3795,8 +3812,6 @@ extern bool constructor_name_p (tree, tree);
extern void defer_fn PARAMS ((tree));
extern void finish_anon_union PARAMS ((tree));
extern tree finish_table PARAMS ((tree, tree, tree, int));
-extern void finish_builtin_type PARAMS ((tree, const char *,
- tree *, int, tree));
extern tree coerce_new_type PARAMS ((tree));
extern tree coerce_delete_type PARAMS ((tree));
extern void comdat_linkage PARAMS ((tree));
@@ -3947,20 +3962,21 @@ extern void cxx_finish PARAMS ((void));
extern void cxx_init_options PARAMS ((void));
/* in method.c */
-extern void init_method PARAMS ((void));
-extern void set_mangled_name_for_decl PARAMS ((tree));
-extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree));
-extern tree hack_identifier PARAMS ((tree, tree));
-extern tree make_thunk PARAMS ((tree, tree, tree));
-extern void use_thunk PARAMS ((tree, int));
-extern void synthesize_method PARAMS ((tree));
-extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
-extern tree skip_artificial_parms_for PARAMS ((tree, tree));
+extern void init_method (void);
+extern void set_mangled_name_for_decl (tree);
+extern tree build_opfncall (enum tree_code, int, tree, tree, tree);
+extern tree hack_identifier (tree, tree);
+extern tree make_thunk (tree, bool, tree, tree);
+extern void finish_thunk (tree, tree, tree);
+extern void use_thunk (tree, bool);
+extern void synthesize_method (tree);
+extern tree implicitly_declare_fn (special_function_kind, tree, bool);
+extern tree skip_artificial_parms_for (tree, tree);
/* In optimize.c */
-extern void optimize_function PARAMS ((tree));
-extern int calls_setjmp_p PARAMS ((tree));
-extern int maybe_clone_body PARAMS ((tree));
+extern void optimize_function (tree);
+extern bool calls_setjmp_p (tree);
+extern bool maybe_clone_body (tree);
/* in pt.c */
extern void check_template_shadow PARAMS ((tree));
@@ -4282,7 +4298,7 @@ extern tree cp_add_pending_fn_decls PARAMS ((void*,tree));
extern int cp_is_overload_p PARAMS ((tree));
extern int cp_auto_var_in_fn_p PARAMS ((tree,tree));
extern tree cp_copy_res_decl_for_inlining PARAMS ((tree, tree, tree, void*,
- int*, void*));
+ int*, tree));
extern int cp_start_inlining PARAMS ((tree));
extern void cp_end_inlining PARAMS ((tree));
@@ -4385,7 +4401,7 @@ extern tree mangle_typeinfo_string_for_type PARAMS ((tree));
extern tree mangle_vtbl_for_type PARAMS ((tree));
extern tree mangle_vtt_for_type PARAMS ((tree));
extern tree mangle_ctor_vtbl_for_type PARAMS ((tree, tree));
-extern tree mangle_thunk PARAMS ((tree, tree, tree));
+extern tree mangle_thunk PARAMS ((tree, int, tree, tree));
extern tree mangle_conv_op_name_for_type PARAMS ((tree));
extern tree mangle_guard_variable PARAMS ((tree));
extern tree mangle_ref_init_variable PARAMS ((tree));
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 97d24202850..2443505bd8f 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -28,6 +28,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
diff --git a/gcc/cp/cxxfilt.c b/gcc/cp/cxxfilt.c
new file mode 100644
index 00000000000..42da31559a1
--- /dev/null
+++ b/gcc/cp/cxxfilt.c
@@ -0,0 +1,304 @@
+/* Demangler for GNU C++ - main program
+ Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.uucp)
+ Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
+ Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "demangle.h"
+#include "getopt.h"
+#include "version.h"
+
+static const char *program_name;
+static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
+
+static void demangle_it PARAMS ((char *));
+static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN;
+static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN;
+static void print_demangler_list PARAMS ((FILE *));
+
+static void
+demangle_it (mangled_name)
+ char *mangled_name;
+{
+ char *result;
+
+ /* For command line args, also try to demangle type encodings. */
+ result = cplus_demangle (mangled_name, flags | DMGL_TYPES);
+ if (result == NULL)
+ {
+ printf ("%s\n", mangled_name);
+ }
+ else
+ {
+ printf ("%s\n", result);
+ free (result);
+ }
+}
+
+static void
+print_demangler_list (stream)
+ FILE *stream;
+{
+ const struct demangler_engine *demangler;
+
+ fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
+
+ for (demangler = libiberty_demanglers + 1;
+ demangler->demangling_style != unknown_demangling;
+ ++demangler)
+ fprintf (stream, ",%s", demangler->demangling_style_name);
+
+ fprintf (stream, "}");
+}
+
+static void
+usage (stream, status)
+ FILE *stream;
+ int status;
+{
+ fprintf (stream, "\
+Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n",
+ program_name);
+
+ fprintf (stream, "\
+ [-s ");
+ print_demangler_list (stream);
+ fprintf (stream, "]\n");
+
+ fprintf (stream, "\
+ [--format ");
+ print_demangler_list (stream);
+ fprintf (stream, "]\n");
+
+ fprintf (stream, "\
+ [--help] [--version] [arg...]\n");
+ exit (status);
+}
+
+#define MBUF_SIZE 32767
+char mbuffer[MBUF_SIZE];
+
+int strip_underscore = 0;
+
+static const struct option long_options[] = {
+ {"strip-underscores", no_argument, 0, '_'},
+ {"format", required_argument, 0, 's'},
+ {"help", no_argument, 0, 'h'},
+ {"no-strip-underscores", no_argument, 0, 'n'},
+ {"version", no_argument, 0, 'v'},
+ {0, no_argument, 0, 0}
+};
+
+static const char *
+standard_symbol_characters PARAMS ((void));
+
+static const char *
+hp_symbol_characters PARAMS ((void));
+
+/* Return the string of non-alnum characters that may occur
+ as a valid symbol component, in the standard assembler symbol
+ syntax. */
+
+static const char *
+standard_symbol_characters ()
+{
+ return "_$.";
+}
+
+
+/* Return the string of non-alnum characters that may occur
+ as a valid symbol name component in an HP object file.
+
+ Note that, since HP's compiler generates object code straight from
+ C++ source, without going through an assembler, its mangled
+ identifiers can use all sorts of characters that no assembler would
+ tolerate, so the alphabet this function creates is a little odd.
+ Here are some sample mangled identifiers offered by HP:
+
+ typeid*__XT24AddressIndExpClassMember_
+ [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
+ __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
+
+ This still seems really weird to me, since nowhere else in this
+ file is there anything to recognize curly brackets, parens, etc.
+ I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
+ this is right, but I still strongly suspect that there's a
+ misunderstanding here.
+
+ If we decide it's better for c++filt to use HP's assembler syntax
+ to scrape identifiers out of its input, here's the definition of
+ the symbol name syntax from the HP assembler manual:
+
+ Symbols are composed of uppercase and lowercase letters, decimal
+ digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
+ underscore (_). A symbol can begin with a letter, digit underscore or
+ dollar sign. If a symbol begins with a digit, it must contain a
+ non-digit character.
+
+ So have fun. */
+static const char *
+hp_symbol_characters ()
+{
+ return "_$.<>#,*&[]:(){}";
+}
+
+extern int main PARAMS ((int, char **));
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result;
+ int c;
+ const char *valid_symbols;
+ enum demangling_styles style = auto_demangling;
+
+ program_name = argv[0];
+
+ strip_underscore = (USER_LABEL_PREFIX[0] == '_');
+
+ while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
+ {
+ switch (c)
+ {
+ case '?':
+ usage (stderr, 1);
+ break;
+ case 'h':
+ usage (stdout, 0);
+ case 'n':
+ strip_underscore = 0;
+ break;
+ case 'v':
+ printf ("GNU %s (C++ demangler), version %s\n",
+ program_name, version_string);
+ return (0);
+ case '_':
+ strip_underscore = 1;
+ break;
+ case 's':
+ {
+ style = cplus_demangle_name_to_style (optarg);
+ if (style == unknown_demangling)
+ {
+ fprintf (stderr, "%s: unknown demangling style `%s'\n",
+ program_name, optarg);
+ return (1);
+ }
+ else
+ cplus_demangle_set_style (style);
+ }
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ for ( ; optind < argc; optind++)
+ {
+ demangle_it (argv[optind]);
+ }
+ }
+ else
+ {
+ switch (current_demangling_style)
+ {
+ case gnu_demangling:
+ case lucid_demangling:
+ case arm_demangling:
+ case java_demangling:
+ case edg_demangling:
+ case gnat_demangling:
+ case gnu_v3_demangling:
+ case auto_demangling:
+ valid_symbols = standard_symbol_characters ();
+ break;
+ case hp_demangling:
+ valid_symbols = hp_symbol_characters ();
+ break;
+ default:
+ /* Folks should explicitly indicate the appropriate alphabet for
+ each demangling. Providing a default would allow the
+ question to go unconsidered. */
+ fatal ("Internal error: no symbol alphabet for current style");
+ }
+
+ for (;;)
+ {
+ int i = 0;
+ c = getchar ();
+ /* Try to read a label. */
+ while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
+ {
+ if (i >= MBUF_SIZE-1)
+ break;
+ mbuffer[i++] = c;
+ c = getchar ();
+ }
+ if (i > 0)
+ {
+ int skip_first = 0;
+
+ mbuffer[i] = 0;
+ if (mbuffer[0] == '.' || mbuffer[0] == '$')
+ ++skip_first;
+ if (strip_underscore && mbuffer[skip_first] == '_')
+ ++skip_first;
+
+ if (skip_first > i)
+ skip_first = i;
+
+ flags |= (int) style;
+ result = cplus_demangle (mbuffer + skip_first, flags);
+ if (result)
+ {
+ if (mbuffer[0] == '.')
+ putc ('.', stdout);
+ fputs (result, stdout);
+ free (result);
+ }
+ else
+ fputs (mbuffer, stdout);
+
+ fflush (stdout);
+ }
+ if (c == EOF)
+ break;
+ putchar (c);
+ fflush (stdout);
+ }
+ }
+
+ return (0);
+}
+
+static void
+fatal (str)
+ const char *str;
+{
+ fprintf (stderr, "%s: %s\n", program_name, str);
+ exit (1);
+}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e68c06447e1..e3f5b5a9f29 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
@@ -9535,7 +9537,7 @@ tree
build_ptrmemfunc_type (type)
tree type;
{
- tree fields[4];
+ tree field, fields;
tree t;
tree unqualified_variant = NULL_TREE;
@@ -9561,10 +9563,14 @@ build_ptrmemfunc_type (type)
/* ... and not really an aggregate. */
SET_IS_AGGR_TYPE (t, 0);
- fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
- fields[1] = build_decl (FIELD_DECL, delta_identifier,
- delta_type_node);
- finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+ field = build_decl (FIELD_DECL, pfn_identifier, type);
+ fields = field;
+
+ field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
/* Zap out the name so that the back-end will give us the debugging
information for this anonymous RECORD_TYPE. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 248fa2d6725..6734301f2df 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
@@ -1415,43 +1417,6 @@ finish_anon_union (anon_union_decl)
add_decl_stmt (anon_union_decl);
}
-
-/* Finish processing a builtin type TYPE. It's name is NAME,
- its fields are in the array FIELDS. LEN is the number of elements
- in FIELDS minus one, or put another way, it is the maximum subscript
- used in FIELDS.
-
- It is given the same alignment as ALIGN_TYPE. */
-
-void
-finish_builtin_type (type, name, fields, len, align_type)
- tree type;
- const char *name;
- tree fields[];
- int len;
- tree align_type;
-{
- register int i;
-
- TYPE_FIELDS (type) = fields[0];
- for (i = 0; i < len; i++)
- {
- layout_type (TREE_TYPE (fields[i]));
- DECL_FIELD_CONTEXT (fields[i]) = type;
- TREE_CHAIN (fields[i]) = fields[i+1];
- }
- DECL_FIELD_CONTEXT (fields[i]) = type;
- TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
- TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
- layout_type (type);
-#if 0 /* not yet, should get fixed properly later */
- TYPE_NAME (type) = make_type_decl (get_identifier (name), type);
-#else
- TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);
-#endif
- TYPE_STUB_DECL (type) = TYPE_NAME (type);
- layout_decl (TYPE_NAME (type), 0);
-}
/* Auxiliary functions to make type signatures for
`operator new' and `operator delete' correspond to
diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c
index c4472b07359..fa55833e208 100644
--- a/gcc/cp/dump.c
+++ b/gcc/cp/dump.c
@@ -21,6 +21,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "tree-dump.h"
@@ -317,21 +319,22 @@ cp_dump_tree (dump_info, t)
dump_string (di, "destructor");
if (DECL_CONV_FN_P (t))
dump_string (di, "conversion");
- if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
- {
- if (DECL_GLOBAL_CTOR_P (t))
- dump_string (di, "global init");
- if (DECL_GLOBAL_DTOR_P (t))
- dump_string (di, "global fini");
- }
+ if (DECL_GLOBAL_CTOR_P (t))
+ dump_string (di, "global init");
+ if (DECL_GLOBAL_DTOR_P (t))
+ dump_string (di, "global fini");
if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t))
dump_string (di, "pseudo tmpl");
}
else
{
dump_string (di, "thunk");
- dump_int (di, "dlta", THUNK_DELTA (t));
- dump_child ("vcll", THUNK_VCALL_OFFSET (t));
+ if (DECL_THIS_THUNK_P (t))
+ dump_string (di, "this adjusting");
+ else
+ dump_string (di, "result adjusting");
+ dump_int (di, "fixd", THUNK_FIXED_OFFSET (t));
+ dump_child ("virt", THUNK_VIRTUAL_OFFSET (t));
dump_child ("fn", DECL_INITIAL (t));
}
break;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index da880f5fad4..9ede84a7156 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -21,6 +21,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "real.h"
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 747cc1aaef6..753686b1114 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index e5b0439c93d..ede1c473677 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 7b718ace0df..9e474114312 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index d46244857b2..2d8e8f429a5 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "gcc.h"
/* This bit is set if we saw a `-xfoo' language specification. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 39d4c57047e..bfce5564b4b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -24,6 +24,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
@@ -2445,7 +2447,10 @@ build_new_1 (exp)
things; in particular, it would make it difficult to bail out
if the allocation function returns null. Er, no, it wouldn't;
we just don't run the constructor. The standard says it's
- unspecified whether or not the args are evaluated. */
+ unspecified whether or not the args are evaluated.
+
+ FIXME FIXME FIXME inline invisible refs as refs. That way we
+ can preevaluate value parameters. */
if (cleanup)
{
@@ -2753,10 +2758,10 @@ build_vec_init (base, init, from_array)
T* rval = t1;
ptrdiff_t iterator = maxindex;
try {
- do {
+ for (; iterator != -1; --iterator) {
... initialize *t1 ...
++t1;
- } while (--iterator != -1);
+ }
} catch (...) {
... destroy elements that were constructed ...
}
@@ -2856,19 +2861,20 @@ build_vec_init (base, init, from_array)
{
/* If the ITERATOR is equal to -1, then we don't have to loop;
we've already initialized all the elements. */
- tree if_stmt;
- tree do_stmt;
- tree do_body;
+ tree for_stmt;
+ tree for_body;
tree elt_init;
- if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build (NE_EXPR, boolean_type_node,
- iterator, integer_minus_one_node),
- if_stmt);
+ for_stmt = begin_for_stmt ();
+ finish_for_init_stmt (for_stmt);
+ finish_for_cond (build (NE_EXPR, boolean_type_node,
+ iterator, integer_minus_one_node),
+ for_stmt);
+ finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0),
+ for_stmt);
/* Otherwise, loop through the elements. */
- do_stmt = begin_do_stmt ();
- do_body = begin_compound_stmt (/*has_no_scope=*/1);
+ for_body = begin_compound_stmt (/*has_no_scope=*/1);
/* When we're not building a statement-tree, things are a little
complicated. If, when we recursively call build_aggr_init,
@@ -2933,15 +2939,8 @@ build_vec_init (base, init, from_array)
if (base2)
finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0));
- finish_compound_stmt (/*has_no_scope=*/1, do_body);
- finish_do_body (do_stmt);
- finish_do_stmt (build (NE_EXPR, boolean_type_node,
- build_unary_op (PREDECREMENT_EXPR, iterator, 0),
- integer_minus_one_node),
- do_stmt);
-
- finish_then_clause (if_stmt);
- finish_if_stmt ();
+ finish_compound_stmt (/*has_no_scope=*/1, for_body);
+ finish_for_stmt (for_stmt);
}
/* Make sure to cleanup any partially constructed elements. */
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 4558940d675..e60ebe8761e 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 523db85ab38..cf106d518cd 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -49,6 +49,8 @@
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "real.h"
@@ -154,6 +156,7 @@ static void add_substitution PARAMS ((tree));
static inline int is_std_substitution PARAMS ((tree, substitution_identifier_index_t));
static inline int is_std_substitution_char PARAMS ((tree, substitution_identifier_index_t));
static int find_substitution PARAMS ((tree));
+static void mangle_call_offset PARAMS ((tree, tree));
/* Functions for emitting mangled representations of things. */
@@ -2532,45 +2535,79 @@ mangle_ctor_vtbl_for_type (type, binfo)
return get_identifier (result);
}
-/* Return an identifier for the mangled name of a thunk to FN_DECL.
- OFFSET is the initial adjustment to this used to find the vptr. If
- VCALL_OFFSET is non-NULL, this is a virtual thunk, and it is the
- vtbl offset in bytes.
+/* Mangle a this pointer or result pointer adjustment.
+
+ <call-offset> ::= h <fixed offset number> _
+ ::= v <fixed offset number> _ <virtual offset number> _ */
+
+static void
+mangle_call_offset (fixed_offset, virtual_offset)
+ tree fixed_offset;
+ tree virtual_offset;
+{
+ if (virtual_offset)
+ write_char (virtual_offset ? 'v' : 'h');
+ else
+ write_char ('h');
+
+ /* For either flavor, write the fixed offset. */
+ write_integer_cst (fixed_offset);
+ write_char ('_');
+
+ /* For a virtual thunk, add the virtual offset. */
+ if (virtual_offset)
+ {
+ write_integer_cst (virtual_offset);
+ write_char ('_');
+ }
+}
+
+/* Return an identifier for the mangled name of a this-adjusting or
+ covariant thunk to FN_DECL. FIXED_OFFSET is the initial adjustment
+ to this used to find the vptr. If VIRTUAL_OFFSET is non-NULL, this
+ is a virtual thunk, and it is the vtbl offset in
+ bytes. THIS_ADJUSTING is non-zero for a this adjusting thunk and
+ zero for a covariant thunk. Note, that FN_DECL might be a covariant
+ thunk itself. A covariant thunk name always includes the adjustment
+ for the this pointer, even if there is none.
- <special-name> ::= Th <offset number> _ <base encoding>
- ::= Tv <offset number> _ <vcall offset number> _
- <base encoding>
+ <special-name> ::= T <call-offset> <base encoding>
+ ::= Tc <this_adjust call-offset> <result_adjust call-offset>
+ <base encoding>
*/
tree
-mangle_thunk (fn_decl, offset, vcall_offset)
+mangle_thunk (fn_decl, this_adjusting, fixed_offset, virtual_offset)
tree fn_decl;
- tree offset;
- tree vcall_offset;
+ int this_adjusting;
+ tree fixed_offset;
+ tree virtual_offset;
{
const char *result;
start_mangling (fn_decl);
write_string ("_Z");
- /* The <special-name> for virtual thunks is Tv, for non-virtual
- thunks Th. */
write_char ('T');
- if (vcall_offset != 0)
- write_char ('v');
+
+ if (this_adjusting && !DECL_RESULT_THUNK_P (fn_decl))
+ /* Plain this adjusting thunk. */
+ mangle_call_offset (fixed_offset, virtual_offset);
+ else if (!this_adjusting)
+ {
+ /* Covariant thunk with no this adjustment */
+ write_char ('c');
+ mangle_call_offset (integer_zero_node, NULL_TREE);
+ mangle_call_offset (fixed_offset, virtual_offset);
+ }
else
- write_char ('h');
-
- /* For either flavor, write the offset to this. */
- write_integer_cst (offset);
- write_char ('_');
-
- /* For a virtual thunk, add the vcall offset. */
- if (vcall_offset)
{
- /* Virtual thunk. Write the vcall offset and base type name. */
- write_integer_cst (vcall_offset);
- write_char ('_');
+ /* This adjusting thunk to covariant thunk. */
+ write_char ('c');
+ mangle_call_offset (fixed_offset, virtual_offset);
+ mangle_call_offset (ssize_int (THUNK_FIXED_OFFSET (fn_decl)),
+ THUNK_VIRTUAL_OFFSET (fn_decl));
+ fn_decl = TREE_OPERAND (DECL_INITIAL (fn_decl), 0);
}
/* Scoped name. */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 8a905b21b75..12a66f6526d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
/* Handle method declarations. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "rtl.h"
@@ -54,17 +56,18 @@ enum mangling_flags
typedef enum mangling_flags mangling_flags;
-static void do_build_assign_ref PARAMS ((tree));
-static void do_build_copy_constructor PARAMS ((tree));
-static tree synthesize_exception_spec PARAMS ((tree, tree (*) (tree, void *), void *));
-static tree locate_dtor PARAMS ((tree, void *));
-static tree locate_ctor PARAMS ((tree, void *));
-static tree locate_copy PARAMS ((tree, void *));
+static tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree);
+static void do_build_assign_ref (tree);
+static void do_build_copy_constructor (tree);
+static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
+static tree locate_dtor (tree, void *);
+static tree locate_ctor (tree, void *);
+static tree locate_copy (tree, void *);
/* Called once to initialize method.c. */
void
-init_method ()
+init_method (void)
{
init_mangle ();
}
@@ -73,8 +76,7 @@ init_method ()
/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */
void
-set_mangled_name_for_decl (decl)
- tree decl;
+set_mangled_name_for_decl (tree decl)
{
if (processing_template_decl)
/* There's no need to mangle the name of a template function. */
@@ -108,10 +110,8 @@ set_mangled_name_for_decl (decl)
/* NOSTRICT */
tree
-build_opfncall (code, flags, xarg1, xarg2, arg3)
- enum tree_code code;
- int flags;
- tree xarg1, xarg2, arg3;
+build_opfncall (enum tree_code code, int flags,
+ tree xarg1, tree xarg2, tree arg3)
{
return build_new_op (code, flags, xarg1, xarg2, arg3);
}
@@ -136,8 +136,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
compiler faster). */
tree
-hack_identifier (value, name)
- tree value, name;
+hack_identifier (tree value, tree name)
{
tree type;
@@ -265,67 +264,70 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
}
-/* Return a thunk to FUNCTION. For a virtual thunk, DELTA is the
- offset to this used to locate the vptr, and VCALL_INDEX is used to
- look up the eventual subobject location. For a non-virtual thunk,
- DELTA is the offset to this and VCALL_INDEX is NULL. */
+/* Return a this or result adjusting thunk to FUNCTION. THIS_ADJUSTING
+ indicates whether it is a this or result adjusting thunk.
+ FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment
+ (see thunk_adjust). VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET
+ never is. VIRTUAL_OFFSET is the /index/ into the vtable for this
+ adjusting thunks, we scale it to a byte offset. For covariant
+ thunks VIRTUAL_OFFSET is the virtual binfo. You must post process
+ the returned thunk with finish_thunk. */
tree
-make_thunk (function, delta, vcall_index)
- tree function;
- tree delta;
- tree vcall_index;
+make_thunk (tree function, bool this_adjusting,
+ tree fixed_offset, tree virtual_offset)
{
- tree thunk_id;
- tree thunk;
- tree vcall_offset;
HOST_WIDE_INT d;
-
+ tree thunk;
+
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
-
- /* Scale the VCALL_INDEX to be in terms of bytes. */
- if (vcall_index)
- vcall_offset
+ /* We can have this thunks to covariant thunks, but not vice versa. */
+ my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127);
+
+ /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */
+ if (this_adjusting && virtual_offset)
+ virtual_offset
= size_binop (MULT_EXPR,
- vcall_index,
- convert (ssizetype,
- TYPE_SIZE_UNIT (vtable_entry_type)));
- else
- vcall_offset = NULL_TREE;
-
- d = tree_low_cst (delta, 0);
-
- /* See if we already have the thunk in question. */
+ virtual_offset,
+ convert (ssizetype,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
+
+ d = tree_low_cst (fixed_offset, 0);
+
+ /* See if we already have the thunk in question. For this_adjusting
+ thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
+ will be a BINFO (because of the organization of the layout
+ algorithm). */
for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
- if (THUNK_DELTA (thunk) == d
- && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE)
- == (vcall_offset != NULL_TREE))
- && (THUNK_VCALL_OFFSET (thunk)
- ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk),
- vcall_offset)
- : true))
+ if (DECL_THIS_THUNK_P (thunk) == this_adjusting
+ && THUNK_FIXED_OFFSET (thunk) == d
+ && (this_adjusting
+ ? (!THUNK_VIRTUAL_OFFSET (thunk) == !virtual_offset
+ && (!virtual_offset
+ || tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
+ virtual_offset)))
+ : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset))
return thunk;
-
+
/* All thunks must be created before FUNCTION is actually emitted;
the ABI requires that all thunks be emitted together with the
function to which they transfer control. */
my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);
- thunk_id = mangle_thunk (function, delta, vcall_offset);
- thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function));
+ thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
cxx_dup_lang_specific_decl (function);
- SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
TREE_READONLY (thunk) = TREE_READONLY (function);
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
if (flag_weak)
comdat_linkage (thunk);
- SET_DECL_THUNK_P (thunk);
+ SET_DECL_THUNK_P (thunk, this_adjusting);
DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
- THUNK_DELTA (thunk) = d;
- THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+ THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
+ THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
+
/* The thunk itself is not a constructor or destructor, even if
the thing it is thunking to is. */
DECL_INTERFACE_KNOWN (thunk) = 1;
@@ -351,18 +353,85 @@ make_thunk (function, delta, vcall_index)
return thunk;
}
-/* Emit the definition of a C++ multiple inheritance vtable thunk. If
- EMIT_P is nonzero, the thunk is emitted immediately. */
+/* Finish THUNK, a thunk decl. FIXED_OFFSET and VIRTUAL_OFFSET are the
+ adjustments to apply. */
void
-use_thunk (thunk_fndecl, emit_p)
- tree thunk_fndecl;
- int emit_p;
+finish_thunk (tree thunk, tree fixed_offset, tree virtual_offset)
+{
+ tree function, name;
+
+ my_friendly_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk), 20021127);
+ function = TREE_OPERAND (DECL_INITIAL (thunk), 0);
+ name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
+ fixed_offset, virtual_offset);
+ THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
+ THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
+ DECL_NAME (thunk) = name;
+ SET_DECL_ASSEMBLER_NAME (thunk, name);
+}
+
+/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
+ offset indicated by VIRTUAL_OFFSET, if that is
+ non-null. THIS_ADJUSTING is non-zero for a this adjusting thunk and
+ zero for a result adjusting thunk. */
+
+static tree
+thunk_adjust (tree ptr, bool this_adjusting,
+ HOST_WIDE_INT fixed_offset, tree virtual_offset)
+{
+ if (this_adjusting)
+ /* Adjust the pointer by the constant. */
+ ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr,
+ ssize_int (fixed_offset)));
+
+ /* If there's a virtual offset, look up that value in the vtable and
+ adjust the pointer again. */
+ if (virtual_offset)
+ {
+ tree vtable;
+
+ /* It shouldn't be a binfo any more. */
+ my_friendly_assert (TREE_CODE (virtual_offset) == INTEGER_CST, 20021127);
+
+ ptr = save_expr (ptr);
+ /* The vptr is always at offset zero in the object. */
+ vtable = build1 (NOP_EXPR,
+ build_pointer_type (build_pointer_type
+ (vtable_entry_type)),
+ ptr);
+ /* Form the vtable address. */
+ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
+ /* Find the entry with the vcall offset. */
+ vtable = build (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset);
+ /* Get the offset itself. */
+ vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
+ /* Adjust the `this' pointer. */
+ ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable));
+ }
+
+ if (!this_adjusting)
+ /* Adjust the pointer by the constant. */
+ ptr = fold (build (PLUS_EXPR, TREE_TYPE (ptr), ptr,
+ ssize_int (fixed_offset)));
+
+ return ptr;
+}
+
+/* Emit the definition of a C++ multiple inheritance or covariant
+ return vtable thunk. If EMIT_P is nonzero, the thunk is emitted
+ immediately. */
+
+void
+use_thunk (tree thunk_fndecl, bool emit_p)
{
tree fnaddr;
tree function;
- tree vcall_offset;
- HOST_WIDE_INT delta, vcall_value;
+ tree virtual_offset;
+ HOST_WIDE_INT fixed_offset, virtual_value;
+
+ /* We should have called finish_thunk to give it a name. */
+ my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
@@ -385,20 +454,13 @@ use_thunk (thunk_fndecl, emit_p)
if (!emit_p)
return;
- delta = THUNK_DELTA (thunk_fndecl);
- vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
-
- if (vcall_offset)
- {
- vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
-
- /* It is expected that a value of zero means no vcall. */
- if (!vcall_value)
- abort ();
- }
- else
- vcall_value = 0;
+ fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
+ virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
+ virtual_value = (virtual_offset
+ ? tree_low_cst (virtual_offset, /*pos=*/0) : 0);
+ my_friendly_assert (!virtual_offset || virtual_value, 20021026);
+
/* And, if we need to emit the thunk, it's used. */
mark_used (thunk_fndecl);
/* This thunk is actually defined. */
@@ -421,8 +483,9 @@ use_thunk (thunk_fndecl, emit_p)
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
- if (targetm.asm_out.can_output_mi_thunk (thunk_fndecl, delta,
- vcall_value, function))
+ if (DECL_THIS_THUNK_P (thunk_fndecl)
+ && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
+ virtual_value, function))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@@ -433,8 +496,8 @@ use_thunk (thunk_fndecl, emit_p)
current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname);
- targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, delta,
- vcall_value, function);
+ targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
+ fixed_offset, virtual_value, function);
assemble_end_function (thunk_fndecl, fnname);
current_function_decl = 0;
@@ -443,9 +506,10 @@ use_thunk (thunk_fndecl, emit_p)
}
else
{
- /* If we don't have the necessary code for efficient thunks,
- generate a thunk function that just makes a call to the real
- function. Unfortunately, this doesn't work for varargs. */
+ /* If this is a covariant thunk, or we don't have the necessary
+ code for efficient thunks, generate a thunk function that
+ just makes a call to the real function. Unfortunately, this
+ doesn't work for varargs. */
tree a, t;
@@ -453,7 +517,7 @@ use_thunk (thunk_fndecl, emit_p)
error ("generic thunk code fails for method `%#D' which uses `...'",
function);
- /* Set up clone argument trees for the thunk. */
+ /* Set up cloned argument trees for the thunk. */
t = NULL_TREE;
for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
{
@@ -469,42 +533,22 @@ use_thunk (thunk_fndecl, emit_p)
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
/* We don't bother with a body block for thunks. */
- /* Adjust the this pointer by the constant. */
- t = ssize_int (delta);
- t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
-
- /* If there's a vcall offset, look up that value in the vtable and
- adjust the `this' pointer again. */
- if (vcall_offset && !integer_zerop (vcall_offset))
- {
- tree orig_this;
-
- t = save_expr (t);
- orig_this = t;
- /* The vptr is always at offset zero in the object. */
- t = build1 (NOP_EXPR,
- build_pointer_type (build_pointer_type
- (vtable_entry_type)),
- t);
- /* Form the vtable address. */
- t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
- /* Find the entry with the vcall offset. */
- t = build (PLUS_EXPR, TREE_TYPE (t), t, vcall_offset);
- /* Calculate the offset itself. */
- t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
- /* Adjust the `this' pointer. */
- t = fold (build (PLUS_EXPR,
- TREE_TYPE (orig_this),
- orig_this,
- t));
- }
-
+ t = a;
+
+ if (DECL_THIS_THUNK_P (thunk_fndecl))
+ t = thunk_adjust (t, /*this_adjusting=*/1,
+ fixed_offset, virtual_offset);
+
/* Build up the call to the real function. */
t = tree_cons (NULL_TREE, t, NULL_TREE);
for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
t = tree_cons (NULL_TREE, a, t);
t = nreverse (t);
t = build_call (function, t);
+ if (DECL_RESULT_THUNK_P (thunk_fndecl))
+ t = thunk_adjust (t, /*this_adjusting=*/0,
+ fixed_offset, virtual_offset);
+
if (VOID_TYPE_P (TREE_TYPE (t)))
finish_expr_stmt (t);
else
@@ -528,8 +572,7 @@ use_thunk (thunk_fndecl, emit_p)
/* Generate code for default X(X&) constructor. */
static void
-do_build_copy_constructor (fndecl)
- tree fndecl;
+do_build_copy_constructor (tree fndecl)
{
tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
tree t;
@@ -632,8 +675,7 @@ do_build_copy_constructor (fndecl)
}
static void
-do_build_assign_ref (fndecl)
- tree fndecl;
+do_build_assign_ref (tree fndecl)
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
@@ -735,12 +777,11 @@ do_build_assign_ref (fndecl)
}
void
-synthesize_method (fndecl)
- tree fndecl;
+synthesize_method (tree fndecl)
{
- int nested = (current_function_decl != NULL_TREE);
+ bool nested = (current_function_decl != NULL_TREE);
tree context = decl_function_context (fndecl);
- int need_body = 1;
+ bool need_body = true;
tree stmt;
if (at_eof)
@@ -777,7 +818,7 @@ synthesize_method (fndecl)
if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
{
do_build_assign_ref (fndecl);
- need_body = 0;
+ need_body = false;
}
else if (DECL_CONSTRUCTOR_P (fndecl))
{
@@ -814,10 +855,8 @@ synthesize_method (fndecl)
variants yet, so we need to look at the main one. */
static tree
-synthesize_exception_spec (type, extractor, client)
- tree type;
- tree (*extractor) (tree, void *);
- void *client;
+synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
+ void *client)
{
tree raises = empty_except_spec;
tree fields = TYPE_FIELDS (type);
@@ -861,9 +900,7 @@ synthesize_exception_spec (type, extractor, client)
/* Locate the dtor of TYPE. */
static tree
-locate_dtor (type, client)
- tree type;
- void *client ATTRIBUTE_UNUSED;
+locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
{
tree fns;
@@ -877,9 +914,7 @@ locate_dtor (type, client)
/* Locate the default ctor of TYPE. */
static tree
-locate_ctor (type, client)
- tree type;
- void *client ATTRIBUTE_UNUSED;
+locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
{
tree fns;
@@ -910,15 +945,13 @@ struct copy_data
and desired qualifiers of the source operand. */
static tree
-locate_copy (type, client_)
- tree type;
- void *client_;
+locate_copy (tree type, void *client_)
{
struct copy_data *client = (struct copy_data *)client_;
tree fns;
int ix = -1;
tree best = NULL_TREE;
- int excess_p = 0;
+ bool excess_p = false;
if (client->name)
{
@@ -971,16 +1004,13 @@ locate_copy (type, client_)
reference argument or a non-const reference. */
tree
-implicitly_declare_fn (kind, type, const_p)
- special_function_kind kind;
- tree type;
- int const_p;
+implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
{
tree declspecs = NULL_TREE;
tree fn, args = NULL_TREE;
tree raises = empty_except_spec;
- int retref = 0;
- int has_parm = 0;
+ bool retref = false;
+ bool has_parm = false;
tree name = constructor_name (TYPE_IDENTIFIER (type));
switch (kind)
@@ -1004,12 +1034,12 @@ implicitly_declare_fn (kind, type, const_p)
struct copy_data data;
tree argtype = type;
- has_parm = 1;
+ has_parm = true;
data.name = NULL;
data.quals = 0;
if (kind == sfk_assignment_operator)
{
- retref = 1;
+ retref = true;
declspecs = build_tree_list (NULL_TREE, type);
name = ansi_assopname (NOP_EXPR);
@@ -1061,8 +1091,7 @@ implicitly_declare_fn (kind, type, const_p)
as there are artificial parms in FN. */
tree
-skip_artificial_parms_for (fn, list)
- tree fn, list;
+skip_artificial_parms_for (tree fn, tree list)
{
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
list = TREE_CHAIN (list);
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 6fbcc2be192..6de190d4811 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "rtl.h"
@@ -37,15 +39,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Prototypes. */
-static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
-static void update_cloned_parm PARAMS ((tree, tree));
-static void dump_function PARAMS ((enum tree_dump_index, tree));
+static tree calls_setjmp_r (tree *, int *, void *);
+static void update_cloned_parm (tree, tree);
+static void dump_function (enum tree_dump_index, tree);
/* Optimize the body of FN. */
void
-optimize_function (fn)
- tree fn;
+optimize_function (tree fn)
{
dump_function (TDI_original, fn);
@@ -81,10 +82,8 @@ optimize_function (fn)
/* Called from calls_setjmp_p via walk_tree. */
static tree
-calls_setjmp_r (tp, walk_subtrees, data)
- tree *tp;
- int *walk_subtrees ATTRIBUTE_UNUSED;
- void *data ATTRIBUTE_UNUSED;
+calls_setjmp_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
/* We're only interested in FUNCTION_DECLS. */
if (TREE_CODE (*tp) != FUNCTION_DECL)
@@ -98,9 +97,8 @@ calls_setjmp_r (tp, walk_subtrees, data)
occasionally return a nonzero value even when FN does not actually
call `setjmp'. */
-int
-calls_setjmp_p (fn)
- tree fn;
+bool
+calls_setjmp_p (tree fn)
{
return walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
calls_setjmp_r,
@@ -113,9 +111,7 @@ calls_setjmp_p (fn)
debugging generation code will be able to find the original PARM. */
static void
-update_cloned_parm (parm, cloned_parm)
- tree parm;
- tree cloned_parm;
+update_cloned_parm (tree parm, tree cloned_parm)
{
DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
@@ -136,12 +132,11 @@ update_cloned_parm (parm, cloned_parm)
necessary. Returns nonzero if there's no longer any need to
process the main body. */
-int
-maybe_clone_body (fn)
- tree fn;
+bool
+maybe_clone_body (tree fn)
{
tree clone;
- int first = 1;
+ bool first = true;
/* We only clone constructors and destructors. */
if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
@@ -155,7 +150,7 @@ maybe_clone_body (fn)
list. */
for (clone = TREE_CHAIN (fn);
clone && DECL_CLONED_FUNCTION_P (clone);
- clone = TREE_CHAIN (clone), first = 0)
+ clone = TREE_CHAIN (clone), first = false)
{
tree parm;
tree clone_parm;
@@ -278,9 +273,7 @@ maybe_clone_body (fn)
/* Dump FUNCTION_DECL FN as tree dump PHASE. */
static void
-dump_function (phase, fn)
- enum tree_dump_index phase;
- tree fn;
+dump_function (enum tree_dump_index phase, tree fn)
{
FILE *stream;
int flags;
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 0be461eada5..2f0fd937fcb 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -31,6 +31,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "input.h"
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fa3caac01dc..275605e9d9e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -28,6 +28,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "obstack.h"
#include "tree.h"
#include "flags.h"
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index f40e412726c..4a47560ea65 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 64c6ec873fc..ad7a1f68497 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -27,6 +27,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "input.h"
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 7540b5c0e72..d8041ab53e4 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
@@ -1150,8 +1152,7 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
{
tree pseudo_type;
char *pseudo_name;
- int ix;
- tree fields[10];
+ tree fields;
tree field_decl;
tree result;
@@ -1167,15 +1168,18 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);
/* First field is the pseudo type_info base class. */
- fields[0] = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
+ fields = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
/* Now add the derived fields. */
- for (ix = 0; (field_decl = va_arg (ap, tree));)
- fields[++ix] = field_decl;
+ while ((field_decl = va_arg (ap, tree)))
+ {
+ TREE_CHAIN (field_decl) = fields;
+ fields = field_decl;
+ }
/* Create the pseudo type. */
pseudo_type = make_aggr_type (RECORD_TYPE);
- finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
+ finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
@@ -1285,13 +1289,18 @@ create_tinfo_types ()
/* Create the internal type_info structure. This is used as a base for
the other structures. */
{
- tree fields[2];
+ tree field, fields;
ti_desc_type_node = make_aggr_type (RECORD_TYPE);
- fields[0] = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node);
- fields[1] = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node);
- finish_builtin_type (ti_desc_type_node, "__type_info_pseudo",
- fields, 1, ptr_type_node);
+ field = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node);
+ fields = field;
+
+ field = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ finish_builtin_struct (ti_desc_type_node, "__type_info_pseudo",
+ fields, NULL_TREE);
TYPE_HAS_CONSTRUCTOR (ti_desc_type_node) = 1;
}
@@ -1326,13 +1335,18 @@ create_tinfo_types ()
/* Base class internal helper. Pointer to base type, offset to base,
flags. */
{
- tree fields[2];
+ tree field, fields;
+
+ field = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);
+ fields = field;
- fields[0] = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);
- fields[1] = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
+ field = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
base_desc_type_node = make_aggr_type (RECORD_TYPE);
- finish_builtin_type (base_desc_type_node, "__base_class_type_info_pseudo",
- fields, 1, ptr_type_node);
+ finish_builtin_struct (base_desc_type_node, "__base_class_type_info_pseudo",
+ fields, NULL_TREE);
TYPE_HAS_CONSTRUCTOR (base_desc_type_node) = 1;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index fefd11b8b16..4c03f073afd 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "obstack.h"
@@ -97,7 +99,6 @@ static tree dfs_push_type_decls PARAMS ((tree, void *));
static tree dfs_push_decls PARAMS ((tree, void *));
static tree dfs_unuse_fields PARAMS ((tree, void *));
static tree add_conversions PARAMS ((tree, void *));
-static int covariant_return_p PARAMS ((tree, tree));
static int look_for_overrides_r PARAMS ((tree, tree));
static struct search_level *push_search_level
PARAMS ((struct stack_level *, struct obstack *));
@@ -1850,58 +1851,6 @@ dfs_walk (binfo, fn, qfn, data)
return dfs_walk_real (binfo, 0, fn, qfn, data);
}
-/* Returns > 0 if a function with type DRETTYPE overriding a function
- with type BRETTYPE is covariant, as defined in [class.virtual].
-
- Returns 1 if trivial covariance, 2 if non-trivial (requiring runtime
- adjustment), or -1 if pedantically invalid covariance. */
-
-static int
-covariant_return_p (brettype, drettype)
- tree brettype, drettype;
-{
- tree binfo;
- base_kind kind;
-
- if (TREE_CODE (brettype) == FUNCTION_DECL)
- {
- brettype = TREE_TYPE (TREE_TYPE (brettype));
- drettype = TREE_TYPE (TREE_TYPE (drettype));
- }
- else if (TREE_CODE (brettype) == METHOD_TYPE)
- {
- brettype = TREE_TYPE (brettype);
- drettype = TREE_TYPE (drettype);
- }
-
- if (same_type_p (brettype, drettype))
- return 0;
-
- if (! (TREE_CODE (brettype) == TREE_CODE (drettype)
- && (TREE_CODE (brettype) == POINTER_TYPE
- || TREE_CODE (brettype) == REFERENCE_TYPE)
- && TYPE_QUALS (brettype) == TYPE_QUALS (drettype)))
- return 0;
-
- if (! can_convert (brettype, drettype))
- return 0;
-
- brettype = TREE_TYPE (brettype);
- drettype = TREE_TYPE (drettype);
-
- /* If not pedantic, allow any standard pointer conversion. */
- if (! IS_AGGR_TYPE (drettype) || ! IS_AGGR_TYPE (brettype))
- return -1;
-
- binfo = lookup_base (drettype, brettype, ba_check | ba_quiet, &kind);
-
- if (!binfo)
- return 0;
- if (BINFO_OFFSET_ZEROP (binfo) && kind != bk_via_virtual)
- return 1;
- return 2;
-}
-
/* Check that virtual overrider OVERRIDER is acceptable for base function
BASEFN. Issue diagnostic, and return zero, if unacceptable. */
@@ -1915,32 +1864,74 @@ check_final_overrider (overrider, basefn)
tree base_return = TREE_TYPE (base_type);
tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
- int i;
+ int fail = 0;
if (same_type_p (base_return, over_return))
/* OK */;
- else if ((i = covariant_return_p (base_return, over_return)))
+ else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
+ || (TREE_CODE (base_return) == TREE_CODE (over_return)
+ && POINTER_TYPE_P (base_return)))
{
- if (i == 2)
- sorry ("adjusting pointers for covariant returns");
+ /* Potentially covariant. */
+ unsigned base_quals, over_quals;
+
+ fail = !POINTER_TYPE_P (base_return);
+ if (!fail)
+ {
+ fail = cp_type_quals (base_return) != cp_type_quals (over_return);
+
+ base_return = TREE_TYPE (base_return);
+ over_return = TREE_TYPE (over_return);
+ }
+ base_quals = cp_type_quals (base_return);
+ over_quals = cp_type_quals (over_return);
+
+ if ((base_quals & over_quals) != over_quals)
+ fail = 1;
+
+ if (CLASS_TYPE_P (base_return) && CLASS_TYPE_P (over_return))
+ {
+ tree binfo = lookup_base (over_return, base_return,
+ ba_check | ba_quiet, NULL);
- if (pedantic && i == -1)
+ if (!binfo)
+ fail = 1;
+ }
+ else if (!pedantic
+ && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
+ /* GNU extension, allow trivial pointer conversions such as
+ converting to void *, or qualification conversion. */
{
- cp_pedwarn_at ("invalid covariant return type for `%#D'", overrider);
- cp_pedwarn_at (" overriding `%#D' (must be pointer or reference to class)", basefn);
+ /* can_convert will permit user defined conversion from a
+ (reference to) class type. We must reject them. */
+ over_return = TREE_TYPE (over_type);
+ if (TREE_CODE (over_return) == REFERENCE_TYPE)
+ over_return = TREE_TYPE (over_return);
+ if (CLASS_TYPE_P (over_return))
+ fail = 2;
}
+ else
+ fail = 2;
}
- else if (IS_AGGR_TYPE_2 (base_return, over_return)
- && same_or_base_type_p (base_return, over_return))
- {
- cp_error_at ("invalid covariant return type for `%#D'", overrider);
- cp_error_at (" overriding `%#D' (must use pointer or reference)", basefn);
- return 0;
- }
- else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)) == NULL_TREE)
+ else
+ fail = 2;
+ if (!fail)
+ /* OK */;
+ else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
+ return 0;
+ else
{
- cp_error_at ("conflicting return type specified for `%#D'", overrider);
- cp_error_at (" overriding `%#D'", basefn);
+ if (fail == 1)
+ {
+ cp_error_at ("invalid covariant return type for `%#D'", overrider);
+ cp_error_at (" overriding `%#D'", basefn);
+ }
+ else
+ {
+ cp_error_at ("conflicting return type specified for `%#D'",
+ overrider);
+ cp_error_at (" overriding `%#D'", basefn);
+ }
SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
DECL_CONTEXT (overrider));
return 0;
@@ -1949,10 +1940,16 @@ check_final_overrider (overrider, basefn)
/* Check throw specifier is at least as strict. */
if (!comp_except_specs (base_throw, over_throw, 0))
{
- cp_error_at ("looser throw specifier for `%#F'", overrider);
- cp_error_at (" overriding `%#F'", basefn);
+ if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
+ {
+ cp_error_at ("looser throw specifier for `%#F'", overrider);
+ cp_error_at (" overriding `%#F'", basefn);
+ SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
+ DECL_CONTEXT (overrider));
+ }
return 0;
}
+
return 1;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 81b4ccfdafc..1ceb1f37261 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -26,6 +26,8 @@
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "tree-inline.h"
@@ -2188,7 +2190,7 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
tree args;
tree slot;
tree type;
- int copy_from_buffer_p;
+ enum style_t { ctor, arg, pcc } style;
aggr_init_expr = *tp;
/* We don't need to walk into types; there's nothing in a type that
@@ -2210,48 +2212,66 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
args = TREE_OPERAND (aggr_init_expr, 1);
slot = TREE_OPERAND (aggr_init_expr, 2);
type = TREE_TYPE (aggr_init_expr);
+
if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
+ style = ctor;
+#ifdef PCC_STATIC_STRUCT_RETURN
+ else if (1)
+ style = pcc;
+#endif
+ else if (TREE_ADDRESSABLE (type))
+ style = arg;
+ else
+ /* We shouldn't build an AGGR_INIT_EXPR if we don't need any special
+ handling. See build_cplus_new. */
+ abort ();
+
+ if (style == ctor || style == arg)
{
- /* Replace the first argument with the address of the third
- argument to the AGGR_INIT_EXPR. */
+ /* Pass the address of the slot. If this is a constructor, we
+ replace the first argument; otherwise, we tack on a new one. */
+ if (style == ctor)
+ args = TREE_CHAIN (args);
+
cxx_mark_addressable (slot);
args = tree_cons (NULL_TREE,
build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (slot)),
slot),
- TREE_CHAIN (args));
+ args);
}
+
call_expr = build (CALL_EXPR,
TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
fn, args, NULL_TREE);
TREE_SIDE_EFFECTS (call_expr) = 1;
- /* If we're using the non-reentrant PCC calling convention, then we
- need to copy the returned value out of the static buffer into the
- SLOT. */
- copy_from_buffer_p = 0;
-#ifdef PCC_STATIC_STRUCT_RETURN
- if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
+ if (style == arg)
+ {
+ /* Tell the backend that we've added our return slot to the argument
+ list. */
+ CALL_EXPR_HAS_RETURN_SLOT_ADDR (call_expr) = 1;
+ /* And don't let anyone use the value of the call directly in a
+ larger expression. */
+ TREE_TYPE (call_expr) = void_type_node;
+ }
+ else if (style == pcc)
{
+ /* If we're using the non-reentrant PCC calling convention, then we
+ need to copy the returned value out of the static buffer into the
+ SLOT. */
int old_ac = flag_access_control;
flag_access_control = 0;
call_expr = build_aggr_init (slot, call_expr,
DIRECT_BIND | LOOKUP_ONLYCONVERTING);
flag_access_control = old_ac;
- copy_from_buffer_p = 1;
}
-#endif
- /* If this AGGR_INIT_EXPR indicates the value returned by a
- function, then we want to use the value of the initialized
- location as the result. */
- if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
- {
- call_expr = build (COMPOUND_EXPR, type,
- call_expr, slot);
- TREE_SIDE_EFFECTS (call_expr) = 1;
- }
+ /* We want to use the value of the initialized location as the
+ result. */
+ call_expr = build (COMPOUND_EXPR, type,
+ call_expr, slot);
/* Replace the AGGR_INIT_EXPR with the CALL_EXPR. */
TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
@@ -2275,8 +2295,19 @@ emit_associated_thunks (fn)
if (DECL_VIRTUAL_P (fn))
{
tree thunk;
+
for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
- use_thunk (thunk, /*emit_p=*/1);
+ {
+ use_thunk (thunk, /*emit_p=*/1);
+ if (DECL_RESULT_THUNK_P (thunk))
+ {
+ tree probe;
+
+ for (probe = DECL_THUNKS (thunk);
+ probe; probe = TREE_CHAIN (probe))
+ use_thunk (probe, /*emit_p=*/1);
+ }
+ }
}
}
diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c
index adc3ffd40cf..947ca36c6d4 100644
--- a/gcc/cp/spew.c
+++ b/gcc/cp/spew.c
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
@@ -387,7 +389,8 @@ feed_input (input)
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tfeeding %s:%d [%d tokens]\n",
- input->locus.file, input->locus.line, input->limit - input->pos);
+ input->locus.file, input->locus.line,
+ input->last_pos - input->cur_pos);
#endif
f->input = input;
@@ -1214,7 +1217,7 @@ snarf_method (decl)
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n",
- meth->limit, starting.file, starting.line);
+ meth->last_pos, starting.file, starting.line);
#endif
DECL_PENDING_INLINE_INFO (decl) = meth;
@@ -1275,7 +1278,7 @@ snarf_defarg ()
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n",
- buf->limit, starting.file, starting.line);
+ buf->last_pos, starting.file, starting.line);
#endif
arg = make_node (DEFAULT_ARG);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 6c313eba4d8..4c328394114 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
@@ -299,6 +301,7 @@ build_cplus_new (type, init)
tree fn;
tree slot;
tree rval;
+ int is_ctor;
/* Make sure that we're not trying to create an instance of an
abstract class. */
@@ -307,6 +310,11 @@ build_cplus_new (type, init)
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init);
+ fn = TREE_OPERAND (init, 0);
+ is_ctor = (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
+
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
@@ -320,13 +328,18 @@ build_cplus_new (type, init)
replaces every AGGR_INIT_EXPR with a copy that uses a fresh
temporary slot. Then, expand_expr builds up a call-expression
using the new slot. */
- fn = TREE_OPERAND (init, 0);
- rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
- TREE_SIDE_EFFECTS (rval) = 1;
- AGGR_INIT_VIA_CTOR_P (rval)
- = (TREE_CODE (fn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
- && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
+
+ /* If we don't need to use a constructor to create an object of this
+ type, don't mess with AGGR_INIT_EXPR. */
+ if (is_ctor || TREE_ADDRESSABLE (type))
+ {
+ rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
+ TREE_SIDE_EFFECTS (rval) = 1;
+ AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
+ }
+ else
+ rval = init;
+
rval = build_target_expr (slot, rval);
return rval;
@@ -2311,33 +2324,32 @@ cp_auto_var_in_fn_p (var, fn)
tree
cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
- need_decl, target_exprs)
+ need_decl, return_slot_addr)
tree result, fn, caller;
void *decl_map_;
int *need_decl;
- void *target_exprs;
+ tree return_slot_addr;
{
splay_tree decl_map = (splay_tree)decl_map_;
- varray_type *texps = (varray_type *)target_exprs;
tree var;
- int aggregate_return_p;
-
- /* Figure out whether or not FN returns an aggregate. */
- aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
- *need_decl = ! aggregate_return_p;
- /* If FN returns an aggregate then the caller will always create the
- temporary (using a TARGET_EXPR) and the call will be the
- initializing expression for the TARGET_EXPR. If we were just to
+ /* If FN returns an aggregate then the caller will always pass the
+ address of the return slot explicitly. If we were just to
create a new VAR_DECL here, then the result of this function
would be copied (bitwise) into the variable initialized by the
TARGET_EXPR. That's incorrect, so we must transform any
references to the RESULT into references to the target. */
- if (aggregate_return_p)
+
+ /* We should have an explicit return slot iff the return type is
+ TREE_ADDRESSABLE. See simplify_aggr_init_expr. */
+ if (TREE_ADDRESSABLE (TREE_TYPE (result))
+ != (return_slot_addr != NULL_TREE))
+ abort ();
+
+ *need_decl = !return_slot_addr;
+ if (return_slot_addr)
{
- if (VARRAY_ACTIVE_SIZE (*texps) == 0)
- abort ();
- var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
+ var = build_indirect_ref (return_slot_addr, "");
if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
TREE_TYPE (result)))
abort ();
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 85eef41c2e0..1c78dd1d057 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 750aa3c94bf..e60fdcacb92 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -33,6 +33,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"