libgomp build fails because of the false -Wformat error, even though:
1. Correct C99 inttypes.h macros are used.
2. __mingw_* C99 wrappers are used.
3. The printf attribute is used, but it was aliased to ms_printf

The attached patch makes mingw-w64 printf attribute equivalent to other platforms on C99 or later. This allows libgomp to build again with -Werror on. This patch should not affect the original mingw.org distribution in any way.

For C99 or later, the mingw-w64 headers already wrap printf/scanf properly, and inttypes.h also gives the correct C99 specifiers, so it makes sense to treat the printf attribute as C99 compliant. Under C89 mode, the headers would produce MS specific specifiers, so the printf attribute under C89 reverts to the old behavior of being aliased to ms_printf.

This might break other code that assumes differently however. I don't think there is a solution to satisfy everyone, but at least this allows C99/C++11 compliant code to build again with -Werror. Comments?
From 397097aba5a098f18da92704e9ca7560adb4f29c Mon Sep 17 00:00:00 2001
From: Jonathan Yong <10wa...@gmail.com>
Date: Thu, 12 Nov 2020 06:45:00 +0000
Subject: [PATCH] gcc: make mingw-w64 printf/scanf attribute gnu equivalents in
 C99

Makes printf/scanf attribute equivalent to gnu_printf and gnu_scanf
in C99 mode. Fixes false positive warnings for functions with printf
attribute, even when correct C99 style printf specifiers are used.

12-11-2020  Jonathan Yong  <10wa...@gmail.com>

gcc/ChangeLog:

	* c-family/c-format.c
	(convert_format_name_to_system_name):
	Turn TARGET_OVERRIDES_FORMAT_ATTRIBUTES into a callback
	that returns a list of attribute aliases.
	* config/i386/mingw-w64.h (TARGET_OVERRIDES_FORMAT_C89):
	Define. Tell GCC to use ms_printf and ms_scanf in C89.
	* config/i386/mingw32.h:
	(TARGET_OVERRIDES_FORMAT_ATTRIBUTES):
	Point to wrapper function and update description.
	(TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT): remove.
	* config/i386/msformat-c.c:
	(mingw_format_attribute_overrides):
	New callback.
	(mingw_format_attribute_overrides_table): make null
	terminated.
---
 gcc/c-family/c-format.c      | 28 ++++++++++++++++------------
 gcc/config/i386/mingw-w64.h  |  4 ++++
 gcc/config/i386/mingw32.h    |  8 ++------
 gcc/config/i386/msformat-c.c | 23 ++++++++++++++++++++---
 4 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 77d24ad94e4..4edf4c64f79 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -5077,7 +5077,7 @@ extern const format_kind_info TARGET_FORMAT_TYPES[];
 #endif
 
 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
-extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES[];
+extern const target_ovr_attr* TARGET_OVERRIDES_FORMAT_ATTRIBUTES (int format_std_version);
 #endif
 #ifdef TARGET_OVERRIDES_FORMAT_INIT
   extern void TARGET_OVERRIDES_FORMAT_INIT (void);
@@ -5102,6 +5102,9 @@ static const char *
 convert_format_name_to_system_name (const char *attr_name)
 {
   int i;
+#ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
+  const target_ovr_attr* override_attributes;
+#endif
 
   if (attr_name == NULL || *attr_name == 0
       || strncmp (attr_name, "gcc_", 4) == 0)
@@ -5112,18 +5115,19 @@ convert_format_name_to_system_name (const char *attr_name)
 
 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
   /* Check if format attribute is overridden by target.  */
-  if (TARGET_OVERRIDES_FORMAT_ATTRIBUTES != NULL
-      && TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT > 0)
+  override_attributes = TARGET_OVERRIDES_FORMAT_ATTRIBUTES(C_STD_VER);
+  if (override_attributes != NULL)
     {
-      for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
-        {
-          if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src,
-			   attr_name))
-            return attr_name;
-          if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst,
-			   attr_name))
-            return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
-        }
+      for (i = 0;
+	   override_attributes[i].named_attr_src != NULL
+	   && override_attributes[i].named_attr_dst != NULL;
+	   ++i)
+	{
+	if (cmp_attribs (override_attributes[i].named_attr_src, attr_name))
+	  return attr_name;
+	if (cmp_attribs (override_attributes[i].named_attr_dst, attr_name))
+	  return override_attributes[i].named_attr_src;
+      }
     }
 #endif
   /* Otherwise default to gnu format.  */
