From patchwork Fri Jan 7 18:33:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tomas Kalibera X-Patchwork-Id: 49722 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DB77F3857C4D for ; Fri, 7 Jan 2022 18:34:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DB77F3857C4D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1641580462; bh=YKyT+zcl3o3G0FEb97RKTJ+WvleaHznmSk1bqKNH5mM=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=Kc0LY9UlONs6Klt0GuhY9ImHDwzkTjVlEyYyncSfnCDQ8dibD7CX7hnkzL1YaKakp 89YC+VVs8JNsJv7bokLKHabCIwYv1Sa4o+8pstnJI5ATQZZaGxMz+y5zKrxnXaxJP5 8ZlFy/GqPa057WF2zBh/mLGAAQcsbtn02KN7Uv+A= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 790093858D28; Fri, 7 Jan 2022 18:33:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 790093858D28 Received: by mail-wr1-x42e.google.com with SMTP id r10so5027077wrc.3; Fri, 07 Jan 2022 10:33:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:to:cc:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding:content-language; bh=YKyT+zcl3o3G0FEb97RKTJ+WvleaHznmSk1bqKNH5mM=; b=JgvFNipsn0P/0X7nSFGAKfSWTyXHqRN8N/ge7m3q2v07j04JlxH8VYVYbytrJ5F1cj lLoJY83rxCxBCJSA3NkP23Z+6x0Run9q6HlQnErF99zPMlFJHjdwUQQ3am/+fEXFL/9K I/tdQFObnQJS+KkdJq9jll59p6K/yM3Aox+MHPmxQKgLMvxwlGGh91gcPiEtSFp7i1w1 SXB+yT1zYGtN5emiRnwKGxr2ouIa9DGbhHpV+efJqcQORztXcTmOfIAR8qKrSNbTtHYt B0ex1VjxWJrJtpfgggxhlZD00Kq9klPyPdQEzz060ivSYB1epI3JjI2dj4DdPAK9BiqF RVvQ== X-Gm-Message-State: AOAM531sBnHsvydS5g/5f3z5l0p0r6ZUMcVp9sUjLfQpsQOk+2GvoO2h 6gYXIqwxbWf7yuFDgE+7n40= X-Google-Smtp-Source: ABdhPJwbN6i4QKLpeHrlpU4vum/n1NFCQor87dkMa2rj1Bx0uVYUJ7a+cZUX8ksnQ1nmyVLhDBFdPw== X-Received: by 2002:a05:6000:107:: with SMTP id o7mr11929876wrx.546.1641580432439; Fri, 07 Jan 2022 10:33:52 -0800 (PST) Received: from [137.208.148.103] ([137.208.148.103]) by smtp.gmail.com with ESMTPSA id d11sm5774750wri.101.2022.01.07.10.33.48 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 07 Jan 2022 10:33:51 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH] [12/11/10] Fix invalid format warnings on Windows Message-ID: Date: Fri, 7 Jan 2022 19:33:40 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-8.0 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, 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-Patchwork-Original-From: Tomas Kalibera via Gcc-patches From: Tomas Kalibera Reply-To: Tomas Kalibera Cc: redi@gcc.gnu.org, joseph@codesourcery.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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); // 1   printf("Hello %I64u\n", x);     // 2   printf("Hello %llu\n", x);      // 3 because each of them violates one of the formats.  This causes trouble particularly for systems that turn warnings into errors or otherwise require no warnings (leading to the use of -Wno-format or of various printf replacements). Also, one gets a warning twice if the format string violates both formats. These issues have been reported as PR 95130 and PR 92292: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95130 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92292 This patch fixes these issues following the suggestion of Joseph Myers, it disables the built in format in case there are additional ones. It applies to GCC 12, 11, 10 and fixes the example above as tested on cross compilers built on Linux.  I've also verified that R built using a 10.3 native compiler with the patch applied builds and passes its tests.  I've updated the patch based on advice and comments from Martin Liska and Martin Storsjo. Could this or a variant of please be accepted to 12/11/10? Thanks Tomas gcc/c-family/ChangeLog:         * 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.    /* See if this function has any format attributes.  */    for (a = attrs; a; a = TREE_CHAIN (a)) @@ -1176,6 +1177,58 @@ 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)) +            { +              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; +            } +            } +        } +          if (skipped_default_format) continue; +        } +        if (warn_format)          {            /* FIXME: Rewrite all the internal functions in this file diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 13341fa315e..be4d8400447 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -6057,7 +6057,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..8155ee8c6f2 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;