From a6f86b51673a67a9a8f4c1d5232aa9fe81962170 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 8 Dec 2003 23:08:50 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 12 +++++++++++ gcc/cp/call.c | 54 ++++++++++++++++++++++++++++++++++++++---------- gcc/cp/cp-tree.h | 1 + gcc/cp/ptree.c | 2 ++ gcc/cp/tree.c | 38 ++++++++++++++++++++++++---------- 5 files changed, 85 insertions(+), 22 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 63c8ce776cd..4b3b74ad257 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2003-12-08 Jason Merrill + 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 yesterday. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 354eb8bb71a..16482ddf9f8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -104,11 +104,12 @@ static tree direct_reference_binding (tree, tree); static bool promoted_arithmetic_type_p (tree); static tree conditional_conversion (tree, tree); 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 void add_candidates (tree, tree, tree, bool, tree, tree, int, struct z_candidate **); static tree merge_conversion_sequences (tree, tree); +static bool magic_varargs_p (tree); tree build_vfield_ref (tree datum, tree type) @@ -4191,16 +4192,18 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner, 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 -call_builtin_trap (void) +call_builtin_trap (tree type) { tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap")); my_friendly_assert (fn != NULL, 20030927); 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; } @@ -4239,7 +4242,7 @@ convert_arg_to_ellipsis (tree arg) warning ("cannot pass objects of non-POD type `%#T' through `...'; \ call will abort at runtime", TREE_TYPE (arg)); - arg = call_builtin_trap (); + arg = call_builtin_trap (TREE_TYPE (arg)); } return arg; @@ -4261,8 +4264,10 @@ build_x_va_arg (tree expr, tree type) if (! pod_type_p (type)) { /* Undefined behavior [expr.call] 5.2.2/7. */ - warning ("cannot receive objects of non-POD type `%#T' through `...'", - type); + warning ("cannot receive objects of non-POD type `%#T' through `...'; \ +call will abort at runtime", + type); + return call_builtin_trap (type); } return build_va_arg (expr, type); @@ -4368,6 +4373,29 @@ convert_for_arg_passing (tree type, tree 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 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 @@ -4517,10 +4545,14 @@ build_over_call (struct z_candidate *cand, int flags) /* Ellipsis */ for (; arg; arg = TREE_CHAIN (arg)) - converted_args - = tree_cons (NULL_TREE, - convert_arg_to_ellipsis (TREE_VALUE (arg)), - converted_args); + { + tree a = TREE_VALUE (arg); + if (magic_varargs_p (fn)) + /* 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b1a434e0b0e..a16a4858faa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3692,6 +3692,7 @@ extern int walk_namespaces (walk_namespaces_fn, extern int wrapup_globals_for_namespace (tree, void *); extern tree create_implicit_typedef (tree, tree); extern tree maybe_push_decl (tree); +extern tree force_target_expr (tree, tree); extern tree build_target_expr_with_type (tree, tree); extern int local_variable_p (tree); extern int nonstatic_local_decl_p (tree); diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 6dbf0605a48..7979504e3fd 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -150,8 +150,10 @@ cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix) void cxx_print_identifier (FILE *file, tree node, int indent) { + indent_to (file, indent); cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings"); print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4); + indent_to (file, indent); cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings"); print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c14289d0d90..79d3736ff33 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -49,6 +49,7 @@ static tree build_target_expr (tree, tree); static tree count_trees_r (tree *, int *, void *); static tree verify_stmt_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_com_interface_attribute (tree *, tree, tree, int, bool *); @@ -242,6 +243,19 @@ build_target_expr (tree decl, tree value) 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. TYPE is the type that this initialization should appear to have. @@ -269,10 +283,7 @@ build_cplus_new (tree type, tree init) && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); - slot = build_decl (VAR_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (slot) = 1; - DECL_CONTEXT (slot) = current_function_decl; - layout_decl (slot, 0); + slot = build_local_temp (type); /* We split the CALL_EXPR into its function and its arguments here. Then, in expand_expr, we put them back together. The reason for @@ -306,7 +317,6 @@ tree build_target_expr_with_type (tree init, tree type) { tree slot; - tree rval; if (TREE_CODE (init) == TARGET_EXPR) return init; @@ -321,13 +331,19 @@ build_target_expr_with_type (tree init, tree type) aggregate; there's no additional work to be done. */ return force_rvalue (init); - slot = build_decl (VAR_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (slot) = 1; - DECL_CONTEXT (slot) = current_function_decl; - layout_decl (slot, 0); - rval = build_target_expr (slot, init); + slot = build_local_temp (type); + return 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. */ -- 2.30.2