This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch]: Fix PR/40786 Windows %I32 format confusion
2009/8/23 Joseph S. Myers <joseph@codesourcery.com>:
> On Sun, 23 Aug 2009, Kai Tietz wrote:
>
>> Tested for i686-pc-mingw32 and for x86_64-pc-mingw32. Ok for apply?
>
> Did this fix the previously observed test failures?
>
>> + ? ? ?if (types->scalar_identity_flag
>> + ? ? ? && cur_type && wanted_type
>> + ? ? ? && TYPE_SIZE (cur_type) == TYPE_SIZE (wanted_type))
>> + ? ? continue;
>
> This looks like it will allow arguments of floating-point or pointer
> types. ?I believe scalar_identity_flag should only allow integer types (if
> the wanted type is an integer type) and should be checking TYPE_PRECISION;
> that is, something like (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
> || (INTEGRAL_TYPE_P (cur_type) && INTEGRAL_TYPE_P (wanted_type))) &&
> TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type). ?You should add
> testcases that float is not accepted for %I32, double is not accepted for
> %I64, but that 32-bit enums are accepted for %I32.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
Ok, I adjusted the check as you suggested. And I add new testcase
gcc.dg/format/ms-format2.c. Also I extend the ms-format1.c to check
enum's and long type for I32, too.
Ok for apply?
Cheers,
Kai
--
| (\_/) This is Bunny. Copy and paste
| (='.'=) Bunny into your signature to help
| (")_(") him gain world domination
Index: gcc/gcc/c-format.c
===================================================================
--- gcc.orig/gcc/c-format.c 2009-07-07 18:10:24.000000000 +0200
+++ gcc/gcc/c-format.c 2009-08-23 21:10:58.218496700 +0200
@@ -259,6 +259,8 @@
tree wanted_type;
/* The name of this type to use in diagnostics. */
const char *wanted_type_name;
+ /* Should be type checked just for scalar width identity. */
+ int scalar_identity_flag;
/* The level of indirection through pointers at which this type occurs. */
int pointer_count;
/* Whether, when pointer_count is 1, to allow any character type when
@@ -288,33 +290,33 @@
static const format_length_info printf_length_specs[] =
{
- { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
- { "q", FMT_LEN_ll, STD_EXT, NO_FMT },
- { "L", FMT_LEN_L, STD_C89, NO_FMT },
- { "z", FMT_LEN_z, STD_C99, NO_FMT },
- { "Z", FMT_LEN_z, STD_EXT, NO_FMT },
- { "t", FMT_LEN_t, STD_C99, NO_FMT },
- { "j", FMT_LEN_j, STD_C99, NO_FMT },
- { "H", FMT_LEN_H, STD_EXT, NO_FMT },
- { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT },
- { NO_FMT, NO_FMT }
+ { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
+ { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
+ { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
+ { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
+ { "Z", FMT_LEN_z, STD_EXT, NO_FMT, 0 },
+ { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
+ { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
+ { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
+ { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
/* Length specifiers valid for asm_fprintf. */
static const format_length_info asm_fprintf_length_specs[] =
{
- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 },
- { "w", FMT_LEN_none, STD_C89, NO_FMT },
- { NO_FMT, NO_FMT }
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
+ { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
/* Length specifiers valid for GCC diagnostics. */
static const format_length_info gcc_diag_length_specs[] =
{
- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 },
- { "w", FMT_LEN_none, STD_C89, NO_FMT },
- { NO_FMT, NO_FMT }
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
+ { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
/* The custom diagnostics all accept the same length specifiers. */
@@ -325,16 +327,16 @@
/* This differs from printf_length_specs only in that "Z" is not accepted. */
static const format_length_info scanf_length_specs[] =
{
- { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
- { "q", FMT_LEN_ll, STD_EXT, NO_FMT },
- { "L", FMT_LEN_L, STD_C89, NO_FMT },
- { "z", FMT_LEN_z, STD_C99, NO_FMT },
- { "t", FMT_LEN_t, STD_C99, NO_FMT },
- { "j", FMT_LEN_j, STD_C99, NO_FMT },
- { "H", FMT_LEN_H, STD_EXT, NO_FMT },
- { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT },
- { NO_FMT, NO_FMT }
+ { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
+ { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
+ { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
+ { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
+ { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
+ { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
+ { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
+ { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
@@ -343,16 +345,16 @@
static const format_length_info strfmon_length_specs[] =
{
/* A GNU extension. */
- { "L", FMT_LEN_L, STD_C89, NO_FMT },
- { NO_FMT, NO_FMT }
+ { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
/* For now, the Fortran front-end routines only use l as length modifier. */
static const format_length_info gcc_gfc_length_specs[] =
{
- { "l", FMT_LEN_l, STD_C89, NO_FMT },
- { NO_FMT, NO_FMT }
+ { "l", FMT_LEN_l, STD_C89, NO_FMT, 0 },
+ { NO_FMT, NO_FMT, 0 }
};
@@ -1479,6 +1481,7 @@
const format_char_info *fci = NULL;
char flag_chars[256];
int alloc_flag = 0;
+ int scalar_identity_flag = 0;
const char *format_start = format_chars;
if (*format_chars == 0)
{
@@ -1612,6 +1615,7 @@
width_wanted_type.wanted_type_name = NULL;
width_wanted_type.pointer_count = 0;
width_wanted_type.char_lenient_flag = 0;
+ width_wanted_type.scalar_identity_flag = 0;
width_wanted_type.writing_in_flag = 0;
width_wanted_type.reading_from_flag = 0;
width_wanted_type.name = _("field width");
@@ -1714,6 +1718,7 @@
precision_wanted_type.wanted_type_name = NULL;
precision_wanted_type.pointer_count = 0;
precision_wanted_type.char_lenient_flag = 0;
+ precision_wanted_type.scalar_identity_flag = 0;
precision_wanted_type.writing_in_flag = 0;
precision_wanted_type.reading_from_flag = 0;
precision_wanted_type.name = _("field precision");
@@ -1767,6 +1772,7 @@
length_chars = NULL;
length_chars_val = FMT_LEN_none;
length_chars_std = STD_C89;
+ scalar_identity_flag = 0;
if (fli)
{
while (fli->name != 0
@@ -1787,6 +1793,7 @@
length_chars = fli->name;
length_chars_val = fli->index;
length_chars_std = fli->std;
+ scalar_identity_flag = fli->scalar_identity_flag;
}
i = strlen (flag_chars);
flag_chars[i++] = fki->length_code_char;
@@ -2075,6 +2082,9 @@
wanted_type_ptr->char_lenient_flag = 0;
if (strchr (fci->flags2, 'c') != 0)
wanted_type_ptr->char_lenient_flag = 1;
+ wanted_type_ptr->scalar_identity_flag = 0;
+ if (scalar_identity_flag)
+ wanted_type_ptr->scalar_identity_flag = 1;
wanted_type_ptr->writing_in_flag = 0;
wanted_type_ptr->reading_from_flag = 0;
if (alloc_flag)
@@ -2259,6 +2269,12 @@
&& (!pedantic || i < 2)
&& char_type_flag)
continue;
+ if (types->scalar_identity_flag
+ && (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
+ || (INTEGRAL_TYPE_P (cur_type)
+ && INTEGRAL_TYPE_P (wanted_type)))
+ && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type))
+ continue;
/* Now we have a type mismatch. */
format_type_warning (types->name, format_start, format_length,
wanted_type, types->pointer_count,
Index: gcc/gcc/c-format.h
===================================================================
--- gcc.orig/gcc/c-format.h 2009-02-21 20:00:36.000000000 +0100
+++ gcc/gcc/c-format.h 2009-08-22 19:20:02.611000000 +0200
@@ -96,6 +96,10 @@
const char *double_name;
enum format_lengths double_index;
enum format_std_version double_std;
+
+ /* If this flag is set, just scalar width identity is checked, and
+ not the type identity itself. */
+ int scalar_identity_flag;
} format_length_info;
Index: gcc/gcc/config/i386/msformat-c.c
===================================================================
--- gcc.orig/gcc/config/i386/msformat-c.c 2009-07-06 14:02:16.000000000 +0200
+++ gcc/gcc/config/i386/msformat-c.c 2009-08-22 19:22:40.323000000 +0200
@@ -36,12 +36,12 @@
static format_length_info ms_printf_length_specs[] =
{
- { "h", FMT_LEN_h, STD_C89, NULL, FMT_LEN_none, STD_C89 },
- { "l", FMT_LEN_l, STD_C89, NULL, FMT_LEN_none, STD_C89 },
- { "I32", FMT_LEN_l, STD_EXT, NULL, FMT_LEN_none, STD_C89 },
- { "I64", FMT_LEN_ll, STD_EXT, NULL, FMT_LEN_none, STD_C89 },
- { "I", FMT_LEN_L, STD_EXT, NULL, FMT_LEN_none, STD_C89 },
- { NULL, FMT_LEN_none, STD_C89, NULL, FMT_LEN_none, STD_C89 }
+ { "h", FMT_LEN_h, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 },
+ { "l", FMT_LEN_l, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 },
+ { "I32", FMT_LEN_l, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
+ { "I64", FMT_LEN_ll, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
+ { "I", FMT_LEN_L, STD_EXT, NULL, FMT_LEN_none, STD_C89, 0 },
+ { NULL, FMT_LEN_none, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 }
};
static const format_flag_spec ms_printf_flag_specs[] =
Index: gcc/gcc/testsuite/gcc.dg/format/ms-format2.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.dg/format/ms-format2.c 2009-08-23 21:35:33.930496700 +0200
@@ -0,0 +1,23 @@
+/* Test for printf formats. Formats using extensions to the standard
+ should be rejected in strict pedantic mode. But allowed by -Wno-pedantic-ms-format.
+*/
+/* Origin: Kai Tietz <kai.tietz@onevision.com> */
+/* { dg-do compile { target { *-*-mingw* } } } */
+/* { dg-options "-std=iso9899:1999 -pedantic -Wformat -Wno-pedantic-ms-format" } */
+
+#define USE_SYSTEM_FORMATS
+#include "format.h"
+
+#ifdef _WIN64
+#define XXX "%I64x"
+#else
+#define XXX "%I32x"
+#endif
+
+void
+foo (float f, double d, void *p)
+{
+ printf (XXX, p); /* { dg-warning "format" "bad argument types" } */
+ printf ("%I32x", f); /* { dg-warning "format" "bad argument types" } */
+ printf ("%I64x", d); /* { dg-warning "format" "bad argument types" } */
+}
Index: gcc/gcc/testsuite/gcc.dg/format/ms-format1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.dg/format/ms-format1.c 2009-08-23 21:38:46.000000000 +0200
+++ gcc/gcc/testsuite/gcc.dg/format/ms-format1.c 2009-08-23 21:26:25.457496700 +0200
@@ -8,10 +8,16 @@
#define USE_SYSTEM_FORMATS
#include "format.h"
+enum en1 { A=0, B=1 };
+typedef enum { _A=0, _B=1 } en2;
+
void
-foo (int i, long long ll, size_t z)
+foo (int i, long l, long long ll, size_t z, enum en1 e1, en2 e2)
{
printf ("%I32d", i);
+ printf ("%I32d", l);
+ printf ("%I32d", e1);
+ printf ("%I32d", e2);
printf ("%I64x", ll);
printf ("%Ix", z);
}