Commit a6f86b51 by Jason Merrill Committed by Jason Merrill

re PR c++/11971 (ICE in cp_expr_size with variadic function call)

        PR c++/11971
        * tree.c (build_local_temp): Split out from build_cplus_new.
        (force_target_expr): New fn.
        * call.c (call_builtin_trap): Call it.  Take a type parm.
        (convert_arg_to_ellipsis): Pass it.
        (build_x_va_arg): Use call_builtin_trap.

        PR c++/11929
        * call.c (magic_varargs_p): New fn.
        (build_over_call): Do no ellipsis conversions for arguments to
        functions with magic varargs.

From-SVN: r74462
parent 0b24b248
2003-12-08 Jason Merrill <jason@redhat.com> 2003-12-08 Jason Merrill <jason@redhat.com>
PR c++/11971
* tree.c (build_local_temp): Split out from build_cplus_new.
(force_target_expr): New fn.
* call.c (call_builtin_trap): Call it. Take a type parm.
(convert_arg_to_ellipsis): Pass it.
(build_x_va_arg): Use call_builtin_trap.
PR c++/11929
* call.c (magic_varargs_p): New fn.
(build_over_call): Do no ellipsis conversions for arguments to
functions with magic varargs.
* name-lookup.c, init.c, except.c: Revert Giovanni's patch from * name-lookup.c, init.c, except.c: Revert Giovanni's patch from
yesterday. yesterday.
......
...@@ -104,11 +104,12 @@ static tree direct_reference_binding (tree, tree); ...@@ -104,11 +104,12 @@ static tree direct_reference_binding (tree, tree);
static bool promoted_arithmetic_type_p (tree); static bool promoted_arithmetic_type_p (tree);
static tree conditional_conversion (tree, tree); static tree conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *); static char *name_as_c_string (tree, tree, bool *);
static tree call_builtin_trap (void); static tree call_builtin_trap (tree);
static tree prep_operand (tree); static tree prep_operand (tree);
static void add_candidates (tree, tree, tree, bool, tree, tree, static void add_candidates (tree, tree, tree, bool, tree, tree,
int, struct z_candidate **); int, struct z_candidate **);
static tree merge_conversion_sequences (tree, tree); static tree merge_conversion_sequences (tree, tree);
static bool magic_varargs_p (tree);
tree tree
build_vfield_ref (tree datum, tree type) build_vfield_ref (tree datum, tree type)
...@@ -4191,16 +4192,18 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner, ...@@ -4191,16 +4192,18 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
} }
/* Build a call to __builtin_trap which can be used in an expression. */ /* Build a call to __builtin_trap which can be used as an expression of
type TYPE. */
static tree static tree
call_builtin_trap (void) call_builtin_trap (tree type)
{ {
tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap")); tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap"));
my_friendly_assert (fn != NULL, 20030927); my_friendly_assert (fn != NULL, 20030927);
fn = build_call (fn, NULL_TREE); fn = build_call (fn, NULL_TREE);
fn = build (COMPOUND_EXPR, integer_type_node, fn, integer_zero_node); fn = build (COMPOUND_EXPR, type, fn, error_mark_node);
fn = force_target_expr (type, fn);
return fn; return fn;
} }
...@@ -4239,7 +4242,7 @@ convert_arg_to_ellipsis (tree arg) ...@@ -4239,7 +4242,7 @@ convert_arg_to_ellipsis (tree arg)
warning ("cannot pass objects of non-POD type `%#T' through `...'; \ warning ("cannot pass objects of non-POD type `%#T' through `...'; \
call will abort at runtime", call will abort at runtime",
TREE_TYPE (arg)); TREE_TYPE (arg));
arg = call_builtin_trap (); arg = call_builtin_trap (TREE_TYPE (arg));
} }
return arg; return arg;
...@@ -4261,8 +4264,10 @@ build_x_va_arg (tree expr, tree type) ...@@ -4261,8 +4264,10 @@ build_x_va_arg (tree expr, tree type)
if (! pod_type_p (type)) if (! pod_type_p (type))
{ {
/* Undefined behavior [expr.call] 5.2.2/7. */ /* Undefined behavior [expr.call] 5.2.2/7. */
warning ("cannot receive objects of non-POD type `%#T' through `...'", warning ("cannot receive objects of non-POD type `%#T' through `...'; \
type); call will abort at runtime",
type);
return call_builtin_trap (type);
} }
return build_va_arg (expr, type); return build_va_arg (expr, type);
...@@ -4368,6 +4373,29 @@ convert_for_arg_passing (tree type, tree val) ...@@ -4368,6 +4373,29 @@ convert_for_arg_passing (tree type, tree val)
return val; return val;
} }
/* Returns true iff FN is a function with magic varargs, i.e. ones for
which no conversions at all should be done. This is true for some
builtins which don't act like normal functions. */
static bool
magic_varargs_p (tree fn)
{
if (DECL_BUILT_IN (fn))
switch (DECL_FUNCTION_CODE (fn))
{
case BUILT_IN_CLASSIFY_TYPE:
case BUILT_IN_CONSTANT_P:
case BUILT_IN_NEXT_ARG:
case BUILT_IN_STDARG_START:
case BUILT_IN_VA_START:
return true;
default:;
}
return false;
}
/* Subroutine of the various build_*_call functions. Overload resolution /* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
...@@ -4517,10 +4545,14 @@ build_over_call (struct z_candidate *cand, int flags) ...@@ -4517,10 +4545,14 @@ build_over_call (struct z_candidate *cand, int flags)
/* Ellipsis */ /* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg)) for (; arg; arg = TREE_CHAIN (arg))
converted_args {
= tree_cons (NULL_TREE, tree a = TREE_VALUE (arg);
convert_arg_to_ellipsis (TREE_VALUE (arg)), if (magic_varargs_p (fn))
converted_args); /* Do no conversions for magic varargs. */;
else
a = convert_arg_to_ellipsis (a);
converted_args = tree_cons (NULL_TREE, a, converted_args);
}
converted_args = nreverse (converted_args); converted_args = nreverse (converted_args);
......
...@@ -3692,6 +3692,7 @@ extern int walk_namespaces (walk_namespaces_fn, ...@@ -3692,6 +3692,7 @@ extern int walk_namespaces (walk_namespaces_fn,
extern int wrapup_globals_for_namespace (tree, void *); extern int wrapup_globals_for_namespace (tree, void *);
extern tree create_implicit_typedef (tree, tree); extern tree create_implicit_typedef (tree, tree);
extern tree maybe_push_decl (tree); extern tree maybe_push_decl (tree);
extern tree force_target_expr (tree, tree);
extern tree build_target_expr_with_type (tree, tree); extern tree build_target_expr_with_type (tree, tree);
extern int local_variable_p (tree); extern int local_variable_p (tree);
extern int nonstatic_local_decl_p (tree); extern int nonstatic_local_decl_p (tree);
......
...@@ -150,8 +150,10 @@ cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix) ...@@ -150,8 +150,10 @@ cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix)
void void
cxx_print_identifier (FILE *file, tree node, int indent) cxx_print_identifier (FILE *file, tree node, int indent)
{ {
indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings"); cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4); print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings"); cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4); print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
......
...@@ -49,6 +49,7 @@ static tree build_target_expr (tree, tree); ...@@ -49,6 +49,7 @@ static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *); static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *); static tree verify_stmt_tree_r (tree *, int *, void *);
static tree find_tree_r (tree *, int *, void *); static tree find_tree_r (tree *, int *, void *);
static tree build_local_temp (tree);
static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *); static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *); static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
...@@ -242,6 +243,19 @@ build_target_expr (tree decl, tree value) ...@@ -242,6 +243,19 @@ build_target_expr (tree decl, tree value)
return t; return t;
} }
/* Return an undeclared local temporary of type TYPE for use in building a
TARGET_EXPR. */
static tree
build_local_temp (tree type)
{
tree slot = build_decl (VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
layout_decl (slot, 0);
return slot;
}
/* INIT is a CALL_EXPR which needs info about its target. /* INIT is a CALL_EXPR which needs info about its target.
TYPE is the type that this initialization should appear to have. TYPE is the type that this initialization should appear to have.
...@@ -269,10 +283,7 @@ build_cplus_new (tree type, tree init) ...@@ -269,10 +283,7 @@ build_cplus_new (tree type, tree init)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
slot = build_decl (VAR_DECL, NULL_TREE, type); slot = build_local_temp (type);
DECL_ARTIFICIAL (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
layout_decl (slot, 0);
/* We split the CALL_EXPR into its function and its arguments here. /* We split the CALL_EXPR into its function and its arguments here.
Then, in expand_expr, we put them back together. The reason for Then, in expand_expr, we put them back together. The reason for
...@@ -306,7 +317,6 @@ tree ...@@ -306,7 +317,6 @@ tree
build_target_expr_with_type (tree init, tree type) build_target_expr_with_type (tree init, tree type)
{ {
tree slot; tree slot;
tree rval;
if (TREE_CODE (init) == TARGET_EXPR) if (TREE_CODE (init) == TARGET_EXPR)
return init; return init;
...@@ -321,13 +331,19 @@ build_target_expr_with_type (tree init, tree type) ...@@ -321,13 +331,19 @@ build_target_expr_with_type (tree init, tree type)
aggregate; there's no additional work to be done. */ aggregate; there's no additional work to be done. */
return force_rvalue (init); return force_rvalue (init);
slot = build_decl (VAR_DECL, NULL_TREE, type); slot = build_local_temp (type);
DECL_ARTIFICIAL (slot) = 1; return build_target_expr (slot, init);
DECL_CONTEXT (slot) = current_function_decl; }
layout_decl (slot, 0);
rval = build_target_expr (slot, init);
return rval; /* Like the above function, but without the checking. This function should
only be used by code which is deliberately trying to subvert the type
system, such as call_builtin_trap. */
tree
force_target_expr (tree type, tree init)
{
tree slot = build_local_temp (type);
return build_target_expr (slot, init);
} }
/* Like build_target_expr_with_type, but use the type of INIT. */ /* Like build_target_expr_with_type, but use the type of INIT. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment