From patchwork Sat Aug 19 00:58:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 803476 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-460605-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="X2s9BXwX"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xZ10W21Yqz9s8J for ; Sat, 19 Aug 2017 10:24:11 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=vg7U8igqQdqo /FMRibYPTtTadMQ++lsrNuJ4FgUSFoHxEqMeoTSLk6FAMTUaRde5lIdjmMmwzIUc t3WJ/6oIimrydT+OjwudkjEQwxFNmhIDEm+HgrMjmNq1kjAmVhZf4ZvdV+o+xTAi 6PxzLzFAlQ9j55ZYdCldcGabfppvPmQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=3xk92I+ACzFhVFISy4 VchJhHfhw=; b=X2s9BXwXewobKVdBgDmW+qHt5Tbf0cSyJ7/fqHyLXHrzyCzBcD USlLVzS6tsXHG3HTjCJ+XONp3y70Uc8qpk4ok3Xea6Um99nUcn0lyD31Fmd2KMUF Q1l1d5SNaaWEquvSszJuYYGkG8LuIA41zJBNgimyqYA+PT0lTKNBb5mzA= Received: (qmail 119050 invoked by alias); 19 Aug 2017 00:23:41 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 115274 invoked by uid 89); 19 Aug 2017 00:23:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=underline X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 19 Aug 2017 00:23:28 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BCFD83680C for ; Sat, 19 Aug 2017 00:23:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BCFD83680C Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from c64.redhat.com (ovpn-112-20.phx2.redhat.com [10.3.112.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id A0902619D7; Sat, 19 Aug 2017 00:23:25 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 1/2] c-family/c/c++: pass optional vec to c-format.c Date: Fri, 18 Aug 2017 20:58:43 -0400 Message-Id: <1503104324-51207-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes This patch passes along the vec of argument locations at a callsite from the C frontend to check_function_arguments and from there to c-format.c, so that we can underline the pertinent argument to mismatched format codes even for tree codes like decls and constants which lack a location_t for their usage sites. This takes e.g.: printf("hello %i %i %i ", foo, bar, baz); ~^ %s to: printf("hello %i %i %i ", foo, bar, baz); ~^ ~~~ %s which is useful for cases where there's more than one variadic argument. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. OK for trunk? gcc/c-family/ChangeLog: * c-common.c (check_function_arguments): Add "arglogs" param; pass it to check_function_format. * c-common.h (check_function_arguments): Add vec * param. (check_function_format): Likewise. * c-format.c (struct format_check_context): Add field "arglocs". (check_function_format): Add param "arglocs"; pass it to check_format_info. (check_format_info): Add param "arglocs"; use it to initialize new field of format_ctx. (check_format_arg): Pass format_ctx->arglocs to new param of check_format_info_main. (class argument_parser): New field "arglocs". (argument_parser::argument_parser): Add "arglocs_" param and use it to initialize new field. (argument_parser::check_argument_type): Pass new arglocs field to check_format_types. (check_format_info_main): Add param "arglocs", and use it when constructing arg_parser. (check_format_types): Add param "arglocs"; use it if non-NULL when !EXPR_HAS_LOCATION (cur_param) to get at location information. gcc/c/ChangeLog: * c-typeck.c (build_function_call_vec): Pass arg_loc to call to check_function_arguments. gcc/cp/ChangeLog: * call.c (build_over_call): Pass NULL for new parameter to check_function_arguments. * typeck.c (cp_build_function_call_vec): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/format/diagnostic-ranges.c: Update expected results to show underlining of all pertinent params. * gcc.dg/format/pr72858.c: Likewise. --- gcc/c-family/c-common.c | 4 +- gcc/c-family/c-common.h | 4 +- gcc/c-family/c-format.c | 52 ++++++++---- gcc/c/c-typeck.c | 2 +- gcc/cp/call.c | 2 +- gcc/cp/typeck.c | 2 +- gcc/testsuite/gcc.dg/format/diagnostic-ranges.c | 41 ++++------ gcc/testsuite/gcc.dg/format/pr72858.c | 102 +++++++++--------------- 8 files changed, 98 insertions(+), 111 deletions(-) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 4dc3b33..156c89d 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -5539,7 +5539,7 @@ attribute_fallthrough_p (tree attr) diagnostics. Return true if -Wnonnull warning has been diagnosed. */ bool check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, - int nargs, tree *argarray) + int nargs, tree *argarray, vec *arglocs) { bool warned_p = false; @@ -5553,7 +5553,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, /* Check for errors in format strings. */ if (warn_format || warn_suggest_attribute_format) - check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray); + check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray, arglocs); if (warn_format) check_function_sentinel (fntype, nargs, argarray); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 980d396..8e36768 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -808,7 +808,7 @@ extern tree fname_decl (location_t, unsigned, tree); extern int check_user_alignment (const_tree, bool); extern bool check_function_arguments (location_t loc, const_tree, const_tree, - int, tree *); + int, tree *, vec *); extern void check_function_arguments_recurse (void (*) (void *, tree, unsigned HOST_WIDE_INT), @@ -816,7 +816,7 @@ extern void check_function_arguments_recurse (void (*) unsigned HOST_WIDE_INT); extern bool check_builtin_function_arguments (location_t, vec, tree, int, tree *); -extern void check_function_format (tree, int, tree *); +extern void check_function_format (tree, int, tree *, vec *); extern bool attribute_fallthrough_p (tree); extern tree handle_format_attribute (tree *, tree, tree, int, bool *); extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *); diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index 7c9095c..0dba979 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -989,6 +989,7 @@ struct format_check_context format_check_results *res; function_format_info *info; tree params; + vec *arglocs; }; /* Return the format name (as specified in the original table) for the format @@ -1011,14 +1012,16 @@ format_flags (int format_num) gcc_unreachable (); } -static void check_format_info (function_format_info *, tree); +static void check_format_info (function_format_info *, tree, + vec *); static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); static void check_format_info_main (format_check_results *, function_format_info *, const char *, location_t, tree, int, tree, unsigned HOST_WIDE_INT, - object_allocator &); + object_allocator &, + vec *); static void init_dollar_format_checking (int, tree); static int maybe_read_dollar_number (const char **, int, @@ -1033,7 +1036,8 @@ static void check_format_types (const substring_loc &fmt_loc, format_wanted_type *, const format_kind_info *fki, int offset_to_type_start, - char conversion_char); + char conversion_char, + vec *arglocs); static void format_type_warning (const substring_loc &fmt_loc, source_range *param_range, format_wanted_type *, tree, @@ -1076,7 +1080,8 @@ decode_format_type (const char *s) attribute themselves. */ void -check_function_format (tree attrs, int nargs, tree *argarray) +check_function_format (tree attrs, int nargs, tree *argarray, + vec *arglocs) { tree a; @@ -1097,7 +1102,7 @@ check_function_format (tree attrs, int nargs, tree *argarray) int i; for (i = nargs - 1; i >= 0; i--) params = tree_cons (NULL_TREE, argarray[i], params); - check_format_info (&info, params); + check_format_info (&info, params, arglocs); } /* Attempt to detect whether the current function might benefit @@ -1400,7 +1405,8 @@ get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates) PARAMS is the list of argument values. */ static void -check_format_info (function_format_info *info, tree params) +check_format_info (function_format_info *info, tree params, + vec *arglocs) { format_check_context format_ctx; unsigned HOST_WIDE_INT arg_num; @@ -1434,6 +1440,7 @@ check_format_info (function_format_info *info, tree params) format_ctx.res = &res; format_ctx.info = info; format_ctx.params = params; + format_ctx.arglocs = arglocs; check_function_arguments_recurse (check_format_arg, &format_ctx, format_tree, arg_num); @@ -1518,6 +1525,7 @@ check_format_arg (void *ctx, tree format_tree, format_check_results *res = format_ctx->res; function_format_info *info = format_ctx->info; tree params = format_ctx->params; + vec *arglocs = format_ctx->arglocs; int format_length; HOST_WIDE_INT offset; @@ -1703,7 +1711,7 @@ check_format_arg (void *ctx, tree format_tree, res->number_other++; object_allocator fwt_pool ("format_wanted_type pool"); check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree, - format_length, params, arg_num, fwt_pool); + format_length, params, arg_num, fwt_pool, arglocs); } /* Support class for argument_parser and check_format_info_main. @@ -1768,7 +1776,8 @@ class argument_parser const char * const orig_format_chars, location_t format_string_loc, flag_chars_t &flag_chars, int &has_operand_number, tree first_fillin_param, - object_allocator &fwt_pool_); + object_allocator &fwt_pool_, + vec *arglocs); bool read_any_dollar (); @@ -1847,6 +1856,7 @@ class argument_parser private: format_wanted_type *first_wanted_type; format_wanted_type *last_wanted_type; + vec *arglocs; }; /* flag_chars_t's constructor. */ @@ -1997,7 +2007,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_, flag_chars_t &flag_chars_, int &has_operand_number_, tree first_fillin_param_, - object_allocator &fwt_pool_) + object_allocator &fwt_pool_, + vec *arglocs_) : info (info_), fki (&format_types[info->format_type]), flag_specs (fki->flag_specs), @@ -2013,7 +2024,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_, has_operand_number (has_operand_number_), first_fillin_param (first_fillin_param_), first_wanted_type (NULL), - last_wanted_type (NULL) + last_wanted_type (NULL), + arglocs (arglocs_) { } @@ -2736,7 +2748,7 @@ check_argument_type (const format_char_info *fci, ptrdiff_t offset_to_type_start = type_start - orig_format_chars; check_format_types (fmt_loc, first_wanted_type, fki, offset_to_type_start, - conversion_char); + conversion_char, arglocs); } return true; @@ -2755,7 +2767,8 @@ check_format_info_main (format_check_results *res, location_t fmt_param_loc, tree format_string_cst, int format_length, tree params, unsigned HOST_WIDE_INT arg_num, - object_allocator &fwt_pool) + object_allocator &fwt_pool, + vec *arglocs) { const char * const orig_format_chars = format_chars; const tree first_fillin_param = params; @@ -2802,7 +2815,7 @@ check_format_info_main (format_check_results *res, argument_parser arg_parser (info, format_chars, format_string_cst, orig_format_chars, format_string_loc, flag_chars, has_operand_number, - first_fillin_param, fwt_pool); + first_fillin_param, fwt_pool, arglocs); if (!arg_parser.read_any_dollar ()) return; @@ -3032,7 +3045,8 @@ static void check_format_types (const substring_loc &fmt_loc, format_wanted_type *types, const format_kind_info *fki, int offset_to_type_start, - char conversion_char) + char conversion_char, + vec *arglocs) { for (; types != 0; types = types->next) { @@ -3072,11 +3086,19 @@ check_format_types (const substring_loc &fmt_loc, source_range param_range; source_range *param_range_ptr; - if (CAN_HAVE_LOCATION_P (cur_param)) + if (EXPR_HAS_LOCATION (cur_param)) { param_range = EXPR_LOCATION_RANGE (cur_param); param_range_ptr = ¶m_range; } + else if (arglocs) + { + /* arg_num is 1-based. */ + gcc_assert (types->arg_num > 0); + location_t param_loc = (*arglocs)[types->arg_num - 1]; + param_range = get_range_from_loc (line_table, param_loc); + param_range_ptr = ¶m_range; + } else param_range_ptr = NULL; diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index c33601f..d7ca148 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3118,7 +3118,7 @@ build_function_call_vec (location_t loc, vec arg_loc, /* Check that the arguments to the function are valid. */ bool warned_p = check_function_arguments (loc, fundecl, fntype, - nargs, argarray); + nargs, argarray, &arg_loc); if (name != NULL_TREE && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10)) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3790299..067db59a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7949,7 +7949,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) fargs[j] = maybe_constant_value (argarray[j]); warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn), - nargs, fargs); + nargs, fargs, NULL); } if (DECL_INHERITED_CTOR (fn)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a5a363b..63667f3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3699,7 +3699,7 @@ cp_build_function_call_vec (tree function, vec **params, /* Check for errors in format strings and inappropriately null parameters. */ bool warned_p = check_function_arguments (input_location, fndecl, fntype, - nargs, argarray); + nargs, argarray, NULL); ret = build_cxx_call (function, nargs, argarray, complain); diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c index 8cce5b3..bc6f665 100644 --- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c +++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c @@ -8,28 +8,24 @@ void test_mismatching_types (const char *msg) { printf("hello %i", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */ -/* TODO: ideally would also underline "msg". */ /* { dg-begin-multiline-output "" } printf("hello %i", msg); - ~^ + ~^ ~~~ %s { dg-end-multiline-output "" } */ printf("hello %s", 42); /* { dg-warning "format '%s' expects argument of type 'char \\*', but argument 2 has type 'int'" } */ -/* TODO: ideally would also underline "42". */ /* { dg-begin-multiline-output "" } printf("hello %s", 42); - ~^ + ~^ ~~ %d { dg-end-multiline-output "" } */ - printf("hello %i", (long)0); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'long int' " } */ -/* TODO: ideally would also underline the argument. */ /* { dg-begin-multiline-output "" } printf("hello %i", (long)0); - ~^ + ~^ ~ %li { dg-end-multiline-output "" } */ } @@ -38,11 +34,12 @@ void test_multiple_arguments (void) { printf ("arg0: %i arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */ 100, 101, 102); -/* TODO: ideally would also underline "101". */ /* { dg-begin-multiline-output "" } printf ("arg0: %i arg1: %s arg 2: %i", ~^ %d + 100, 101, 102); + ~~~ { dg-end-multiline-output "" } */ } @@ -84,10 +81,9 @@ void test_hex (const char *msg) "i" is \x69 */ printf("hello \x25\x69", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */ -/* TODO: ideally would also underline "msg". */ /* { dg-begin-multiline-output "" } printf("hello \x25\x69", msg); - ~~~~^~~~ + ~~~~^~~~ ~~~ \x25s { dg-end-multiline-output "" } */ } @@ -98,10 +94,9 @@ void test_oct (const char *msg) "i" is octal 151. */ printf("hello \045\151", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */ -/* TODO: ideally would also underline "msg". */ /* { dg-begin-multiline-output "" } printf("hello \045\151", msg); - ~~~~^~~~ + ~~~~^~~~ ~~~ \045s { dg-end-multiline-output "" } */ } @@ -115,9 +110,10 @@ void test_multiple (const char *msg) /* { dg-begin-multiline-output "" } printf("prefix" "\x25" "\151" "suffix", ^~~~~~~~ + msg); + ~~~ { dg-end-multiline-output "" } */ -/* TODO: ideally would also underline "msg". */ /* { dg-begin-multiline-output "" } printf("prefix" "\x25" "\151" "suffix", ~~~~~~~~^~~~ @@ -128,10 +124,9 @@ void test_multiple (const char *msg) void test_u8 (const char *msg) { printf(u8"hello %i", msg);/* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */ -/* TODO: ideally would also underline "msg". */ /* { dg-begin-multiline-output "" } printf(u8"hello %i", msg); - ~^ + ~^ ~~~ %s { dg-end-multiline-output "" } */ } @@ -151,7 +146,7 @@ void test_field_width_specifier (long l, int i1, int i2) printf (" %*.*d ", l, i1, i2); /* { dg-warning "14: field width specifier '\\*' expects argument of type 'int', but argument 2 has type 'long int'" } */ /* { dg-begin-multiline-output "" } printf (" %*.*d ", l, i1, i2); - ~^~~~ + ~^~~~ ~ { dg-end-multiline-output "" } */ } @@ -160,10 +155,9 @@ void test_field_width_specifier (long l, int i1, int i2) void test_field_width_specifier_2 (char *d, long foo, long bar) { __builtin_sprintf (d, " %*ld ", foo, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */ - /* TODO: ideally we'd underline the first "foo" here". */ /* { dg-begin-multiline-output "" } __builtin_sprintf (d, " %*ld ", foo, foo); - ~^~~ + ~^~~ ~~~ { dg-end-multiline-output "" } */ __builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */ @@ -176,10 +170,9 @@ void test_field_width_specifier_2 (char *d, long foo, long bar) void test_field_precision_specifier (char *d, long foo, long bar) { __builtin_sprintf (d, " %.*ld ", foo, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */ - /* TODO: ideally we'd underline the first "foo" here". */ /* { dg-begin-multiline-output "" } __builtin_sprintf (d, " %.*ld ", foo, foo); - ~~^~~ + ~~^~~ ~~~ { dg-end-multiline-output "" } */ __builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */ @@ -247,7 +240,7 @@ void test_macro (const char *msg) printf("hello " INT_FMT " world", msg); /* { dg-warning "10: format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */ /* { dg-begin-multiline-output "" } printf("hello " INT_FMT " world", msg); - ^~~~~~~~ + ^~~~~~~~ ~~~ { dg-end-multiline-output "" } */ /* { dg-begin-multiline-output "" } #define INT_FMT "%i" @@ -263,7 +256,7 @@ void test_macro_2 (const char *msg) printf("hello %" PRIu32 " world", msg); /* { dg-warning "10: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'const char \\*' " } */ /* { dg-begin-multiline-output "" } printf("hello %" PRIu32 " world", msg); - ^~~~~~~~~ + ^~~~~~~~~ ~~~ { dg-end-multiline-output "" } */ /* { dg-begin-multiline-output "" } #define PRIu32 "u" @@ -313,7 +306,7 @@ void test_non_contiguous_strings (void) /* { dg-message "26: format string is defined here" "" { target *-*-* } .-1 } */ /* { dg-begin-multiline-output "" } __builtin_printf(" %" "d ", 0.5); - ^~~~ + ^~~~ ~~~ { dg-end-multiline-output "" } */ /* { dg-begin-multiline-output "" } __builtin_printf(" %" "d ", 0.5); @@ -330,6 +323,6 @@ void test_const_arrays (void) __builtin_printf(a, 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */ /* { dg-begin-multiline-output "" } __builtin_printf(a, 0.5); - ^ + ^ ~~~ { dg-end-multiline-output "" } */ } diff --git a/gcc/testsuite/gcc.dg/format/pr72858.c b/gcc/testsuite/gcc.dg/format/pr72858.c index c142d24..b8c5829 100644 --- a/gcc/testsuite/gcc.dg/format/pr72858.c +++ b/gcc/testsuite/gcc.dg/format/pr72858.c @@ -25,56 +25,49 @@ test_x (char *d, sprintf (d, " %-8x ", uiexpr); sprintf (d, " %-8x ", lexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", lexpr); - ~~~^ + ~~~^ ~~~~~ %-8lx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ulexpr); - ~~~^ + ~~~^ ~~~~~~ %-8lx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", llexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", llexpr); - ~~~^ + ~~~^ ~~~~~~ %-8llx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ullexpr); - ~~~^ + ~~~^ ~~~~~~~ %-8llx { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8x ", fexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */ -/* TODO: ideally would also underline "fexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", fexpr); - ~~~^ + ~~~^ ~~~~~ %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */ -/* TODO: ideally would also underline "dexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", dexpr); - ~~~^ + ~~~^ ~~~~~ %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */ -/* TODO: ideally would also underline "ldexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ldexpr); - ~~~^ + ~~~^ ~~~~~~ %-8Lf { dg-end-multiline-output "" } */ @@ -82,7 +75,7 @@ test_x (char *d, sprintf (d, " %-8x ", ptr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'void \\*'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ptr); - ~~~^ + ~~~^ ~~~ %-8p { dg-end-multiline-output "" } */ @@ -92,7 +85,7 @@ test_x (char *d, sprintf (d, " %-8x ", s); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'struct s'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", s); - ~~~^ + ~~~^ ~ { dg-end-multiline-output "" } */ } @@ -109,17 +102,15 @@ test_lx (char *d, /* Integer arguments. */ sprintf (d, " %-8lx ", iexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", iexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8x { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */ -/* TODO: ideally would also underline "uiexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", uiexpr); - ~~~~^ + ~~~~^ ~~~~~~ %-8x { dg-end-multiline-output "" } */ @@ -127,41 +118,36 @@ test_lx (char *d, sprintf (d, " %-8lx ", ulexpr); sprintf (d, " %-8lx ", llexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */ -/* TODO: ideally would also underline "llexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", llexpr); - ~~~~^ + ~~~~^ ~~~~~~ %-8llx { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */ -/* TODO: ideally would also underline "ullexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", ullexpr); - ~~~~^ + ~~~~^ ~~~~~~~ %-8llx { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8lx ", fexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */ -/* TODO: ideally would also underline "fexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", fexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */ -/* TODO: ideally would also underline "dexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", dexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */ -/* TODO: ideally would also underline "ldexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", ldexpr); - ~~~~^ + ~~~~^ ~~~~~~ %-8Lf { dg-end-multiline-output "" } */ } @@ -181,32 +167,28 @@ test_o (char *d, sprintf (d, " %-8o ", uiexpr); sprintf (d, " %-8o ", lexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", lexpr); - ~~~^ + ~~~^ ~~~~~ %-8lo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", ulexpr); - ~~~^ + ~~~^ ~~~~~~ %-8lo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", llexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", llexpr); - ~~~^ + ~~~^ ~~~~~~ %-8llo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */ -/* TODO: ideally would also underline "lexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", ullexpr); - ~~~^ + ~~~^ ~~~~~~~ %-8llo { dg-end-multiline-output "" } */ } @@ -223,17 +205,15 @@ test_lo (char *d, /* Integer arguments. */ sprintf (d, " %-8lo ", iexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", iexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8o { dg-end-multiline-output "" } */ sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */ -/* TODO: ideally would also underline "uiexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", uiexpr); - ~~~~^ + ~~~~^ ~~~~~~ %-8o { dg-end-multiline-output "" } */ @@ -241,17 +221,15 @@ test_lo (char *d, sprintf (d, " %-8lo ", ulexpr); sprintf (d, " %-8lo ", llexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */ -/* TODO: ideally would also underline "llexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", llexpr); - ~~~~^ + ~~~~^ ~~~~~~ %-8llo { dg-end-multiline-output "" } */ sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */ -/* TODO: ideally would also underline "ullexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", ullexpr); - ~~~~^ + ~~~~^ ~~~~~~~ %-8llo { dg-end-multiline-output "" } */ } @@ -265,10 +243,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) /* Integer arguments. */ sprintf (d, " %-8e ", iexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8e ", iexpr); - ~~~^ + ~~~^ ~~~~~ %-8d { dg-end-multiline-output "" } */ @@ -277,10 +254,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) sprintf (d, " %-8e ", fexpr); sprintf (d, " %-8e ", dexpr); sprintf (d, " %-8e ", ldexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'long double'" } */ -/* TODO: ideally would also underline "ldexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8e ", ldexpr); - ~~~^ + ~~~^ ~~~~~~ %-8Le { dg-end-multiline-output "" } */ } @@ -294,10 +270,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) /* Integer arguments. */ sprintf (d, " %-8Le ", iexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", iexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8d { dg-end-multiline-output "" } */ @@ -306,14 +281,14 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) sprintf (d, " %-8Le ", fexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", fexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8e { dg-end-multiline-output "" } */ sprintf (d, " %-8Le ", dexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", dexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8e { dg-end-multiline-output "" } */ @@ -329,10 +304,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) /* Integer arguments. */ sprintf (d, " %-8E ", iexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8E ", iexpr); - ~~~^ + ~~~^ ~~~~~ %-8d { dg-end-multiline-output "" } */ @@ -341,10 +315,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) sprintf (d, " %-8E ", fexpr); sprintf (d, " %-8E ", dexpr); sprintf (d, " %-8E ", ldexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'long double'" } */ -/* TODO: ideally would also underline "ldexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8E ", ldexpr); - ~~~^ + ~~~^ ~~~~~~ %-8LE { dg-end-multiline-output "" } */ } @@ -358,24 +331,23 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) /* Integer arguments. */ sprintf (d, " %-8LE ", iexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'int'" } */ -/* TODO: ideally would also underline "iexpr". */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", iexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8d { dg-end-multiline-output "" } */ sprintf (d, " %-8LE ", fexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", fexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8E { dg-end-multiline-output "" } */ sprintf (d, " %-8LE ", dexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", dexpr); - ~~~~^ + ~~~~^ ~~~~~ %-8E { dg-end-multiline-output "" } */ @@ -394,19 +366,19 @@ test_everything (char *d, long lexpr) /* { dg-warning "26: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); - ~~~^~~~~~ + ~~~^~~~~~ ~~~~~ { dg-end-multiline-output "" } */ /* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); - ~~~~~^~~~ + ~~~~~^~~~ ~~~~~ { dg-end-multiline-output "" } */ /* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); - ~~~~~~~~^ + ~~~~~~~~^ ~~~~~ %-+*.*ld { dg-end-multiline-output "" } */ }