diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 91 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 62 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 94 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 112 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/cxxfilt.c | 304 | ||||
-rw-r--r-- | gcc/cp/decl.c | 16 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 39 | ||||
-rw-r--r-- | gcc/cp/dump.c | 21 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 2 | ||||
-rw-r--r-- | gcc/cp/expr.c | 2 | ||||
-rw-r--r-- | gcc/cp/friend.c | 2 | ||||
-rw-r--r-- | gcc/cp/g++spec.c | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 41 | ||||
-rw-r--r-- | gcc/cp/lex.c | 2 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 87 | ||||
-rw-r--r-- | gcc/cp/method.c | 319 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 39 | ||||
-rw-r--r-- | gcc/cp/parse.y | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/cp/ptree.c | 2 | ||||
-rw-r--r-- | gcc/cp/repo.c | 2 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 46 | ||||
-rw-r--r-- | gcc/cp/search.c | 141 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 75 | ||||
-rw-r--r-- | gcc/cp/spew.c | 9 | ||||
-rw-r--r-- | gcc/cp/tree.c | 56 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
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" |