Index: gcc/gcc/c-format.c
===================================================================
--- gcc.orig/gcc/c-format.c
+++ gcc/gcc/c-format.c
@@ -80,7 +80,8 @@ static bool check_format_string (tree ar
int flags, bool *no_add_attrs);
static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value,
int validated_p);
-
+static const char *replace_formatter_name_to_system_name (const char *attr_name);
+static int compare_tofa (const char *tattr_name, const char *attr_name);
/* Handle a "format_arg" attribute; arguments as in
struct attribute_spec.handler. */
@@ -191,6 +192,8 @@ decode_format_attr (tree args, function_
{
const char *p = IDENTIFIER_POINTER (format_type_id);
+ p = replace_formatter_name_to_system_name (p);
+
info->format_type = decode_format_type (p);
if (info->format_type == format_type_error)
@@ -715,7 +718,7 @@ static const format_char_info monetary_c
/* This must be in the same order as enum format_type. */
static const format_kind_info format_types_orig[] =
{
- { "printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
+ { "gnu_printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
printf_flag_specs, printf_flag_pairs,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
'w', 0, 'p', 0, 'L', 0,
@@ -757,18 +760,18 @@ static const format_kind_info format_typ
0, 0, 0, 0, 0, 0,
NULL, NULL
},
- { "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
+ { "gnu_scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
scanf_flag_specs, scanf_flag_pairs,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
'w', 0, 0, '*', 'L', 'm',
NULL, NULL
},
- { "strftime", NULL, time_char_table, "_-0^#", "EO",
+ { "gnu_strftime", NULL, time_char_table, "_-0^#", "EO",
strftime_flag_specs, strftime_flag_pairs,
FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
NULL, NULL
},
- { "strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
+ { "gnu_strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
strfmon_flag_specs, strfmon_flag_pairs,
FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
NULL, NULL
@@ -847,6 +850,7 @@ decode_format_type (const char *s)
{
int i;
int slen;
+ s = replace_formatter_name_to_system_name (s);
slen = strlen (s);
for (i = 0; i < n_format_types; i++)
{
@@ -1776,7 +1780,22 @@ check_format_info_main (format_check_res
if (fli)
{
while (fli->name != 0 && fli->name[0] != *format_chars)
- fli++;
+ {
+ if (fli->name[0] == '\0')
+ {
+ int si = strlen (fli->name + 1) + 1;
+ int i = 1;
+ while (fli->name[i] != 0 && fli->name[i] == format_chars [i - 1])
+ ++i;
+ if (si == i)
+ {
+ if (si > 2)
+ format_chars += si - 2;
+ break;
+ }
+ }
+ fli++;
+ }
if (fli->name != 0)
{
format_chars++;
@@ -2703,6 +2722,72 @@ init_dynamic_diag_info (void)
extern const format_kind_info TARGET_FORMAT_TYPES[];
#endif
+#ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
+extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES[];
+#endif
+
+/* Description of gnu specific format attributes reflected to
+ system format attribute types, as printf, scanf, strftime, and
+ strfmon. */
+const target_ovr_attr gnu_target_overrides_format_attributes[] =
+{
+ { "gnu_printf", "printf" },
+ { "gnu_scanf", "scanf" },
+ { "gnu_strftime", "strftime" },
+ { "gnu_strfmon", "strfmon" },
+ { NULL, NULL }
+};
+
+static const char *
+replace_formatter_name_to_system_name (const char *attr_name)
+{
+ int i;
+
+ if (attr_name == NULL || *attr_name == 0 || strncmp (attr_name, "gcc_", 4) == 0)
+ return 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)
+ {
+ for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
+ {
+ if (compare_tofa (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src, attr_name))
+ return attr_name;
+ if (compare_tofa (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst, attr_name))
+ return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
+ }
+ }
+#endif
+ /* Otherwise default to gnu formatter. */
+ for (i = 0; gnu_target_overrides_format_attributes[i].named_attr_src != NULL; ++i)
+ {
+ if (compare_tofa (gnu_target_overrides_format_attributes[i].named_attr_src, attr_name))
+ return attr_name;
+ if (compare_tofa (gnu_target_overrides_format_attributes[i].named_attr_dst, attr_name))
+ return gnu_target_overrides_format_attributes[i].named_attr_src;
+ }
+
+ return attr_name;
+}
+
+/* Compare the target override format attribute by treating double underscore syntax. */
+static int
+compare_tofa (const char *tattr_name, const char *attr_name)
+{
+ int alen = strlen (attr_name);
+ int slen = (tattr_name ? strlen (tattr_name) : 0);
+ if (alen > 4 && attr_name[0] == '_' && attr_name[1] == '_'
+ && attr_name[alen - 1] == '_' && attr_name[alen - 2] == '_')
+ {
+ attr_name += 2;
+ alen -= 4;
+ }
+ if (alen != slen || strncmp (tattr_name, attr_name, alen) != 0)
+ return 0;
+ return 1;
+}
+
/* Handle a "format" attribute; arguments as in
struct attribute_spec.handler. */
tree
Index: gcc/gcc/c-format.h
===================================================================
--- gcc.orig/gcc/c-format.h
+++ gcc/gcc/c-format.h
@@ -306,4 +306,18 @@ typedef struct
#define T_D128 &dfloat128_type_node
#define TEX_D128 { STD_EXT, "_Decimal128", T_D128 }
+/* Structure describing the target specific to be override formatter
+ attributes, e.g. printf, scanf, etc. This allows to support different
+ runtime-library specific formatter attributes to co-exist and defining
+ a default system version.
+ This type is used for the pointer variable TARGET_OVERRIDES_FORMAT_ATTRIBUTES
+ refers to. */
+typedef struct
+{
+ /* The name of the to be copied formatter attribute. */
+ const char *named_attr_src;
+ /* The name of the to be overridden formatter attribute. */
+ const char *named_attr_dst;
+} target_ovr_attr;
+
#endif /* GCC_C_FORMAT_H */
Index: gcc/gcc/config.gcc
===================================================================
--- gcc.orig/gcc/config.gcc
+++ gcc/gcc/config.gcc
@@ -1359,8 +1359,8 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt"
extra_objs="winnt.o winnt-stubs.o"
- c_target_objs=cygwin2.o
- cxx_target_objs="cygwin2.o winnt-cxx.o"
+ c_target_objs="cygwin2.o msformat-c.o"
+ cxx_target_objs="cygwin2.o winnt-cxx.o msformat-c.o"
extra_gcc_objs=cygwin1.o
if test x$enable_threads = xyes; then
thread_file='posix'
@@ -1373,7 +1373,8 @@ i[34567]86-*-mingw32* | x86_64-*-mingw32
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt"
extra_objs="winnt.o winnt-stubs.o"
- cxx_target_objs=winnt-cxx.o
+ c_target_objs="msformat-c.o"
+ cxx_target_objs="winnt-cxx.o msformat-c.o"
default_use_cxa_atexit=yes
case ${enable_threads} in
"" | yes | win32)
Index: gcc/gcc/config/i386/mingw32.h
===================================================================
--- gcc.orig/gcc/config/i386/mingw32.h
+++ gcc/gcc/config/i386/mingw32.h
@@ -143,6 +143,22 @@ 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
+ overrides of formatter attributs. See format.h for structure definition. */
+#undef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
+#define TARGET_OVERRIDES_FORMAT_ATTRIBUTES mingw_formatter_attribute_overrides
+
+/* Specify the count of elements in TARGET_OVERRIDES_ATTRIBUTE. */
+#undef TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT
+#define TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT 3
+
+/* MS specific format attributes for ms_printf, ms_scanf, ms_strftime. */
+#undef TARGET_FORMAT_TYPES
+#define TARGET_FORMAT_TYPES mingw_formatter_attributes
+
+#undef TARGET_N_FORMAT_TYPES
+#define TARGET_N_FORMAT_TYPES 3
+
/* JCR_SECTION works on mingw32. */
#undef TARGET_USE_JCR_SECTION
#define TARGET_USE_JCR_SECTION 1
Index: gcc/gcc/config/i386/msformat-c.c
===================================================================
--- /dev/null
+++ gcc/gcc/config/i386/msformat-c.c
@@ -0,0 +1,189 @@
+/* Check calls to formatted I/O functions (-Wformat).
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "c-common.h"
+#include "toplev.h"
+#include "intl.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "c-format.h"
+#include "alloc-pool.h"
+
+/* Mingw specific format attributes ms_printf, ms_scanf, and ms_strftime. */
+
+static const format_length_info ms_printf_length_specs[] =
+{
+ { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
+ { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
+ { "\0I32", FMT_LEN_l, STD_C89, NULL, 0, 0 },
+ { "\0I64", FMT_LEN_ll, STD_C9L, NULL, 0, 0 },
+ { "I", FMT_LEN_L, STD_C89, NULL, 0, 0 },
+ { NULL, 0, 0, NULL, 0, 0 }
+};
+
+static const format_flag_spec ms_printf_flag_specs[] =
+{
+ { ' ', 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 },
+ { '+', 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
+ { '#', 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
+ { '0', 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 },
+ { '-', 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 },
+ { '\'', 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT },
+ { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
+ { '.', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
+ { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
+ { 0, 0, 0, NULL, NULL, 0 }
+};
+
+static const format_flag_pair ms_printf_flag_pairs[] =
+{
+ { ' ', '+', 1, 0 },
+ { '0', '-', 1, 0 },
+ { 0, 0, 0, 0 }
+};
+
+static const format_flag_spec ms_scanf_flag_specs[] =
+{
+ { '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
+ { 'a', 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT },
+ { 'w', 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 },
+ { 'L', 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 },
+ { '\'', 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT },
+ { 0, 0, 0, NULL, NULL, 0 }
+};
+
+static const format_flag_pair ms_scanf_flag_pairs[] =
+{
+ { '*', 'L', 0, 0 },
+ { 0, 0, 0, 0 }
+};
+
+static const format_flag_spec ms_strftime_flag_specs[] =
+{
+ { '_', 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT },
+ { '-', 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT },
+ { '0', 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT },
+ { '^', 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT },
+ { '#', 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT },
+ { 'w', 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT },
+ { 'E', 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 },
+ { 'O', 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 },
+ { 'O', 'o', 0, NULL, N_("the 'O' modifier"), STD_EXT },
+ { 0, 0, 0, NULL, NULL, 0 }
+};
+
+
+static const format_flag_pair ms_strftime_flag_pairs[] =
+{
+ { 'E', 'O', 0, 0 },
+ { '_', '-', 0, 0 },
+ { '_', '0', 0, 0 },
+ { '-', '0', 0, 0 },
+ { '^', '#', 0, 0 },
+ { 0, 0, 0, 0 }
+};
+
+static const format_char_info ms_print_char_table[] =
+{
+ /* C89 conversion specifiers. */
+ { "di", 0, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +'", "i", NULL },
+ { "oxX", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
+ { "u", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0'", "i", NULL },
+ { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "", NULL },
+ { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
+ { "c", 0, STD_C89, { T89_I, BADLEN, T89_S, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
+ { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL },
+ { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
+ /* X/Open conversion specifiers. */
+ { "C", 0, STD_EXT, { TEX_WI, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
+ { "S", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+static const format_char_info ms_scan_char_table[] =
+{
+ /* C89 conversion specifiers. */
+ { "di", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "u", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "oxX", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
+ { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "c", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL },
+ { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL },
+ { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
+ { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
+ /* X/Open conversion specifiers. */
+ { "C", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
+ { "S", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL },
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+static const format_char_info ms_time_char_table[] =
+{
+ /* C89 conversion specifiers. */
+ { "ABZab", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
+ { "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL },
+ { "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL },
+ { "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL },
+ { "p", 0, STD_C89, NOLENGTHS, "#", "", NULL },
+ { "X", 0, STD_C89, NOLENGTHS, "E", "", NULL },
+ { "y", 0, STD_C89, NOLENGTHS, "EO-_0w", "4", NULL },
+ { "Y", 0, STD_C89, NOLENGTHS, "-_0EOw", "o", NULL },
+ { "%", 0, STD_C89, NOLENGTHS, "", "", NULL },
+ /* C99 conversion specifiers. */
+ { "z", 0, STD_C99, NOLENGTHS, "O", "o", NULL },
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+const format_kind_info mingw_formatter_attributes[3] =
+{
+ { "ms_printf", ms_printf_length_specs, ms_print_char_table, " +#0-'", NULL,
+ ms_printf_flag_specs, ms_printf_flag_pairs,
+ FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
+ 'w', 0, 0, 0, 'L', 0,
+ &integer_type_node, &integer_type_node
+ },
+ { "ms_scanf", ms_printf_length_specs, ms_scan_char_table, "*'", NULL,
+ ms_scanf_flag_specs, ms_scanf_flag_pairs,
+ FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
+ 'w', 0, 0, '*', 'L', 'm',
+ NULL, NULL
+ },
+ { "ms_strftime", NULL, ms_time_char_table, "_-0^#", "EO",
+ ms_strftime_flag_specs, ms_strftime_flag_pairs,
+ FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
+ NULL, NULL
+ }
+};
+
+/* Default overrides for printf, scanf and strftime. */
+const target_ovr_attr mingw_formatter_attribute_overrides[4] =
+{
+ { "ms_printf", "printf" },
+ { "ms_scanf", "scanf" },
+ { "ms_strftime", "strftime" }
+};
Index: gcc/gcc/config/i386/t-cygming
===================================================================
--- gcc.orig/gcc/config/i386/t-cygming
+++ gcc/gcc/config/i386/t-cygming
@@ -29,4 +29,10 @@ winnt-stubs.o: $(srcdir)/config/i386/win
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt-stubs.c
+msformat-c.o: $(srcdir)/config/i386/msformat-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+ $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/msformat-c.c
+
STMP_FIXINC=stmp-fixinc
Index: gcc/gcc/doc/extend.texi
===================================================================
--- gcc.orig/gcc/doc/extend.texi
+++ gcc/gcc/doc/extend.texi
@@ -2204,13 +2204,17 @@ for consistency with the @code{printf} s
@code{my_format}.
The parameter @var{archetype} determines how the format string is
-interpreted, and should be @code{printf}, @code{scanf}, @code{strftime}
-or @code{strfmon}. (You can also use @code{__printf__},
-@code{__scanf__}, @code{__strftime__} or @code{__strfmon__}.) The
-parameter @var{string-index} specifies which argument is the format
-string argument (starting from 1), while @var{first-to-check} is the
-number of the first argument to check against the format string. For
-functions where the arguments are not available to be checked (such as
+interpreted, and should be @code{printf}, @code{scanf}, @code{strftime},
+@code{gnu_printf}, @code{gnu_scanf}, @code{gnu_strftime} or
+@code{strfmon}. (You can also use @code{__printf__},
+@code{__scanf__}, @code{__strftime__} or @code{__strfmon__}.) On
+mingw targets there is also @code{ms_printf}, @code{ms_scanf}, and
+@code{ms_strftime} present. The none target specific formatters are
+always the variant of the system. The parameter @var{string-index}
+specifies which argument is the format string argument (starting
+from 1), while @var{first-to-check} is the number of the first
+argument to check against the format string. For functions
+where the arguments are not available to be checked (such as
@code{vprintf}), specify the third parameter as zero. In this case the
compiler only checks the format string for consistency. For
@code{strftime} formats, the third parameter is required to be zero.
Index: gcc/gcc/doc/tm.texi
===================================================================
--- gcc.orig/gcc/doc/tm.texi
+++ gcc/gcc/doc/tm.texi
@@ -10311,6 +10311,18 @@ If defined, this macro is the number of
@code{TARGET_FORMAT_TYPES}.
@end defmac
+@defmac TARGET_OVERRIDES_FORMAT_ATTRIBUTES
+If defined, this macro is the name of a global variable containg
+target-specific format overrides for the @option{-Wformat} option. The
+default is to have no target-specific format overrides. This depends, that
+@code{TARGET_FORMAT_TYPES} is defined too.
+@end defmac
+
+@defmac TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT
+If defined, this macro is the number of entries in
+@code{}.
+@end defmac
+
@deftypefn {Target Hook} bool TARGET_RELAXED_ORDERING
If set to @code{true}, means that the target's memory model does not
guarantee that loads which do not depend on one another will access
Index: gcc/gcc/testsuite/gcc.dg/format/sys_formatter.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.dg/format/sys_formatter.c
@@ -0,0 +1,20 @@
+/* Test system default printf formatter specifiers. */
+/* Origin: Kai Tietz */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89" } */
+
+#define USE_SYSTEM_FORMATS
+#include
+
+__attribute__((format(printf, 1, 2))) void foo (const char *, ...);
+
+#ifdef _WIN32
+#define FORMATTER_TEXT "%I64d %I32d %ld %d\n"
+#else
+#define FORMATTER_TEXT "%lld %ld %ld %d"
+#endif
+
+void bar (long long v1, long v2, int v3)
+{
+ foo (FORMATTER_TEXT, v1, v2, v2, v3);
+}
Index: gcc/gcc/testsuite/gcc.dg/format/format.h
===================================================================
--- gcc.orig/gcc/testsuite/gcc.dg/format/format.h
+++ gcc/gcc/testsuite/gcc.dg/format/format.h
@@ -1,6 +1,29 @@
/* Format checking tests: common header. */
/* Origin: Joseph Myers */
+#if defined (_WIN32) && !defined (__CYGWIN__)
+#define SYSTEM_PRINTF(FMTPOS, WILDARG) __attribute__((format(ms_printf, FMTPOS, WILDARG)))
+#define SYSTEM_SCANF(FMTPOS, WILDARG) __attribute__((format(ms_scanf, FMTPOS, WILDARG)))
+#define SYSTEM_STRFTIME(FMTPOS) __attribute__((__format__(ms_strftime, FMTPOS, 0)))
+#else
+#define SYSTEM_PRINTF(FMTPOS, WILDARG) __attribute__((format(gnu_printf, FMTPOS, WILDARG)))
+#define SYSTEM_SCANF(FMTPOS, WILDARG) __attribute__((format(gnu_scanf, FMTPOS, WILDARG)))
+#define SYSTEM_STRFTIME(FMTPOS) __attribute__((__format__(gnu_strftime, FMTPOS, 0)))
+#endif
+
+#if !defined (USE_SYSTEM_FORMATS)
+#define __printf__ __gnu_printf__
+#define __scanf__ __gnu_scanf__
+#define __strftime__ __gnu_strftime__
+#define USE_PRINTF(FMTPOS, WILDARG) __attribute__((format(gnu_printf, FMTPOS, WILDARG)))
+#define USE_SCANF(FMTPOS, WILDARG) __attribute__((format(gnu_scanf, FMTPOS, WILDARG)))
+#define USE_STRFTIME(FMTPOS) __attribute__((__format__(gnu_strftime, FMTPOS, 0)))
+#else
+#define USE_PRINTF(FMTPOS, WILDARG)
+#define USE_SCANF(FMTPOS, WILDARG)
+#define USE_STRFTIME(FMTPOS)
+#endif
+
#include
#include
@@ -70,3 +93,75 @@ extern size_t strftime (char *restrict,
const struct tm *restrict);
extern ssize_t strfmon (char *restrict, size_t, const char *restrict, ...);
+
+/* Mingw specific part. */
+#if !defined (USE_SYSTEM_FORMATS) && defined(_WIN32)
+extern USE_PRINTF(2,3) int fprintf_gnu (FILE *restrict, const char *restrict, ...);
+#undef fprintf
+#define fprintf fprintf_gnu
+
+extern USE_PRINTF(1,2) int printf_gnu (const char *restrict, ...);
+#undef printf
+#define printf printf_gnu
+
+extern USE_PRINTF(2,3) int fprintf_unlocked_gnu (FILE *restrict, const char *restrict, ...);
+#undef fprintf_unlocked
+#define fprintf_unlocked fprintf_unlocked_gnu
+
+extern USE_PRINTF(1,2)int printf_unlocked_gnu (const char *restrict, ...);
+#undef printf_unlocked
+#define printf_unlocked printf_unlocked_gnu
+
+extern USE_PRINTF(2,3) int sprintf_gnu (char *restrict, const char *restrict, ...);
+#undef sprintf
+#define sprintf sprintf_gnu
+
+extern USE_PRINTF(2,0) int vfprintf_gnu (FILE *restrict, const char *restrict, va_list);
+#undef vsprintf
+#define vsprintf vsprintf_gnu
+
+extern USE_PRINTF(1,0) int vprintf_gnu (const char *restrict, va_list);
+#undef vprintf
+#define vprintf vprintf_gnu
+
+extern USE_PRINTF(2,0) int vsprintf_gnu (char *restrict, const char *restrict, va_list);
+#undef vsprintf
+#define vsprintf vsprintf_gnu
+
+extern USE_PRINTF(3,4) int snprintf_gnu (char *restrict, size_t, const char *restrict, ...);
+#undef snprintf
+#define snprintf snprintf_gnu
+
+extern USE_PRINTF(3,0) int vsnprintf_gnu (char *restrict, size_t, const char *restrict, va_list);
+#undef vsnprintf
+#define vsnprintf vsnprintf_gnu
+
+extern USE_SCANF(2,3) int fscanf_gnu (FILE *restrict, const char *restrict, ...);
+#undef fscanf
+#define fscanf fscanf_gnu
+
+extern USE_SCANF(1,2) int scanf_gnu (const char *restrict, ...);
+#undef scanf
+#define scanf scanf_gnu
+
+extern USE_SCANF(2,3) int sscanf_gnu (const char *restrict, const char *restrict, ...);
+#undef sscanf
+#define sscanf sscanf_gnu
+
+extern USE_SCANF(2,0) int vfscanf_gnu (FILE *restrict, const char *restrict, va_list);
+#undef vfscanf
+#define vfscanf vfscanf_gnu
+
+extern USE_SCANF(1,0) int vscanf_gnu (const char *restrict, va_list);
+#undef vscanf
+#define vscanf vscanf_gnu
+
+extern USE_SCANF(2,0) int vsscanf_gnu (const char *restrict, const char *restrict, va_list);
+#undef vsscanf
+#define vsscanf vsscanf_gnu
+
+extern USE_STRFTIME(3) size_t strftime_gnu (char *restrict, size_t, const char *restrict,
+ const struct tm *restrict);
+#undef strftime
+#define strftime strftime_gnu
+#endif
=