Commit 843f104d by Joseph Myers Committed by Joseph Myers

Add strftime format checking support for C2x %OB and %Ob (bug 82752).

C2x adds strftime %OB and %Ob formats, for alternative forms of month
names (for mainly Slavic languages where a month name on its own is
declined differently from a month name together with a date within
that month).  This patch adds corresponding format checking support.
(glibc support for these formats was added in glibc 2.27.)

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

	PR c/82752
gcc/c-family:
	* c-format.c (C_STD_VER): Handle C2x.
	(C_STD_NAME): Likewise.
	(strftime_flag_specs): Add 'O' modifier with 'p' flag.
	(time_char_table): Use separate entry for 'B' and 'b', with 'O'
	modifier allowed and 'p' flag.
	* c-format.h (enum format_std_version): Add STD_C2X.
	(struct format_char_info): Mention 'p' in comment on flags2.

gcc/testsuite:
	* gcc.dg/format/c2x-strftime-1.c: New test.

From-SVN: r276605
parent daa94de2
2019-10-04 Joseph Myers <joseph@codesourcery.com>
PR c/82752
* c-format.c (C_STD_VER): Handle C2x.
(C_STD_NAME): Likewise.
(strftime_flag_specs): Add 'O' modifier with 'p' flag.
(time_char_table): Use separate entry for 'B' and 'b', with 'O'
modifier allowed and 'p' flag.
* c-format.h (enum format_std_version): Add STD_C2X.
(struct format_char_info): Mention 'p' in comment on flags2.
2019-10-01 David Malcolm <dmalcolm@redhat.com> 2019-10-01 David Malcolm <dmalcolm@redhat.com>
* c-opts.c (c_diagnostic_finalizer): Temporarily clear prefix when * c-opts.c (c_diagnostic_finalizer): Temporarily clear prefix when
......
...@@ -404,9 +404,11 @@ decode_format_attr (const_tree fntype, tree atname, tree args, ...@@ -404,9 +404,11 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
/* The C standard version we are checking formats against when pedantic. */ /* The C standard version we are checking formats against when pedantic. */
#define C_STD_VER ((int) (c_dialect_cxx () \ #define C_STD_VER ((int) (c_dialect_cxx () \
? CPLUSPLUS_STD_VER \ ? CPLUSPLUS_STD_VER \
: (flag_isoc99 \ : (flag_isoc2x \
? STD_C99 \ ? STD_C2X \
: (flag_isoc94 ? STD_C94 : STD_C89)))) : (flag_isoc99 \
? STD_C99 \
: (flag_isoc94 ? STD_C94 : STD_C89)))))
/* The name to give to the standard version we are warning about when /* The name to give to the standard version we are warning about when
pedantic. FEATURE_VER is the version in which the feature warned out pedantic. FEATURE_VER is the version in which the feature warned out
appeared, which is higher than C_STD_VER. */ appeared, which is higher than C_STD_VER. */
...@@ -415,7 +417,9 @@ decode_format_attr (const_tree fntype, tree atname, tree args, ...@@ -415,7 +417,9 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
: "ISO C++11") \ : "ISO C++11") \
: ((FEATURE_VER) == STD_EXT \ : ((FEATURE_VER) == STD_EXT \
? "ISO C" \ ? "ISO C" \
: "ISO C90")) : ((FEATURE_VER) == STD_C2X \
? "ISO C17" \
: "ISO C90")))
/* Adjust a C standard version, which may be STD_C9L, to account for /* Adjust a C standard version, which may be STD_C9L, to account for
-Wno-long-long. Returns other standard versions unchanged. */ -Wno-long-long. Returns other standard versions unchanged. */
#define ADJ_STD(VER) ((int) ((VER) == STD_C9L \ #define ADJ_STD(VER) ((int) ((VER) == STD_C9L \
...@@ -653,6 +657,7 @@ static const format_flag_spec strftime_flag_specs[] = ...@@ -653,6 +657,7 @@ static const format_flag_spec strftime_flag_specs[] =
{ 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 }, { 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 },
{ 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 }, { 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 },
{ 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT }, { 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT },
{ 'O', 'p', 0, 0, NULL, N_("the 'O' modifier"), STD_C2X },
{ 0, 0, 0, 0, NULL, NULL, STD_C89 } { 0, 0, 0, 0, NULL, NULL, STD_C89 }
}; };
...@@ -887,7 +892,8 @@ static const format_char_info scan_char_table[] = ...@@ -887,7 +892,8 @@ static const format_char_info scan_char_table[] =
static const format_char_info time_char_table[] = static const format_char_info time_char_table[] =
{ {
/* C89 conversion specifiers. */ /* C89 conversion specifiers. */
{ "ABZab", 0, STD_C89, NOLENGTHS, "^#", "", NULL }, { "AZa", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
{ "Bb", 0, STD_C89, NOLENGTHS, "O^#", "p", NULL },
{ "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL }, { "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL },
{ "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL }, { "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL },
{ "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL }, { "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL },
......
...@@ -48,6 +48,7 @@ enum format_std_version ...@@ -48,6 +48,7 @@ enum format_std_version
STD_C94, STD_C94,
STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */ STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */
STD_C99, STD_C99,
STD_C2X,
STD_EXT STD_EXT
}; };
...@@ -149,6 +150,7 @@ struct format_char_info ...@@ -149,6 +150,7 @@ struct format_char_info
two digit year formats, "3" for strftime formats giving two digit two digit year formats, "3" for strftime formats giving two digit
years in some locales, "4" for "2" which becomes "3" with an "E" modifier, years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
"o" if use of strftime "O" is a GNU extension beyond C99, "o" if use of strftime "O" is a GNU extension beyond C99,
"p" if use of strftime "O" is a C2x feature,
"W" if the argument is a pointer which is dereferenced and written into, "W" if the argument is a pointer which is dereferenced and written into,
"R" if the argument is a pointer which is dereferenced and read from, "R" if the argument is a pointer which is dereferenced and read from,
"i" for printf integer formats where the '0' flag is ignored with "i" for printf integer formats where the '0' flag is ignored with
......
2019-10-04 Joseph Myers <joseph@codesourcery.com>
PR c/82752
* gcc.dg/format/c2x-strftime-1.c: New test.
2019-10-04 Martin Sebor <msebor@redhat.com> 2019-10-04 Martin Sebor <msebor@redhat.com>
PR middle-end/91977 PR middle-end/91977
......
/* Test for strftime formats. Formats using C2x features. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic -Wformat" } */
#include "format.h"
void
foo (char *s, size_t m, const struct tm *tp)
{
strftime (s, m, "%Ob", tp);
strftime (s, m, "%OB", tp);
/* It's not clear that %h equivalence to %b means %Oh is equivalent
to %Ob; here we expect %Oh to be diagnosed. */
strftime (s, m, "%Oh", tp); /* { dg-warning "flag|modifier" "bad %Oh" } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment