c-format.h (format_kind_info): Add alloc_char field.

* c-format.h (format_kind_info): Add alloc_char field.
	* c-format.c (scanf_flag_specs): Add 'm'.
	(scanf_flag_pairs): Add 'a', 'm' pair.
	(scan_char_table): Allow 'm' modifier for c, s, [, C and S.
	(format_types_orig): Add alloc_char fields.
	(check_format_info_main): Rename aflag to alloc_flag.
	Handle fki->alloc_char. modifier after width and before length
	modifiers.  Move FMT_FLAG_SCANF_A_KLUDGE handling before
	length modifiers as well.
	* config/sol2-c.c (solaris_format_types): Add alloc_char field.

	* gcc.dg/format/c90-scanf-5.c: New test.
	* gcc.dg/format/c99-scanf-4.c: New test.
	* gcc.dg/format/ext-7.c: New test.
	* gcc.dg/format/ext-8.c: New test.

From-SVN: r128555
This commit is contained in:
Jakub Jelinek 2007-09-18 00:07:46 +02:00 committed by Jakub Jelinek
parent abc2dd3c9e
commit 9cef5f55ff
9 changed files with 247 additions and 38 deletions

View File

@ -1,5 +1,16 @@
2007-09-18 Jakub Jelinek <jakub@redhat.com>
* c-format.h (format_kind_info): Add alloc_char field.
* c-format.c (scanf_flag_specs): Add 'm'.
(scanf_flag_pairs): Add 'a', 'm' pair.
(scan_char_table): Allow 'm' modifier for c, s, [, C and S.
(format_types_orig): Add alloc_char fields.
(check_format_info_main): Rename aflag to alloc_flag.
Handle fki->alloc_char. modifier after width and before length
modifiers. Move FMT_FLAG_SCANF_A_KLUDGE handling before
length modifiers as well.
* config/sol2-c.c (solaris_format_types): Add alloc_char field.
PR middle-end/33423
* builtins.c (expand_builtin_memory_chk): Handle COMPOUND_EXPRs
returned by build_call_expr.

View File

@ -437,6 +437,7 @@ static const format_flag_spec 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 },
{ 'm', 0, 0, N_("'m' flag"), N_("the 'm' 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 },
@ -448,6 +449,7 @@ static const format_flag_spec scanf_flag_specs[] =
static const format_flag_pair scanf_flag_pairs[] =
{
{ '*', 'L', 0, 0 },
{ 'a', 'm', 0, 0 },
{ 0, 0, 0, 0 }
};
@ -663,17 +665,17 @@ static const format_char_info scan_char_table[] =
{ "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL },
{ "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
{ "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
{ "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, 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 },
{ "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "cW", NULL },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW", NULL },
{ "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "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, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* C99 conversion specifiers. */
{ "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
{ "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
/* X/Open conversion specifiers. */
{ "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL },
{ "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
};
@ -716,59 +718,59 @@ static const format_kind_info format_types_orig[] =
{ "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',
'w', 0, 'p', 0, 'L', 0,
&integer_type_node, &integer_type_node
},
{ "asm_fprintf", asm_fprintf_length_specs, asm_fprintf_char_table, " +#0-", NULL,
asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
'w', 0, 'p', 0, 'L',
'w', 0, 'p', 0, 'L', 0,
NULL, NULL
},
{ "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "q+", NULL,
gcc_diag_flag_specs, gcc_diag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
0, 0, 'p', 0, 'L', 0,
NULL, &integer_type_node
},
{ "gcc_tdiag", gcc_tdiag_length_specs, gcc_tdiag_char_table, "q+", NULL,
gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
0, 0, 'p', 0, 'L', 0,
NULL, &integer_type_node
},
{ "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "q+", NULL,
gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
0, 0, 'p', 0, 'L', 0,
NULL, &integer_type_node
},
{ "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "q+#", NULL,
gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
0, 0, 'p', 0, 'L', 0,
NULL, &integer_type_node
},
{ "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "", NULL,
NULL, gcc_gfc_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
NULL, NULL
},
{ "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',
'w', 0, 0, '*', 'L', 'm',
NULL, NULL
},
{ "strftime", NULL, time_char_table, "_-0^#", "EO",
strftime_flag_specs, strftime_flag_pairs,
FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0,
FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
NULL, NULL
},
{ "strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
strfmon_flag_specs, strfmon_flag_pairs,
FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L',
FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
NULL, NULL
}
};
@ -1482,7 +1484,7 @@ check_format_info_main (format_check_results *res,
const format_length_info *fli = NULL;
const format_char_info *fci = NULL;
char flag_chars[256];
int aflag = 0;
int alloc_flag = 0;
const char *format_start = format_chars;
if (*format_chars == 0)
{
@ -1741,6 +1743,31 @@ check_format_info_main (format_check_results *res,
}
}
if (fki->alloc_char && fki->alloc_char == *format_chars)
{
i = strlen (flag_chars);
flag_chars[i++] = fki->alloc_char;
flag_chars[i] = 0;
format_chars++;
}
/* Handle the scanf allocation kludge. */
if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
{
if (*format_chars == 'a' && !flag_isoc99)
{
if (format_chars[1] == 's' || format_chars[1] == 'S'
|| format_chars[1] == '[')
{
/* 'a' is used as a flag. */
i = strlen (flag_chars);
flag_chars[i++] = 'a';
flag_chars[i] = 0;
format_chars++;
}
}
}
/* Read any length modifier, if this kind of format has them. */
fli = fki->length_char_specs;
length_chars = NULL;
@ -1803,23 +1830,6 @@ check_format_info_main (format_check_results *res,
}
}
/* Handle the scanf allocation kludge. */
if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
{
if (*format_chars == 'a' && !flag_isoc99)
{
if (format_chars[1] == 's' || format_chars[1] == 'S'
|| format_chars[1] == '[')
{
/* 'a' is used as a flag. */
i = strlen (flag_chars);
flag_chars[i++] = 'a';
flag_chars[i] = 0;
format_chars++;
}
}
}
format_char = *format_chars;
if (format_char == 0
|| (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
@ -1892,7 +1902,9 @@ check_format_info_main (format_check_results *res,
if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
&& strchr (flag_chars, 'a') != 0)
aflag = 1;
alloc_flag = 1;
if (fki->alloc_char && strchr (flag_chars, fki->alloc_char) != 0)
alloc_flag = 1;
if (fki->suppression_char
&& strchr (flag_chars, fki->suppression_char) != 0)
@ -2064,13 +2076,13 @@ check_format_info_main (format_check_results *res,
wanted_type_ptr->wanted_type = wanted_type;
wanted_type_ptr->wanted_type_name = wanted_type_name;
wanted_type_ptr->pointer_count = fci->pointer_count + aflag;
wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag;
wanted_type_ptr->char_lenient_flag = 0;
if (strchr (fci->flags2, 'c') != 0)
wanted_type_ptr->char_lenient_flag = 1;
wanted_type_ptr->writing_in_flag = 0;
wanted_type_ptr->reading_from_flag = 0;
if (aflag)
if (alloc_flag)
wanted_type_ptr->writing_in_flag = 1;
else
{

View File

@ -236,6 +236,8 @@ typedef struct
specifiers, but is used to check for bad combinations such as length
modifier with assignment suppression in scanf. */
int length_code_char;
/* Assignment-allocation flag character ('m' in scanf), otherwise 0. */
int alloc_char;
/* Pointer to type of argument expected if '*' is used for a width,
or NULL if '*' not used for widths. */
tree *width_type;

View File

@ -1,5 +1,5 @@
/* Solaris support needed only by C/C++ frontends.
Copyright (C) 2004, 2005 , 2007 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
Contributed by CodeSourcery, LLC.
This file is part of GCC.
@ -73,7 +73,7 @@ const format_kind_info solaris_format_types[] = {
{ "cmn_err", cmn_err_length_specs, cmn_err_char_table, "", NULL,
cmn_err_flag_specs, cmn_err_flag_pairs,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
'w', 0, 0, 0, 'L',
'w', 0, 0, 0, 'L', 0,
&integer_type_node, &integer_type_node
}
};

View File

@ -1,5 +1,10 @@
2007-09-18 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/format/c90-scanf-5.c: New test.
* gcc.dg/format/c99-scanf-4.c: New test.
* gcc.dg/format/ext-7.c: New test.
* gcc.dg/format/ext-8.c: New test.
PR middle-end/33423
* gcc.c-torture/compile/20070915-1.c: New test.

View File

@ -0,0 +1,19 @@
/* Test for scanf formats. Formats using extensions to the standard
should be rejected in strict pedantic mode.
*/
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
#include "format.h"
void
foo (char **sp, wchar_t **lsp)
{
/* m assignment-allocation modifier, recognized in both C90
and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
scanf ("%ms", sp); /* { dg-warning "C" "%ms" } */
scanf ("%mS", lsp); /* { dg-warning "C" "%mS" } */
scanf ("%mls", lsp); /* { dg-warning "C" "%mls" } */
scanf ("%m[bcd]", sp); /* { dg-warning "C" "%m[]" } */
scanf ("%ml[bcd]", lsp); /* { dg-warning "C" "%ml[]" } */
}

View File

@ -0,0 +1,19 @@
/* Test for scanf formats. Formats using extensions to the standard
should be rejected in strict pedantic mode.
*/
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
#include "format.h"
void
foo (char **sp, wchar_t **lsp)
{
/* m assignment-allocation modifier, recognized in both C90
and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
scanf ("%ms", sp); /* { dg-warning "C" "%ms" } */
scanf ("%mS", lsp); /* { dg-warning "C" "%mS" } */
scanf ("%mls", lsp); /* { dg-warning "C" "%mls" } */
scanf ("%m[bcd]", sp); /* { dg-warning "C" "%m[]" } */
scanf ("%ml[bcd]", lsp); /* { dg-warning "C" "%ml[]" } */
}

View File

@ -0,0 +1,85 @@
/* Test for scanf formats. %a and %m extensions. */
/* { dg-do compile } */
/* { dg-options "-std=gnu89 -Wformat" } */
#include "format.h"
void
foo (char **sp, wchar_t **lsp, int *ip, float *fp, void **pp, double *dp)
{
/* %a formats for allocation, only recognized in C90 mode, are a
GNU extension. Followed by other characters, %a is not treated
specially.
*/
scanf ("%as", sp);
scanf ("%aS", lsp);
scanf ("%las", dp);
scanf ("%la", lsp); /* { dg-warning "but argument 2 has type" } */
scanf ("%las", lsp); /* { dg-warning "but argument 2 has type" } */
scanf ("%a[bcd]", sp);
scanf ("%la[bcd]", dp);
scanf ("%*as");
scanf ("%*aS");
scanf ("%*las"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*a[bcd]");
scanf ("%*la[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%10as", sp);
scanf ("%5aS", lsp);
scanf ("%9las", dp);
scanf ("%25a[bcd]", sp);
scanf ("%48la[bcd]", dp);
scanf ("%*10as");
scanf ("%*5aS");
scanf ("%*9las"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*25a[bcd]");
scanf ("%*48la[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
/* m assignment-allocation modifier, recognized in both C90
and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
scanf ("%ms", sp);
scanf ("%mS", lsp);
scanf ("%mls", lsp);
scanf ("%m[bcd]", sp);
scanf ("%ml[bcd]", lsp);
scanf ("%mc", sp);
scanf ("%mlc", lsp);
scanf ("%mC", lsp);
scanf ("%*ms");
scanf ("%*mS");
scanf ("%*mls"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*m[bcd]");
scanf ("%*ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*mc");
scanf ("%*mlc"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*mC");
scanf ("%10ms", sp);
scanf ("%5mS", lsp);
scanf ("%9mls", lsp);
scanf ("%25m[bcd]", sp);
scanf ("%41ml[bcd]", lsp);
scanf ("%131mc", sp);
scanf ("%27mlc", lsp);
scanf ("%2mC", lsp);
scanf ("%*10ms");
scanf ("%*5mS");
scanf ("%*9mls"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*25m[bcd]");
scanf ("%*41ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*131mc");
scanf ("%*27mlc"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*2mC");
scanf ("%md", ip); /* { dg-warning "flag used with" } */
scanf ("%mi", ip); /* { dg-warning "flag used with" } */
scanf ("%mo", ip); /* { dg-warning "flag used with" } */
scanf ("%mu", ip); /* { dg-warning "flag used with" } */
scanf ("%mx", ip); /* { dg-warning "flag used with" } */
scanf ("%me", fp); /* { dg-warning "flag used with" } */
scanf ("%mf", fp); /* { dg-warning "flag used with" } */
scanf ("%mg", fp); /* { dg-warning "flag used with" } */
scanf ("%mp", pp); /* { dg-warning "flag used with" } */
scanf ("%mas", sp); /* { dg-warning "flag together" } */
scanf ("%maS", lsp); /* { dg-warning "flag together" } */
scanf ("%ma[bcd]", sp); /* { dg-warning "flag together" } */
}

View File

@ -0,0 +1,56 @@
/* Test for scanf formats. %m extensions. */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
#include "format.h"
void
foo (char **sp, wchar_t **lsp, int *ip, float *fp, void **pp)
{
/* m assignment-allocation modifier, recognized in both C90
and C99 modes, is a POSIX and ISO/IEC WDTR 24731-2 extension. */
scanf ("%ms", sp);
scanf ("%mS", lsp);
scanf ("%mls", lsp);
scanf ("%m[bcd]", sp);
scanf ("%ml[bcd]", lsp);
scanf ("%mc", sp);
scanf ("%mlc", lsp);
scanf ("%mC", lsp);
scanf ("%*ms");
scanf ("%*mS");
scanf ("%*mls"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*m[bcd]");
scanf ("%*ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*mc");
scanf ("%*mlc"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*mC");
scanf ("%10ms", sp);
scanf ("%5mS", lsp);
scanf ("%9mls", lsp);
scanf ("%25m[bcd]", sp);
scanf ("%41ml[bcd]", lsp);
scanf ("%131mc", sp);
scanf ("%27mlc", lsp);
scanf ("%2mC", lsp);
scanf ("%*10ms");
scanf ("%*5mS");
scanf ("%*9mls"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*25m[bcd]");
scanf ("%*41ml[bcd]"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*131mc");
scanf ("%*27mlc"); /* { dg-warning "assignment suppression and length modifier" } */
scanf ("%*2mC");
scanf ("%md", ip); /* { dg-warning "flag used with" } */
scanf ("%mi", ip); /* { dg-warning "flag used with" } */
scanf ("%mo", ip); /* { dg-warning "flag used with" } */
scanf ("%mu", ip); /* { dg-warning "flag used with" } */
scanf ("%mx", ip); /* { dg-warning "flag used with" } */
scanf ("%ma", fp); /* { dg-warning "flag used with" } */
scanf ("%mA", fp); /* { dg-warning "flag used with" } */
scanf ("%me", fp); /* { dg-warning "flag used with" } */
scanf ("%mf", fp); /* { dg-warning "flag used with" } */
scanf ("%mg", fp); /* { dg-warning "flag used with" } */
scanf ("%mp", pp); /* { dg-warning "flag used with" } */
}