From f86edb574064219888966e382a76d8fa4bef035f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 23 Aug 2002 08:00:43 -0400 Subject: [PATCH] re PR c++/5607 (No pointer adjustment in covariant return types) * langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro. * langhooks.c (lhd_expr_size): Define default. * langhooks.h (struct lang_hooks): Add expr_size. * explow.c (expr_size): Call it. (int_expr_size): New fn. * expr.h: Declare it. * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how much to store. cp/ PR c++/5607 * search.c (check_final_overrider): No longer static. * class.c (update_vtable_entry_for_fn): Call it. * cp-tree.h: Adjust. * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define. (cp_expr_size): New fn. * call.c (convert_arg_to_ellipsis): Promote non-POD warning to error. * typeck.c (build_modify_expr): Don't use save_expr on an lvalue. From-SVN: r56539 --- gcc/ChangeLog | 11 +++++++++++ gcc/cp/ChangeLog | 12 ++++++++++++ gcc/cp/call.c | 9 ++++++--- gcc/cp/class.c | 4 ++++ gcc/cp/cp-lang.c | 30 +++++++++++++++++++++++++++++- gcc/cp/cp-tree.h | 1 + gcc/cp/search.c | 3 +-- gcc/cp/typeck.c | 5 ++++- gcc/explow.c | 28 +++++++++++++++++++++------- gcc/expr.c | 3 +-- gcc/expr.h | 4 ++++ gcc/langhooks-def.h | 3 +++ gcc/langhooks.c | 13 +++++++++++++ gcc/langhooks.h | 6 ++++++ 14 files changed, 116 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea095095199a..ba97b86d670a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2002-08-22 Jason Merrill + + * langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro. + * langhooks.c (lhd_expr_size): Define default. + * langhooks.h (struct lang_hooks): Add expr_size. + * explow.c (expr_size): Call it. + (int_expr_size): New fn. + * expr.h: Declare it. + * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how + much to store. + 2002-08-23 Alan Modra * config/rs6000/rs6000.c (output_mi_thunk): Don't determine insns diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ac16fcd2c9f6..8e84fe6f62e5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2002-08-22 Jason Merrill + + PR c++/5607 + * search.c (check_final_overrider): No longer static. + * class.c (update_vtable_entry_for_fn): Call it. + * cp-tree.h: Adjust. + + * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define. + (cp_expr_size): New fn. + * call.c (convert_arg_to_ellipsis): Promote non-POD warning to error. + * typeck.c (build_modify_expr): Don't use save_expr on an lvalue. + 2002-08-14 Release Manager * GCC 3.2 Released. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5527066a39e4..c8dcaf021189 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4022,9 +4022,12 @@ convert_arg_to_ellipsis (arg) 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)); + /* 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; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 279072669b68..f655846e060c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2454,6 +2454,10 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) if (overrider == error_mark_node) return; + /* Check for unsupported covariant returns again now that we've + calculated the base offsets. */ + check_final_overrider (TREE_PURPOSE (overrider), fn); + /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ virtual_base = NULL_TREE; diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 931523e8e012..7b1d860a08e6 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -28,7 +28,8 @@ Boston, MA 02111-1307, USA. */ #include "langhooks.h" #include "langhooks-def.h" -static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree)); +static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree)); +static tree cp_expr_size PARAMS ((tree)); #undef LANG_HOOKS_NAME #define LANG_HOOKS_NAME "GNU C++" @@ -91,6 +92,8 @@ static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree)); #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 /* Each front end provides its own hooks, for toplev.c. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -108,3 +111,28 @@ cxx_get_alias_set (t) return c_common_get_alias_set (t); } + +/* 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); +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6fe5875ada74..48b615bf8d79 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4084,6 +4084,7 @@ extern tree lookup_conversions PARAMS ((tree)); extern tree binfo_for_vtable PARAMS ((tree)); extern tree binfo_from_vbase PARAMS ((tree)); extern tree look_for_overrides_here PARAMS ((tree, tree)); +extern int check_final_overrider PARAMS ((tree, tree)); extern tree dfs_walk PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *), diff --git a/gcc/cp/search.c b/gcc/cp/search.c index ab6e25d8bb65..9821907377f7 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -100,7 +100,6 @@ 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 check_final_overrider 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 *)); @@ -1800,7 +1799,7 @@ covariant_return_p (brettype, drettype) /* Check that virtual overrider OVERRIDER is acceptable for base function BASEFN. Issue diagnostic, and return zero, if unacceptable. */ -static int +int check_final_overrider (overrider, basefn) tree overrider, basefn; { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f3ba665aa575..d32696996bfb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5450,7 +5450,10 @@ build_modify_expr (lhs, modifycode, rhs) so the code to compute it is only emitted once. */ tree cond; - rhs = save_expr (rhs); + if (lvalue_p (rhs)) + rhs = stabilize_reference (rhs); + else + rhs = save_expr (rhs); /* Check this here to avoid odd errors when trying to convert a throw to the type of the COND_EXPR. */ diff --git a/gcc/explow.c b/gcc/explow.c index 7a770ee897cf..97435a703b98 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #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)); @@ -285,20 +286,33 @@ rtx 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)); + 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 wide integer for the size in bytes of the value of EXP, or -1 + if the size can vary or is larger than an integer. */ + +HOST_WIDE_INT +int_expr_size (exp) + tree exp; +{ + tree t = (*lang_hooks.expr_size) (exp); + + if (t == 0 + || TREE_CODE (t) != INTEGER_CST + || TREE_OVERFLOW (t) + || TREE_INT_CST_HIGH (t) != 0 + /* If the result would appear negative, it's too big to represent. */ + || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0) + return -1; + return TREE_INT_CST_LOW (t); } /* Return a copy of X in which all memory references diff --git a/gcc/expr.c b/gcc/expr.c index a6ec5466c8f5..2a5c6f9b890b 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6661,8 +6661,7 @@ expand_expr (exp, target, tmode, modifier) * TYPE_QUAL_CONST))), 0, TREE_ADDRESSABLE (exp), 1); - store_constructor (exp, target, 0, - int_size_in_bytes (TREE_TYPE (exp))); + store_constructor (exp, target, 0, int_expr_size (exp)); return target; } diff --git a/gcc/expr.h b/gcc/expr.h index 91ffa3f0507d..97d734b5d307 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -548,6 +548,10 @@ extern unsigned int case_values_threshold PARAMS ((void)); /* Return an rtx for the size in bytes of the value of an expr. */ extern rtx expr_size PARAMS ((tree)); +/* Return a wide integer for the size in bytes of the value of EXP, or -1 + if the size can vary or is larger than an integer. */ +extern HOST_WIDE_INT int_expr_size PARAMS ((tree)); + extern rtx lookup_static_chain PARAMS ((tree)); /* Convert a stack slot address ADDR valid in function FNDECL diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index bb00b501cc6c..e80b798798ae 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -48,6 +48,7 @@ extern int lhd_staticp PARAMS ((tree)); extern void lhd_clear_binding_stack PARAMS ((void)); extern void lhd_print_tree_nothing PARAMS ((FILE *, tree, int)); extern void lhd_set_yydebug PARAMS ((int)); +extern tree lhd_expr_size PARAMS ((tree)); /* Declarations of default tree inlining hooks. */ tree lhd_tree_inlining_walk_subtrees PARAMS ((tree *, int *, @@ -85,6 +86,7 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree)); #define LANG_HOOKS_PRINT_TYPE lhd_print_tree_nothing #define LANG_HOOKS_PRINT_IDENTIFIER lhd_print_tree_nothing #define LANG_HOOKS_SET_YYDEBUG lhd_set_yydebug +#define LANG_HOOKS_EXPR_SIZE lhd_expr_size /* Tree inlining hooks. */ #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES lhd_tree_inlining_walk_subtrees @@ -156,6 +158,7 @@ int lhd_tree_dump_type_quals PARAMS ((tree)); LANG_HOOKS_PRINT_TYPE, \ LANG_HOOKS_PRINT_IDENTIFIER, \ LANG_HOOKS_SET_YYDEBUG, \ + LANG_HOOKS_EXPR_SIZE, \ LANG_HOOKS_TREE_INLINING_INITIALIZER, \ LANG_HOOKS_TREE_DUMP_INITIALIZER \ } diff --git a/gcc/langhooks.c b/gcc/langhooks.c index c0ee16cbcad6..e50ebc9812b5 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -303,3 +303,16 @@ lhd_tree_dump_type_quals (t) 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)); +} diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 368f47d31a55..7a3c3bd0201e 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -156,6 +156,12 @@ struct lang_hooks warning that the front end does not use such a parser. */ void (*set_yydebug) PARAMS ((int)); + /* 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)); + struct lang_hooks_for_tree_inlining tree_inlining; struct lang_hooks_for_tree_dump tree_dump; -- 2.47.2