langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro.
* 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. * expr.c (store_expr): Don't copy an expression of size zero. (expand_expr) [CONSTRUCTOR]: Use expr_size to calculate how much to store. * Makefile.in (builtins.o): Depend on langhooks.h. * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define. (cp_expr_size): New fn. * call.c (build_over_call): Lose empty class hackery. (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: r55983
This commit is contained in:
parent
367aa58580
commit
a77a9a18c0
11 changed files with 86 additions and 46 deletions
|
@ -1,3 +1,14 @@
|
|||
2002-08-02 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* 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.
|
||||
* expr.c (store_expr): Don't copy an expression of size zero.
|
||||
(expand_expr) [CONSTRUCTOR]: Use expr_size to calculate how much
|
||||
to store.
|
||||
* Makefile.in (builtins.o): Depend on langhooks.h.
|
||||
|
||||
2002-08-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* Makefile.in (ra-debug.o): Depend on $(TM_P_H).
|
||||
|
|
|
@ -1427,7 +1427,7 @@ expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
|
|||
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
|
||||
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)
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
2002-08-02 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
|
||||
(cp_expr_size): New fn.
|
||||
* call.c (build_over_call): Lose empty class hackery.
|
||||
(convert_arg_to_ellipsis): Promote non-POD warning to error.
|
||||
* typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
|
||||
|
||||
* semantics.c (expand_body): Do tree optimization in the function
|
||||
context, too.
|
||||
|
||||
|
|
|
@ -4111,9 +4111,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;
|
||||
|
@ -4436,15 +4439,8 @@ build_over_call (cand, args, flags)
|
|||
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))))
|
||||
else if (!real_lvalue_p (arg)
|
||||
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
|
||||
{
|
||||
tree address;
|
||||
tree to = stabilize_reference
|
||||
|
@ -4466,24 +4462,7 @@ build_over_call (cand, args, flags)
|
|||
(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);
|
||||
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
|
|||
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++"
|
||||
|
@ -133,6 +134,8 @@ static bool cxx_warn_unused_global_decl 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
|
||||
|
||||
#undef LANG_HOOKS_MAKE_TYPE
|
||||
#define LANG_HOOKS_MAKE_TYPE cxx_make_type
|
||||
|
@ -280,3 +283,28 @@ cxx_warn_unused_global_decl (decl)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -5077,8 +5077,9 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||
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 = save_expr (rhs);
|
||||
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. */
|
||||
|
@ -5098,10 +5099,7 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||
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);
|
||||
return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
|
||||
}
|
||||
|
||||
case OFFSET_REF:
|
||||
|
|
10
gcc/explow.c
10
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,13 @@ 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 copy of X in which all memory references
|
||||
|
|
|
@ -4241,6 +4241,8 @@ store_expr (exp, target, want_value)
|
|||
|| (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
|
||||
|
@ -6810,8 +6812,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, INTVAL (expr_size (exp)));
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ extern void lhd_set_decl_assembler_name PARAMS ((tree));
|
|||
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 *,
|
||||
|
@ -109,6 +110,7 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
|
|||
#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
|
||||
|
@ -247,6 +249,7 @@ int lhd_tree_dump_type_quals PARAMS ((tree));
|
|||
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, \
|
||||
|
|
|
@ -421,3 +421,17 @@ 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));
|
||||
}
|
||||
|
|
|
@ -328,6 +328,12 @@ struct lang_hooks
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue