*** ./cp/call.c.~1~ Fri Aug 2 10:20:58 2002 --- ./cp/call.c Fri Aug 2 12:18:19 2002 *************** convert_arg_to_ellipsis (arg) *** 4111,4119 **** if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg))) { ! /* Undefined behaviour [expr.call] 5.2.2/7. */ ! warning ("cannot pass objects of non-POD type `%#T' through `...'", ! TREE_TYPE (arg)); } return arg; --- 4111,4122 ---- if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg))) { ! /* Undefined behaviour [expr.call] 5.2.2/7. We used to just warn ! here and do a bitwise copy, but now cp_expr_size will abort if we ! try to do that. */ ! error ("cannot pass objects of non-POD type `%#T' through `...'", ! TREE_TYPE (arg)); ! arg = error_mark_node; } return arg; *************** build_over_call (cand, args, flags) *** 4436,4450 **** else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) return build_target_expr_with_type (arg, DECL_CONTEXT (fn)); } ! else if ((!real_lvalue_p (arg) ! || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) ! /* Empty classes have padding which can be hidden ! inside an (empty) base of the class. This must not ! be touched as it might overlay things. When the ! gcc core learns about empty classes, we can treat it ! like other classes. */ ! && !(is_empty_class (DECL_CONTEXT (fn)) ! && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))) { tree address; tree to = stabilize_reference --- 4439,4446 ---- else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) return build_target_expr_with_type (arg, DECL_CONTEXT (fn)); } ! else if (!real_lvalue_p (arg) ! || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) { tree address; tree to = stabilize_reference *************** build_over_call (cand, args, flags) *** 4466,4489 **** (build_indirect_ref (TREE_VALUE (converted_args), 0)); arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); ! if (is_empty_class (TREE_TYPE (to))) ! { ! TREE_USED (arg) = 1; ! ! val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to); ! /* Even though the assignment may not actually result in any ! code being generated, we do not want to warn about the ! assignment having no effect. That would be confusing to ! users who may be performing the assignment as part of a ! generic algorithm, for example. ! ! Ideally, the notions of having side-effects and of being ! useless would be orthogonal. */ ! TREE_SIDE_EFFECTS (val) = 1; ! TREE_NO_UNUSED_WARNING (val) = 1; ! } ! else ! val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); return val; } --- 4462,4468 ---- (build_indirect_ref (TREE_VALUE (converted_args), 0)); arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); ! val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); return val; } *** ./cp/typeck.c.~1~ Fri Aug 2 10:21:01 2002 --- ./cp/typeck.c Fri Aug 2 10:22:57 2002 *************** build_modify_expr (lhs, modifycode, rhs) *** 5077,5084 **** except that the RHS goes through a save-expr so the code to compute it is only emitted once. */ tree cond; ! rhs = save_expr (rhs); /* Check this here to avoid odd errors when trying to convert a throw to the type of the COND_EXPR. */ --- 5077,5085 ---- except that the RHS goes through a save-expr so the code to compute it is only emitted once. */ tree cond; + tree preeval = NULL_TREE; ! rhs = stabilize_expr (rhs, &preeval); /* Check this here to avoid odd errors when trying to convert a throw to the type of the COND_EXPR. */ *************** build_modify_expr (lhs, modifycode, rhs) *** 5098,5107 **** return cond; /* Make sure the code to compute the rhs comes out before the split. */ ! return build (COMPOUND_EXPR, TREE_TYPE (lhs), ! /* Cast to void to suppress warning ! from warn_if_unused_value. */ ! cp_convert (void_type_node, rhs), cond); } case OFFSET_REF: --- 5099,5105 ---- return cond; /* Make sure the code to compute the rhs comes out before the split. */ ! return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond); } case OFFSET_REF: *** ./cp/cp-lang.c.~1~ Fri Jul 26 16:56:17 2002 --- ./cp/cp-lang.c Fri Aug 2 10:22:58 2002 *************** Boston, MA 02111-1307, USA. */ *** 31,36 **** --- 31,37 ---- static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree)); static bool ok_to_generate_alias_set_for_type PARAMS ((tree)); static bool cxx_warn_unused_global_decl PARAMS ((tree)); + static tree cp_expr_size PARAMS ((tree)); #undef LANG_HOOKS_NAME #define LANG_HOOKS_NAME "GNU C++" *************** static bool cxx_warn_unused_global_decl *** 133,138 **** --- 134,141 ---- #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals + #undef LANG_HOOKS_EXPR_SIZE + #define LANG_HOOKS_EXPR_SIZE cp_expr_size #undef LANG_HOOKS_MAKE_TYPE #define LANG_HOOKS_MAKE_TYPE cxx_make_type *************** cxx_warn_unused_global_decl (decl) *** 280,282 **** --- 283,310 ---- return true; } + + /* Langhook for expr_size: Tell the backend that the value of an expression + of non-POD class type does not include any tail padding; a derived class + might have allocated something there. */ + + static tree + cp_expr_size (exp) + tree exp; + { + if (CLASS_TYPE_P (TREE_TYPE (exp))) + { + /* The backend should not be interested in the size of an expression + of a type with both of these set; all copies of such types must go + through a constructor or assignment op. */ + if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp)) + && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp))) + abort (); + /* This would be wrong for a type with virtual bases, but they are + caught by the abort above. */ + return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp)); + } + else + /* Use the default code. */ + return lhd_expr_size (exp); + } *** ./Makefile.in.~1~ Fri Aug 2 10:20:21 2002 --- ./Makefile.in Fri Aug 2 10:22:58 2002 *************** expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) *** 1427,1433 **** builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \ $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \ ! except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ $(EXPR_H) langhooks.h \ libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) --- 1427,1433 ---- builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \ $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \ ! except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ $(EXPR_H) langhooks.h \ libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) *** ./explow.c.~1~ Wed Jul 24 17:17:07 2002 --- ./explow.c Fri Aug 2 10:22:58 2002 *************** Software Foundation, 59 Temple Place - S *** 34,39 **** --- 34,40 ---- #include "insn-config.h" #include "ggc.h" #include "recog.h" + #include "langhooks.h" static rtx break_out_memory_refs PARAMS ((rtx)); static void emit_stack_probe PARAMS ((rtx)); *************** rtx *** 285,304 **** expr_size (exp) tree exp; { ! tree size; ! ! if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd' ! && DECL_SIZE_UNIT (exp) != 0) ! size = DECL_SIZE_UNIT (exp); ! else ! size = size_in_bytes (TREE_TYPE (exp)); if (TREE_CODE (size) != INTEGER_CST && contains_placeholder_p (size)) size = build (WITH_RECORD_EXPR, sizetype, size, exp); return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0); - } /* Return a copy of X in which all memory references --- 286,298 ---- expr_size (exp) tree exp; { ! tree size = (*lang_hooks.expr_size) (exp); if (TREE_CODE (size) != INTEGER_CST && contains_placeholder_p (size)) size = build (WITH_RECORD_EXPR, sizetype, size, exp); return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0); } /* Return a copy of X in which all memory references *** ./expr.c.~1~ Fri Aug 2 10:20:27 2002 --- ./expr.c Fri Aug 2 10:22:58 2002 *************** store_expr (exp, target, want_value) *** 4241,4246 **** --- 4241,4248 ---- || (temp != target && (side_effects_p (temp) || side_effects_p (target)))) && TREE_CODE (exp) != ERROR_MARK + /* If there's nothing to copy, don't bother. */ + && expr_size (exp) != const0_rtx && ! dont_store_target /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET, but TARGET is not valid memory reference, TEMP will differ *************** expand_expr (exp, target, tmode, modifie *** 6810,6817 **** * TYPE_QUAL_CONST))), 0, TREE_ADDRESSABLE (exp), 1); ! store_constructor (exp, target, 0, ! int_size_in_bytes (TREE_TYPE (exp))); return target; } --- 6812,6818 ---- * TYPE_QUAL_CONST))), 0, TREE_ADDRESSABLE (exp), 1); ! store_constructor (exp, target, 0, INTVAL (expr_size (exp))); return target; } *** ./langhooks-def.h.~1~ Wed Jul 24 17:17:16 2002 --- ./langhooks-def.h Fri Aug 2 10:22:58 2002 *************** extern void lhd_set_decl_assembler_name *** 62,67 **** --- 62,68 ---- extern bool lhd_warn_unused_global_decl PARAMS ((tree)); extern void lhd_incomplete_type_error PARAMS ((tree, tree)); extern tree lhd_type_promotes_to PARAMS ((tree)); + extern tree lhd_expr_size PARAMS ((tree)); /* Declarations of default tree inlining hooks. */ tree lhd_tree_inlining_walk_subtrees PARAMS ((tree *, int *, *************** tree lhd_tree_inlining_convert_parm_for_ *** 109,114 **** --- 110,116 ---- #define LANG_HOOKS_PRINT_IDENTIFIER lhd_print_tree_nothing #define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function #define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name + #define LANG_HOOKS_EXPR_SIZE lhd_expr_size #define LANG_HOOKS_FUNCTION_INIT lhd_do_nothing_f #define LANG_HOOKS_FUNCTION_FINAL lhd_do_nothing_f *************** int lhd_tree_dump_type_quals PARAMS (( *** 247,252 **** --- 249,255 ---- LANG_HOOKS_PRINT_IDENTIFIER, \ LANG_HOOKS_DECL_PRINTABLE_NAME, \ LANG_HOOKS_PRINT_ERROR_FUNCTION, \ + LANG_HOOKS_EXPR_SIZE, \ LANG_HOOKS_ATTRIBUTE_TABLE, \ LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \ *** ./langhooks.c.~1~ Fri Jun 7 13:14:46 2002 --- ./langhooks.c Fri Aug 2 10:22:58 2002 *************** lhd_tree_dump_type_quals (t) *** 421,423 **** --- 421,437 ---- { return TYPE_QUALS (t); } + + /* lang_hooks.expr_size: Determine the size of the value of an expression T + in a language-specific way. Returns a tree for the size in bytes. */ + + tree + lhd_expr_size (exp) + tree exp; + { + if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd' + && DECL_SIZE_UNIT (exp) != 0) + return DECL_SIZE_UNIT (exp); + else + return size_in_bytes (TREE_TYPE (exp)); + } *** ./langhooks.h.~1~ Wed Jul 24 17:17:16 2002 --- ./langhooks.h Fri Aug 2 10:22:58 2002 *************** struct lang_hooks *** 328,333 **** --- 328,339 ---- void (*print_error_function) PARAMS ((struct diagnostic_context *, const char *)); + /* Called from expr_size to calculate the size of the value of an + expression in a language-dependent way. Returns a tree for the size + in bytes. A frontend can call lhd_expr_size to get the default + semantics in cases that it doesn't want to handle specially. */ + tree (*expr_size) PARAMS ((tree)); + /* Pointers to machine-independent attribute tables, for front ends using attribs.c. If one is NULL, it is ignored. Respectively, a table of attributes specific to the language, a table of