From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ed1-x52d.google.com (mail-ed1-x52d.google.com [IPv6:2a00:1450:4864:20::52d]) by sourceware.org (Postfix) with ESMTPS id AA5B4393D035; Wed, 12 Jan 2022 13:34:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AA5B4393D035 Received: by mail-ed1-x52d.google.com with SMTP id a18so10052910edj.7; Wed, 12 Jan 2022 05:34:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=uvqQP16UCrDUjjmojzf9aaRhJDBk61vkDSvUPVvDgB0=; b=GpHK4f/5MphRzGZaWgqSsjyWFz0RfQIgqEXzcjpP9VYwtUP1kffR/w3F4ggnPVysCI iokc44z9+hYz+2iQS4NUBGNWNs0sGVqwhhj//ksq8uMQy5fRxxShCqjhp8d9TG65ZLlZ /2QC4jmk9ul6eaFCLRh74+eOqm2OrMiZTPRr0F1hSDfJOETEL2i2rR6qTA4n30NfOXQg mUHxNBx+wALcTYN/gj7nRM6wFOqr8UGaWg1XXovMVC1rsyuLOiqgAW+RomAlJ/rq2xKy 1vjJZqA6SoSBa5xkw3Zy2XYlGj4wSydBTntMzkzSqhAUBil9ciTgRL/ZqCZUtu7+Q3xQ NIyQ== X-Gm-Message-State: AOAM531lijUNkV9Y1knZNiuBqJeaHmPxljgkljkzJXKPcCghL6s6M1d+ 69cq7cJqThYJsnoGfyZmIl8/PuzIOe8= X-Google-Smtp-Source: ABdhPJy23alnFiyyjVqSJ/7bIPS4nQMJrLTKQ48E7whKvrUySbrcDXO+ZP23EQWna2n0LqofuBgiyQ== X-Received: by 2002:a17:907:3e8b:: with SMTP id hs11mr7570006ejc.461.1641994478596; Wed, 12 Jan 2022 05:34:38 -0800 (PST) Received: from [192.168.0.87] (ip-86-49-13-224.net.upcbroadband.cz. [86.49.13.224]) by smtp.gmail.com with ESMTPSA id d14sm6123712edu.57.2022.01.12.05.34.37 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 12 Jan 2022 05:34:37 -0800 (PST) Subject: Re: [PATCH] [12/11/10] Fix invalid format warnings on Windows To: =?UTF-8?Q?Martin_Li=c5=a1ka?= , gcc-patches@gcc.gnu.org Cc: joseph@codesourcery.com, martin@martin.st, redi@gcc.gnu.org References: <466c29c3-54b1-5627-3d9d-e385ad037a4e@suse.cz> From: Tomas Kalibera Message-ID: <7fd8d3fb-e0c6-decc-374f-495ab81ab1ff@gmail.com> Date: Wed, 12 Jan 2022 14:34:36 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <466c29c3-54b1-5627-3d9d-e385ad037a4e@suse.cz> Content-Type: multipart/mixed; boundary="------------3993F05875100D91145A7485" Content-Language: en-US X-Spam-Status: No, score=-8.7 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Jan 2022 13:34:41 -0000 This is a multi-part message in MIME format. --------------3993F05875100D91145A7485 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit On 1/11/22 2:37 PM, Martin Liška wrote: > Hello. > > I do support the patch, but I would ... Thanks, Martin,  that makes the patch simpler and easier to maintain. Would the attached version do? Thanks Tomas > > On 1/7/22 19:33, Tomas Kalibera wrote: >> +          if (is_attribute_p ("format", get_attribute_name (aa)) && >> +              fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) >> +            { >> +              switch (DECL_FUNCTION_CODE (fndecl)) >> +            { >> +            case BUILT_IN_FSCANF: >> +            case BUILT_IN_PRINTF: >> +            case BUILT_IN_SCANF: >> +            case BUILT_IN_SNPRINTF: >> +            case BUILT_IN_SSCANF: >> +            case BUILT_IN_VFSCANF: >> +            case BUILT_IN_VPRINTF: >> +            case BUILT_IN_VSCANF: >> +            case BUILT_IN_VSNPRINTF: >> +            case BUILT_IN_VSSCANF: >> +            case BUILT_IN_DCGETTEXT: >> +            case BUILT_IN_DGETTEXT: >> +            case BUILT_IN_GETTEXT: >> +            case BUILT_IN_STRFMON: >> +            case BUILT_IN_STRFTIME: >> +            case BUILT_IN_SNPRINTF_CHK: >> +            case BUILT_IN_VSNPRINTF_CHK: >> +            case BUILT_IN_PRINTF_CHK: >> +            case BUILT_IN_VPRINTF_CHK: >> +              skipped_default_format = 1; >> +              break; >> +            default: >> +              break; >> +            } >> +            } > > ... skip this as the listed functions are only these that have defined > ATTR_FORMAT_*: > > $ grep ATTR_FORMAT gcc/builtins.def > DEF_LIB_BUILTIN        (BUILT_IN_FSCANF, "fscanf", > BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3) > DEF_LIB_BUILTIN        (BUILT_IN_PRINTF, "printf", > BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_1_2) > DEF_LIB_BUILTIN        (BUILT_IN_SCANF, "scanf", > BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_SCANF_1_2) > DEF_C99_BUILTIN        (BUILT_IN_SNPRINTF, "snprintf", > BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_3_4) > DEF_LIB_BUILTIN        (BUILT_IN_SSCANF, "sscanf", > BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_NOTHROW_2_3) > DEF_C99_BUILTIN        (BUILT_IN_VFSCANF, "vfscanf", > BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0) > DEF_LIB_BUILTIN        (BUILT_IN_VPRINTF, "vprintf", > BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_1_0) > DEF_C99_BUILTIN        (BUILT_IN_VSCANF, "vscanf", > BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_1_0) > DEF_C99_BUILTIN        (BUILT_IN_VSNPRINTF, "vsnprintf", > BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, > ATTR_FORMAT_PRINTF_NOTHROW_3_0) > DEF_C99_BUILTIN        (BUILT_IN_VSSCANF, "vsscanf", > BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG, > ATTR_FORMAT_SCANF_NOTHROW_2_0) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_DCGETTEXT, "dcgettext", > BT_FN_STRING_CONST_STRING_CONST_STRING_INT, ATTR_FORMAT_ARG_2) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_DGETTEXT, "dgettext", > BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_GETTEXT, "gettext", > BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", > BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, > ATTR_FORMAT_STRFMON_NOTHROW_3_4) > DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", > BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, > ATTR_FORMAT_STRFTIME_NOTHROW_3_0) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", > BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, > ATTR_FORMAT_PRINTF_NOTHROW_5_6) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", > BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, > ATTR_FORMAT_PRINTF_NOTHROW_5_0) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_PRINTF_CHK, "__printf_chk", > BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3) > DEF_EXT_LIB_BUILTIN    (BUILT_IN_VPRINTF_CHK, "__vprintf_chk", > BT_FN_INT_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0) > > Martin --------------3993F05875100D91145A7485 Content-Type: text/x-patch; charset=UTF-8; name="fix_invalid_format_warnings_on_windows.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="fix_invalid_format_warnings_on_windows.patch" >From 82a659c7e5b24bbd39ac567dff3f79cc4c1e083f Mon Sep 17 00:00:00 2001 From: Tomas Kalibera Date: Wed, 12 Jan 2022 08:17:21 -0500 Subject: [PATCH] Mingw32 targets use ms_printf format for printf, but mingw-w64 when configured for UCRT uses gnu_format (via stdio.h). GCC then checks both formats, which means that one cannot print a 64-bit integer without a warning. All these lines issue a warning: printf("Hello %"PRIu64"\n", x); printf("Hello %I64u\n", x); printf("Hello %llu\n", x); because each of them violates one of the formats. Also, one gets a warning twice if the format string violates both formats. Fixed by disabling the built in format in case there are additional ones. gcc/c-family/ChangeLog: PR c/95130 PR c/92292 * c-common.c (check_function_arguments): Pass also function declaration to check_function_format. * c-common.h (check_function_format): Extra argument - function declaration. * c-format.c (check_function_format): For builtin functions with a built in format and at least one more, do not check the first one. --- gcc/c-family/c-common.c | 2 +- gcc/c-family/c-common.h | 2 +- gcc/c-family/c-format.c | 31 +++++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 4a6a4edb763..00fc734d28e 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -6064,7 +6064,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 (fntype, TYPE_ATTRIBUTES (fntype), nargs, argarray, + check_function_format (fndecl, fntype, TYPE_ATTRIBUTES (fntype), nargs, argarray, arglocs); if (warn_format) diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 8b7bf35e888..ee370eafbbc 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -856,7 +856,7 @@ extern void check_function_arguments_recurse (void (*) unsigned HOST_WIDE_INT); extern bool check_builtin_function_arguments (location_t, vec, tree, tree, int, tree *); -extern void check_function_format (const_tree, tree, int, tree *, +extern void check_function_format (const_tree, const_tree, tree, int, tree *, vec *); extern bool attribute_fallthrough_p (tree); extern tree handle_format_attribute (tree *, tree, tree, int, bool *); diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index afa77810a5c..da72d85f66e 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -1160,12 +1160,13 @@ decode_format_type (const char *s, bool *is_raw /* = NULL */) attribute themselves. */ void -check_function_format (const_tree fntype, tree attrs, int nargs, +check_function_format (const_tree fndecl, const_tree fntype, tree attrs, int nargs, tree *argarray, vec *arglocs) { - tree a; + tree a, aa; tree atname = get_identifier ("format"); + int skipped_default_format = 0; /* See if this function has any format attributes. */ for (a = attrs; a; a = TREE_CHAIN (a)) @@ -1176,6 +1177,32 @@ check_function_format (const_tree fntype, tree attrs, int nargs, function_format_info info; decode_format_attr (fntype, atname, TREE_VALUE (a), &info, /*validated=*/true); + + /* Mingw32 targets have traditionally used ms_printf format for the + printf function, and this format is built in GCC. But nowadays, + if mingw-w64 is configured to target UCRT, the printf function + uses the gnu_printf format (specified in the stdio.h header). This + causes GCC to check both formats, which means that there is no way + to e.g. print a long long unsigned without a warning (ms_printf + warns for %llu and gnu_printf warns for %I64u). Also, GCC would warn + twice about the same issue when both formats are violated, e.g. + for %lu used to print long long unsigned. + + Hence, if there are multiple format specifiers, we skip the first + one. See PR 95130, PR 92292. */ + + if (!skipped_default_format && fndecl) + { + for(aa = TREE_CHAIN (a); aa; aa = TREE_CHAIN(aa)) + if (is_attribute_p ("format", get_attribute_name (aa)) && + fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) + { + skipped_default_format = 1; + break; + } + if (skipped_default_format) continue; + } + if (warn_format) { /* FIXME: Rewrite all the internal functions in this file -- 2.25.1 --------------3993F05875100D91145A7485--