From d62a07831c1fc047b3eebd508cfa47212e2cbe80 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Wed, 31 Oct 2018 11:50:07 +0100 Subject: [PATCH 1/2] gmacros: Add G_GNUC_STRFTIME macro Analogous to G_GNUC_PRINTF and G_GNUC_SCANF, to annotate functions similar to strftime. https://gitlab.gnome.org/GNOME/glib/issues/1575 --- docs/reference/glib/glib-sections.txt | 1 + glib/docs.c | 17 +++++++++++++++++ glib/gmacros.h | 5 +++++ 3 files changed, 23 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index d875f9a3a..e59a1c1e4 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -442,6 +442,7 @@ G_GNUC_FALLTHROUGH G_GNUC_UNUSED G_GNUC_PRINTF G_GNUC_SCANF +G_GNUC_STRFTIME G_GNUC_FORMAT G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT diff --git a/glib/docs.c b/glib/docs.c index 5212bb582..562fef0aa 100644 --- a/glib/docs.c +++ b/glib/docs.c @@ -2359,6 +2359,23 @@ * for details. */ +/** + * G_GNUC_STRFTIME: + * @format_idx: the index of the argument corresponding to + * the format string (the arguments are numbered from 1) + * + * Expands to the GNU C strftime format function attribute if the compiler + * is gcc. This is used for declaring functions which take a format argument + * which is passed to strftime() or an API implementing its formats. It allows + * the compiler check the format passed to the function. + * + * See the + * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-Wformat-3288) + * for details. + * + * Since: 2.60 + */ + /** * G_GNUC_FORMAT: * @arg_idx: the index of the argument diff --git a/glib/gmacros.h b/glib/gmacros.h index 0432d9cad..5212d2fe8 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -165,11 +165,15 @@ __attribute__((__format__ (gnu_printf, format_idx, arg_idx))) #define G_GNUC_SCANF( format_idx, arg_idx ) \ __attribute__((__format__ (gnu_scanf, format_idx, arg_idx))) +#define G_GNUC_STRFTIME( format_idx ) \ + __attribute__((__format__ (gnu_strftime, format_idx, 0))) #else #define G_GNUC_PRINTF( format_idx, arg_idx ) \ __attribute__((__format__ (__printf__, format_idx, arg_idx))) #define G_GNUC_SCANF( format_idx, arg_idx ) \ __attribute__((__format__ (__scanf__, format_idx, arg_idx))) +#define G_GNUC_STRFTIME( format_idx ) \ + __attribute__((__format__ (__strftime__, format_idx, 0))) #endif #define G_GNUC_FORMAT( arg_idx ) \ __attribute__((__format_arg__ (arg_idx))) @@ -184,6 +188,7 @@ #else /* !__GNUC__ */ #define G_GNUC_PRINTF( format_idx, arg_idx ) #define G_GNUC_SCANF( format_idx, arg_idx ) +#define G_GNUC_STRFTIME( format_idx ) #define G_GNUC_FORMAT( arg_idx ) #define G_GNUC_NORETURN #define G_GNUC_CONST From ae02adc3c3795bb32348c07d8f48504b41e9e2c7 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Wed, 31 Oct 2018 11:50:07 +0100 Subject: [PATCH 2/2] gdatetime: Enable compile time check of g_date_time_format() format By annotating it with G_GNUC_STRFTIME. https://gitlab.gnome.org/GNOME/glib/issues/1575 --- glib/gdatetime.h | 2 +- glib/tests/gdatetime.c | 8 ++++++++ tests/datetime.c | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/glib/gdatetime.h b/glib/gdatetime.h index 65f9965ac..20167a60d 100644 --- a/glib/gdatetime.h +++ b/glib/gdatetime.h @@ -261,7 +261,7 @@ GDateTime * g_date_time_to_utc (GDateTi GLIB_AVAILABLE_IN_ALL gchar * g_date_time_format (GDateTime *datetime, - const gchar *format) G_GNUC_MALLOC; + const gchar *format) G_GNUC_MALLOC G_GNUC_STRFTIME (2); G_END_DECLS diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c index a028f6d20..a434163c2 100644 --- a/glib/tests/gdatetime.c +++ b/glib/tests/gdatetime.c @@ -25,6 +25,14 @@ #include #include +/* The tests below exercise invalid formats and y2k-unsafe formats, + * so we need to silence the warnings here to pass. + */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-y2k" +#endif + #define ASSERT_DATE(dt,y,m,d) G_STMT_START { \ g_assert_nonnull ((dt)); \ g_assert_cmpint ((y), ==, g_date_time_get_year ((dt))); \ diff --git a/tests/datetime.c b/tests/datetime.c index ae46bbaea..16f4a95e2 100644 --- a/tests/datetime.c +++ b/tests/datetime.c @@ -18,6 +18,14 @@ #include #include +/* The whole purpose of this test is to pass the command line argument + * to g_date_time_format(), so the format argument cannot be compile- + * time checked. Disable the inevitable compiler warning. + */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + int main (int argc, char *argv[]) {