diff --git a/gcc/config/i386/mingw-w64.h b/gcc/config/i386/mingw-w64.h
index 0d0aa939996..586d151a082 100644
--- a/gcc/config/i386/mingw-w64.h
+++ b/gcc/config/i386/mingw-w64.h
@@ -104,3 +104,7 @@ along with GCC; see the file COPYING3.  If not see
    original mingw32.  */
 #undef TARGET_LIBC_HAS_FUNCTION
 #define TARGET_LIBC_HAS_FUNCTION gnu_libc_has_function
+
+/* alias printf/scanf attributes to MS variants when in C89 */
+#undef TARGET_OVERRIDES_FORMAT_C89
+#define TARGET_OVERRIDES_FORMAT_C89
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index 321c30e41cc..8fa2008c1b6 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -241,16 +241,12 @@ do {						         \
    to register C++ static destructors.  */
 #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
 
-/* Contains a pointer to type target_ovr_attr defining the target specific
+/* Returns a pointer to type target_ovr_attr defining the target specific
    overrides of format attributes.  See c-format.h for structure
-   definition.  */
+   definition, null terminated  */
 #undef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
 #define TARGET_OVERRIDES_FORMAT_ATTRIBUTES mingw_format_attribute_overrides
 
-/* Specify the count of elements in TARGET_OVERRIDES_ATTRIBUTE.  */
-#undef TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT
-#define TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT 3
-
 /* Custom initialization for warning -Wpedantic-ms-format for c-format.  */
 #undef TARGET_OVERRIDES_FORMAT_INIT
 #define TARGET_OVERRIDES_FORMAT_INIT msformat_init
diff --git a/gcc/config/i386/msformat-c.c b/gcc/config/i386/msformat-c.c
index 4ceec633a6e..a75b24669a0 100644
--- a/gcc/config/i386/msformat-c.c
+++ b/gcc/config/i386/msformat-c.c
@@ -161,14 +161,31 @@ EXPORTED_CONST format_kind_info mingw_format_attributes[3] =
   }
 };
 
-/* Default overrides for printf, scanf and strftime.  */
-EXPORTED_CONST target_ovr_attr mingw_format_attribute_overrides[4] =
+/* Default overrides for printf, scanf and strftime in C89 */
+static const target_ovr_attr mingw_format_attribute_overrides_table[] =
 {
   { "ms_printf", "printf" },
   { "ms_scanf", "scanf" },
-  { "ms_strftime", "strftime" }
+  { "ms_strftime", "strftime" },
+  { NULL, NULL}
 };
 
+/* For C99 and later, there are no strftime C99 wrappers yet */
+static const target_ovr_attr __attribute__ ((unused)) mingw_format_attribute_overrides_table_c99[] =
+{
+  { "ms_strftime", "strftime" },
+  { NULL, NULL }
+};
+
+EXPORTED_CONST target_ovr_attr *mingw_format_attribute_overrides(int __attribute__ ((unused)) std)
+{
+#ifdef TARGET_OVERRIDES_FORMAT_C89
+  if(std >= STD_C9L)
+    return mingw_format_attribute_overrides_table_c99;
+#endif
+  return mingw_format_attribute_overrides_table;
+}
+
 /* Setup for option Wpedantic-ms-format.  */
 
 #ifdef TARGET_OVERRIDES_FORMAT_INIT
-- 
2.29.2

Attachment: OpenPGP_0x713B5FE29C145D45_and_old_rev.asc
Description: application/pgp-keys

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to