As promised, this patch improves column info for function arguments. It does so by creating a vec<location_t>, that carries locations of function arguments, which is filled when parsing expression list and then this vec is passed down to build_function_call_vec -> convert_arguments. convert_arguments loops over function arguments and uses locations from the vec (it's not done for all functions, some __atomic_* functions have "hidden" arguments and the column info would be bogus).
Another change is that, in the C FE, the locus of a function now points to its name, not opening (. (For C++, the call locus points to closing paren, which is a pain for multi-line arguments. I'll address that in another patch.) Regtested/bootstrapped on x86_64-linux, ok for trunk? 2014-01-30 Marek Polacek <pola...@redhat.com> PR c/59963 c-family/ * c-common.c (add_atomic_size_parameter): Pass vNULL to build_function_call_vec. (resolve_overloaded_builtin): Likewise. * c-common.h (build_function_call_vec): Adjust declaration. cp/ * typeck.c (build_function_call_vec): Add dummy arg_loc parameter. c/ * c-typeck.c (convert_lvalue_to_rvalue): Pass vNULL to build_function_call_vec. (build_function_call): Likewise. (build_atomic_assign): Likewise. (build_function_call_vec): Add arg_loc parameter. Use it. (convert_arguments): Likewise. (convert_for_assignment): Rename rhs_loc to expr_loc. * c-parser.c (c_parser_attributes): Pass NULL to c_parser_expr_list. (c_parser_objc_keywordexpr): Likewise. (c_parser_postfix_expression_after_primary): Call build_function_call_vec with expr_loc rather than op_loc. Call c_parser_expr_list to fill arg_loc. Pass arg_loc to build_function_call_vec. (c_parser_expr_list): Add locations parameter. Fill it with locations of function arguments. * c-decl.c (finish_decl): Pass vNULL to build_function_call_vec. objc/ * objc-next-runtime-abi-02.c (build_throw_stmt): Pass vNULL to build_function_call_vec. (finish_catch): Likewise. (next_runtime_abi_02_get_class_reference): Likewise. * objc-next-runtime-abi-01.c (build_objc_method_call): Pass vNULL to build_function_call_vec. (build_throw_stmt): Likewise. * objc-gnu-runtime-abi-01.c: (build_objc_method_call): Pass vNULL to build_function_call_vec. (build_throw_stmt): Likewise. testsuite/ * gcc.dg/pr59940.c (g): Adjust dg-warning. (y): Adjust dg-error. * gcc.dg/cast-function-1.c (bar): Adjust dg-warnings. * gcc.dg/pr59963-1.c: New test. * gcc.dg/pr59963-2.c: New test. * gcc.dg/pr59963-3.c: New test. --- gcc/c-family/c-common.h.mp 2014-01-30 20:41:46.634693874 +0100 +++ gcc/c-family/c-common.h 2014-01-30 20:41:50.873710404 +0100 @@ -911,8 +911,8 @@ extern void c_do_switch_warnings (splay_ extern tree build_function_call (location_t, tree, tree); -extern tree build_function_call_vec (location_t, tree, vec<tree, va_gc> *, - vec<tree, va_gc> *); +extern tree build_function_call_vec (location_t, vec<location_t>, tree, + vec<tree, va_gc> *, vec<tree, va_gc> *); extern tree resolve_overloaded_builtin (location_t, tree, vec<tree, va_gc> *); --- gcc/c-family/c-common.c.mp 2014-01-30 20:41:46.628693844 +0100 +++ gcc/c-family/c-common.c 2014-01-30 20:41:50.871710394 +0100 @@ -10382,7 +10382,7 @@ add_atomic_size_parameter (unsigned n, l vec_alloc (v, len + 1); for (z = 0; z < len; z++) v->quick_push ((*params)[z]); - f = build_function_call_vec (loc, function, v, NULL); + f = build_function_call_vec (loc, vNULL, function, v, NULL); vec_free (v); return f; } @@ -10813,7 +10813,8 @@ resolve_overloaded_builtin (location_t l return error_mark_node; first_param = (*params)[0]; - result = build_function_call_vec (loc, new_function, params, NULL); + result = build_function_call_vec (loc, vNULL, new_function, params, + NULL); if (result == error_mark_node) return result; if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N --- gcc/cp/typeck.c.mp 2014-01-30 20:41:46.646693930 +0100 +++ gcc/cp/typeck.c 2014-01-30 20:41:50.908710567 +0100 @@ -3357,7 +3357,7 @@ build_function_call (location_t /*loc*/, /* Used by the C-common bits. */ tree -build_function_call_vec (location_t /*loc*/, +build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/, tree function, vec<tree, va_gc> *params, vec<tree, va_gc> * /*origtypes*/) { --- gcc/objc/objc-next-runtime-abi-02.c.mp 2014-01-30 20:58:16.966442491 +0100 +++ gcc/objc/objc-next-runtime-abi-02.c 2014-01-30 20:59:29.848724052 +0100 @@ -1088,7 +1088,8 @@ next_runtime_abi_02_get_class_reference t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1, IDENTIFIER_POINTER (ident)); v->quick_push (t); - t = build_function_call_vec (input_location, objc_get_class_decl, v, 0); + t = build_function_call_vec (input_location, vNULL, objc_get_class_decl, + v, 0); vec_free (v); return t; } @@ -3622,14 +3623,16 @@ build_throw_stmt (location_t loc, tree t tree t; if (rethrown) /* We have a separate re-throw entry. */ - t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL); + t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl, + NULL, NULL); else { /* Throw like the others... */ vec<tree, va_gc> *parms; vec_alloc (parms, 1); parms->quick_push (throw_expr); - t = build_function_call_vec (loc, objc_exception_throw_decl, parms, 0); + t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, + parms, 0); vec_free (parms); } return add_stmt (t); @@ -3708,7 +3711,8 @@ finish_catch (struct objc_try_context ** /* Pick up the new context we made in begin_try above... */ ct = *cur_try_context; - func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL); + func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL, + NULL); append_to_statement_list (func, &ct->finally_body); try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body); *cur_try_context = ct->outer; --- gcc/objc/objc-next-runtime-abi-01.c.mp 2014-01-30 20:58:16.967442495 +0100 +++ gcc/objc/objc-next-runtime-abi-01.c 2014-01-30 21:00:00.952844613 +0100 @@ -882,7 +882,7 @@ build_objc_method_call (location_t loc, /* Build an obj_type_ref, with the correct cast for the method call. */ t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node); - t = build_function_call_vec (loc, t, parms, NULL); + t = build_function_call_vec (loc, vNULL, t, parms, NULL); vec_free (parms); return t; } @@ -2866,7 +2866,8 @@ build_throw_stmt (location_t loc, tree t /* A throw is just a call to the runtime throw function with the object as a parameter. */ parms->quick_push (throw_expr); - t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL); + t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms, + NULL); vec_free (parms); return add_stmt (t); } --- gcc/objc/objc-gnu-runtime-abi-01.c.mp 2014-01-30 20:58:16.969442505 +0100 +++ gcc/objc/objc-gnu-runtime-abi-01.c 2014-01-30 21:00:29.327967618 +0100 @@ -700,7 +700,7 @@ build_objc_method_call (location_t loc, then cast the pointer, then call it with the method arguments. */ tv->quick_push (lookup_object); tv->quick_push (selector); - method = build_function_call_vec (loc, sender, tv, NULL); + method = build_function_call_vec (loc, vNULL, sender, tv, NULL); vec_free (tv); /* Pass the appropriate object to the method. */ @@ -715,7 +715,7 @@ build_objc_method_call (location_t loc, /* Build an obj_type_ref, with the correct cast for the method call. */ t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node); - t = build_function_call_vec (loc, t, parms, NULL); + t = build_function_call_vec (loc, vNULL, t, parms, NULL); vec_free (parms); return t; } @@ -2213,7 +2213,8 @@ build_throw_stmt (location_t loc, tree t /* A throw is just a call to the runtime throw function with the object as a parameter. */ parms->quick_push (throw_expr); - t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL); + t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms, + NULL); vec_free (parms); return add_stmt (t); } --- gcc/c/c-typeck.c.mp 2014-01-30 20:41:46.644693920 +0100 +++ gcc/c/c-typeck.c 2014-01-30 22:53:07.736771769 +0100 @@ -89,8 +89,9 @@ static int function_types_compatible_p ( bool *); static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *); static tree lookup_field (tree, tree); -static int convert_arguments (location_t, tree, vec<tree, va_gc> *, - vec<tree, va_gc> *, tree, tree); +static int convert_arguments (location_t, vec<location_t>, tree, + vec<tree, va_gc> *, vec<tree, va_gc> *, tree, + tree); static tree pointer_diff (location_t, tree, tree); static tree convert_for_assignment (location_t, location_t, tree, tree, tree, enum impl_conv, bool, tree, tree, int); @@ -2014,7 +2015,7 @@ convert_lvalue_to_rvalue (location_t loc params->quick_push (expr_addr); params->quick_push (tmp_addr); params->quick_push (seq_cst); - func_call = build_function_call_vec (loc, fndecl, params, NULL); + func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL); /* Return tmp which contains the value loaded. */ exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp); @@ -2796,7 +2797,7 @@ build_function_call (location_t loc, tre vec_alloc (v, list_length (params)); for (; params; params = TREE_CHAIN (params)) v->quick_push (TREE_VALUE (params)); - ret = build_function_call_vec (loc, function, v, NULL); + ret = build_function_call_vec (loc, vNULL, function, v, NULL); vec_free (v); return ret; } @@ -2818,8 +2819,8 @@ static void inform_declaration (tree dec PARAMS. */ tree -build_function_call_vec (location_t loc, tree function, - vec<tree, va_gc> *params, +build_function_call_vec (location_t loc, vec<location_t> arg_loc, + tree function, vec<tree, va_gc> *params, vec<tree, va_gc> *origtypes) { tree fntype, fundecl = 0; @@ -2901,8 +2902,8 @@ build_function_call_vec (location_t loc, /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ - nargs = convert_arguments (loc, TYPE_ARG_TYPES (fntype), params, origtypes, - function, fundecl); + nargs = convert_arguments (loc, arg_loc, TYPE_ARG_TYPES (fntype), params, + origtypes, function, fundecl); if (nargs < 0) return error_mark_node; @@ -2981,19 +2982,22 @@ build_function_call_vec (location_t loc, This is also where warnings about wrong number of args are generated. + ARG_LOC are locations of function arguments (if any). + Returns the actual number of arguments processed (which may be less than the length of VALUES in some error situations), or -1 on failure. */ static int -convert_arguments (location_t loc, tree typelist, vec<tree, va_gc> *values, - vec<tree, va_gc> *origtypes, tree function, tree fundecl) +convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist, + vec<tree, va_gc> *values, vec<tree, va_gc> *origtypes, + tree function, tree fundecl) { tree typetail, val; unsigned int parmnum; bool error_args = false; const bool type_generic = fundecl - && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl))); + && lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl))); bool type_generic_remove_excess_precision = false; tree selector; @@ -3228,7 +3232,13 @@ convert_arguments (location_t loc, tree if (excess_precision) val = build1 (EXCESS_PRECISION_EXPR, valtype, val); origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum]; - parmval = convert_for_assignment (loc, UNKNOWN_LOCATION, type, + bool arg_loc_ok = !arg_loc.is_empty () + /* Some __atomic_* builtins have additional + hidden argument at position 0. */ + && values->length () == arg_loc.length (); + parmval = convert_for_assignment (loc, + arg_loc_ok ? arg_loc[parmnum] + : UNKNOWN_LOCATION, type, val, origtype, ic_argpass, npc, fundecl, function, parmnum + 1); @@ -3252,7 +3262,7 @@ convert_arguments (location_t loc, tree { /* Convert `float' to `double'. */ if (warn_double_promotion && !c_inhibit_evaluation_warnings) - warning (OPT_Wdouble_promotion, + warning_at (arg_loc[parmnum], OPT_Wdouble_promotion, "implicit conversion from %qT to %qT when passing " "argument to function", valtype, double_type_node); @@ -3619,7 +3629,7 @@ build_atomic_assign (location_t loc, tre params->quick_push (lhs_addr); params->quick_push (rhs); params->quick_push (seq_cst); - func_call = build_function_call_vec (loc, fndecl, params, NULL); + func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL); add_stmt (func_call); /* Finish the compound statement. */ @@ -3650,7 +3660,7 @@ build_atomic_assign (location_t loc, tre params->quick_push (lhs_addr); params->quick_push (old_addr); params->quick_push (seq_cst); - func_call = build_function_call_vec (loc, fndecl, params, NULL); + func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL); add_stmt (func_call); params->truncate (0); @@ -3689,7 +3699,7 @@ build_atomic_assign (location_t loc, tre params->quick_push (integer_zero_node); params->quick_push (seq_cst); params->quick_push (seq_cst); - func_call = build_function_call_vec (loc, fndecl, params, NULL); + func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL); goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl); SET_EXPR_LOCATION (goto_stmt, loc); @@ -5519,13 +5529,13 @@ convert_to_anonymous_field (location_t l ERRTYPE says whether it is argument passing, assignment, initialization or return. - LOCATION is the location of the assignment, RHS_LOC is the location of - the RHS. + LOCATION is the location of the assignment, EXPR_LOC is the location of + the RHS or, for a function, location of an argument. FUNCTION is a tree for the function being called. PARMNUM is the number of the argument, for printing in error messages. */ static tree -convert_for_assignment (location_t location, location_t rhs_loc, tree type, +convert_for_assignment (location_t location, location_t expr_loc, tree type, tree rhs, tree origtype, enum impl_conv errtype, bool null_pointer_constant, tree fundecl, tree function, int parmnum) @@ -5698,7 +5708,7 @@ convert_for_assignment (location_t locat rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs); SET_EXPR_LOCATION (rhs, location); - rhs = convert_for_assignment (location, rhs_loc, + rhs = convert_for_assignment (location, expr_loc, build_pointer_type (TREE_TYPE (type)), rhs, origtype, errtype, null_pointer_constant, fundecl, function, @@ -5728,8 +5738,8 @@ convert_for_assignment (location_t locat bool save = in_late_binary_op; if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) in_late_binary_op = true; - ret = convert_and_check (rhs_loc != UNKNOWN_LOCATION - ? rhs_loc : location, type, orig_rhs); + ret = convert_and_check (expr_loc != UNKNOWN_LOCATION + ? expr_loc : location, type, orig_rhs); if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) in_late_binary_op = save; return ret; @@ -5739,8 +5749,8 @@ convert_for_assignment (location_t locat if ((codel == RECORD_TYPE || codel == UNION_TYPE) && codel == coder && comptypes (type, rhstype)) - return convert_and_check (rhs_loc != UNKNOWN_LOCATION - ? rhs_loc : location, type, rhs); + return convert_and_check (expr_loc != UNKNOWN_LOCATION + ? expr_loc : location, type, rhs); /* Conversion to a transparent union or record from its member types. This applies only to function arguments. */ --- gcc/c/c-parser.c.mp 2014-01-30 20:41:46.641693905 +0100 +++ gcc/c/c-parser.c 2014-01-30 20:41:50.889710480 +0100 @@ -1203,7 +1203,7 @@ static struct c_expr c_parser_expression static struct c_expr c_parser_expression_conv (c_parser *); static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool, vec<tree, va_gc> **, location_t *, - tree *); + tree *, vec<location_t> *); static void c_parser_omp_construct (c_parser *); static void c_parser_omp_threadprivate (c_parser *); static void c_parser_omp_barrier (c_parser *); @@ -3958,7 +3958,7 @@ c_parser_attributes (c_parser *parser) tree tree_list; c_parser_consume_token (parser); expr_list = c_parser_expr_list (parser, false, true, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); tree_list = build_tree_list_vec (expr_list); attr_args = tree_cons (NULL_TREE, arg1, tree_list); release_tree_vector (expr_list); @@ -3971,7 +3971,7 @@ c_parser_attributes (c_parser *parser) else { expr_list = c_parser_expr_list (parser, false, true, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); attr_args = build_tree_list_vec (expr_list); release_tree_vector (expr_list); } @@ -7637,6 +7637,8 @@ c_parser_postfix_expression_after_primar unsigned int i; vec<tree, va_gc> *exprlist; vec<tree, va_gc> *origtypes = NULL; + vec<location_t> arg_loc = vNULL; + while (true) { location_t op_loc = c_parser_peek_token (parser)->location; @@ -7690,7 +7692,8 @@ c_parser_postfix_expression_after_primar exprlist = NULL; else exprlist = c_parser_expr_list (parser, true, false, &origtypes, - sizeof_arg_loc, sizeof_arg); + sizeof_arg_loc, sizeof_arg, + &arg_loc); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); orig_expr = expr; @@ -7700,10 +7703,8 @@ c_parser_postfix_expression_after_primar expr.value, exprlist, sizeof_arg, sizeof_ptr_memacc_comptypes); - /* FIXME diagnostics: Ideally we want the FUNCNAME, not the - "(" after the FUNCNAME, which is what we have now. */ - expr.value = build_function_call_vec (op_loc, expr.value, exprlist, - origtypes); + expr.value = build_function_call_vec (expr_loc, arg_loc, expr.value, + exprlist, origtypes); expr.original_code = ERROR_MARK; if (TREE_CODE (expr.value) == INTEGER_CST && TREE_CODE (orig_expr.value) == FUNCTION_DECL @@ -7716,6 +7717,7 @@ c_parser_postfix_expression_after_primar release_tree_vector (exprlist); release_tree_vector (origtypes); } + arg_loc.release (); break; case CPP_DOT: /* Structure element reference. */ @@ -7869,7 +7871,8 @@ c_parser_expression_conv (c_parser *pars /* Parse a non-empty list of expressions. If CONVERT_P, convert functions and arrays to pointers and lvalues to rvalues. If - FOLD_P, fold the expressions. + FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the + locations of function arguments into this vector. nonempty-expr-list: assignment-expression @@ -7879,7 +7882,8 @@ c_parser_expression_conv (c_parser *pars static vec<tree, va_gc> * c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, vec<tree, va_gc> **p_orig_types, - location_t *sizeof_arg_loc, tree *sizeof_arg) + location_t *sizeof_arg_loc, tree *sizeof_arg, + vec<location_t> *locations) { vec<tree, va_gc> *ret; vec<tree, va_gc> *orig_types; @@ -7905,6 +7909,8 @@ c_parser_expr_list (c_parser *parser, bo ret->quick_push (expr.value); if (orig_types) orig_types->quick_push (expr.original_type); + if (locations) + locations->safe_push (loc); if (sizeof_arg != NULL && cur_sizeof_arg_loc != UNKNOWN_LOCATION && expr.original_code == SIZEOF_EXPR) @@ -7929,6 +7935,8 @@ c_parser_expr_list (c_parser *parser, bo vec_safe_push (ret, expr.value); if (orig_types) vec_safe_push (orig_types, expr.original_type); + if (locations) + locations->safe_push (loc); if (++idx < 3 && sizeof_arg != NULL && cur_sizeof_arg_loc != UNKNOWN_LOCATION @@ -9026,7 +9034,7 @@ c_parser_objc_keywordexpr (c_parser *par { tree ret; vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (vec_safe_length (expr_list) == 1) { /* Just return the expression, remove a level of --- gcc/c/c-decl.c.mp 2014-01-30 20:41:46.637693886 +0100 +++ gcc/c/c-decl.c 2014-01-30 20:41:50.878710426 +0100 @@ -4569,7 +4569,7 @@ finish_decl (tree decl, location_t init_ vec_alloc (v, 1); v->quick_push (cleanup); cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl), - cleanup_decl, v, NULL); + vNULL, cleanup_decl, v, NULL); vec_free (v); /* Don't warn about decl unused; the cleanup uses it. */ --- gcc/testsuite/gcc.dg/pr59940.c.mp 2014-01-30 20:41:46.650693948 +0100 +++ gcc/testsuite/gcc.dg/pr59940.c 2014-01-30 20:41:50.911710582 +0100 @@ -15,13 +15,13 @@ g (void) si = 3.2f; /* { dg-warning "8:conversion" } */ uc = 256; /* { dg-warning "8:large integer implicitly truncated to unsigned type" } */ si = 0x800000000; /* { dg-warning "8:overflow in implicit constant conversion" } */ - return f (si) /* { dg-warning "12:conversion" } */ - + f (si); /* { dg-warning "14:conversion" } */ + return f (si) /* { dg-warning "13:conversion" } */ + + f (si); /* { dg-warning "15:conversion" } */ } int y (void) { - f (); /* { dg-error "5:too few arguments to function" } */ - g (0xa); /* { dg-error "5:too many arguments to function" } */ + f (); /* { dg-error "3:too few arguments to function" } */ + g (0xa); /* { dg-error "3:too many arguments to function" } */ } --- gcc/testsuite/gcc.dg/pr59963-1.c.mp 2014-01-30 20:42:34.000000000 +0100 +++ gcc/testsuite/gcc.dg/pr59963-1.c 2014-01-30 19:26:50.000000000 +0100 @@ -0,0 +1,14 @@ +/* PR c/59963 */ +/* { dg-do compile } */ +/* { dg-options "-Wdouble-promotion" } */ + +extern void baz (); +extern void qux (int, ...); + +void +foo (float f) +{ + bar (f); /* { dg-warning "8:implicit conversion" } */ + baz (f); /* { dg-warning "8:implicit conversion" } */ + qux (42, f); /* { dg-warning "12:implicit conversion" } */ +} --- gcc/testsuite/gcc.dg/cast-function-1.c.mp 2014-01-30 21:50:13.989673987 +0100 +++ gcc/testsuite/gcc.dg/cast-function-1.c 2014-01-30 21:50:46.752810004 +0100 @@ -18,14 +18,14 @@ typedef struct { void bar(double d, int i, str_t s) { - d = ((double (*) (int)) foo1) (i); /* { dg-warning "33:non-compatible|abort" } */ - i = ((int (*) (double)) foo1) (d); /* { dg-warning "33:non-compatible|abort" } */ - s = ((str_t (*) (int)) foo1) (i); /* { dg-warning "32:non-compatible|abort" } */ + d = ((double (*) (int)) foo1) (i); /* { dg-warning "7:non-compatible|abort" } */ + i = ((int (*) (double)) foo1) (d); /* { dg-warning "7:non-compatible|abort" } */ + s = ((str_t (*) (int)) foo1) (i); /* { dg-warning "7:non-compatible|abort" } */ ((void (*) (int)) foo1) (d); /* { dg-warning "non-compatible|abort" } */ i = ((int (*) (int)) foo1) (i); /* { dg-bogus "non-compatible|abort" } */ (void) foo1 (i); /* { dg-bogus "non-compatible|abort" } */ - d = ((double (*) (int)) foo2) (i); /* { dg-warning "33:non-compatible|abort" } */ + d = ((double (*) (int)) foo2) (i); /* { dg-warning "7:non-compatible|abort" } */ i = ((int (*) (double)) foo2) (d); /* { dg-bogus "non-compatible|abort" } */ s = ((str_t (*) (int)) foo2) (i); /* { dg-warning "non-compatible|abort" } */ ((void (*) (int)) foo2) (d); /* { dg-warning "non-compatible|abort" } */ --- gcc/testsuite/gcc.dg/pr59963-2.c.mp 2014-01-30 20:42:41.000000000 +0100 +++ gcc/testsuite/gcc.dg/pr59963-2.c 2014-01-30 20:32:38.000000000 +0100 @@ -0,0 +1,36 @@ +/* PR c/59963 */ +/* { dg-do compile } */ +/* { dg-options "-Woverflow -Wconversion" } */ + +extern void bar (unsigned char); +extern void bar8 (unsigned char, unsigned char, unsigned char, unsigned char, + unsigned char, unsigned char, unsigned char, unsigned char); +extern void bazu (unsigned int, ...); +extern void bazi (char, int); +extern int f (short a, short b); + +int +g (void) +{ + return f (0xffffffffL, /* { dg-warning "13:overflow in implicit constant conversion" } */ + 0xffffffffL) /* { dg-warning "13:overflow in implicit constant conversion" } */ + && f (0xffffffffL, /* { dg-warning "9:overflow in implicit constant conversion" } */ + 0xffffffffL); /* { dg-warning "9:overflow in implicit constant conversion" } */ +} + +void +foo (int i) +{ + bar (256); /* { dg-warning "8:large integer implicitly truncated to unsigned type" } */ + bar (6.66f); /* { dg-warning "8:conversion" } */ + bar8 (-1, /* { dg-warning "9:negative integer implicitly converted to unsigned type" } */ + -2, /* { dg-warning "3:negative integer implicitly converted to unsigned type" } */ + -3, /* { dg-warning "4:negative integer implicitly converted to unsigned type" } */ + -4, /* { dg-warning "5:negative integer implicitly converted to unsigned type" } */ + -5, /* { dg-warning "6:negative integer implicitly converted to unsigned type" } */ + -6, /* { dg-warning "7:negative integer implicitly converted to unsigned type" } */ + -7, /* { dg-warning "8:negative integer implicitly converted to unsigned type" } */ + -8); /* { dg-warning "9:negative integer implicitly converted to unsigned type" } */ + bazu (i, i); /* { dg-warning "9:conversion" } */ + bazi (0x8, 0x80000000); /* { dg-warning "14:conversion of unsigned constant value to negative integer" } */ +} --- gcc/testsuite/gcc.dg/pr59963-3.c.mp 2014-01-30 20:42:46.000000000 +0100 +++ gcc/testsuite/gcc.dg/pr59963-3.c 2014-01-30 19:05:56.000000000 +0100 @@ -0,0 +1,14 @@ +/* PR c/59963 */ +/* { dg-do compile } */ +/* { dg-options "-Wconversion" } */ + +extern void foo (void *p); + +void +bar (void) +{ + { + /* This must not ICE. */ + int i __attribute__((cleanup (foo))); + } +} Marek