Commit 280c1e0d by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtin-attrs.def (gcc_diag, [...]): New format attributes.

gcc:
	* builtin-attrs.def (gcc_diag, gcc_cdiag, gcc_cxxdiag): New
	format attributes.
	* c-format.c (enum format_type): Add gcc_diag_format_type,
	gcc_cdiag_format_type, and gcc_cxxdiag_format_type.
	(gcc_diag_length_specs, gcc_cdiag_length_specs,
	gcc_cxxdiag_length_specs, gcc_diag_flag_pairs,
	gcc_cdiag_flag_pairs, gcc_cxxdiag_flag_pairs, gcc_diag_flag_specs,
	gcc_cdiag_flag_specs, gcc_cxxdiag_flag_specs, gcc_diag_char_table,
	gcc_cdiag_char_table, gcc_cxxdiag_char_table): New.
	(format_types_orig): Add new data.
	(find_char_info_specifier_index, init_dynamic_diag_info): New
	functions.
	(handle_format_attribute): Update to handle new format attributes.

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

From-SVN: r68689
parent 54bbcbd9
2003-06-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtin-attrs.def (gcc_diag, gcc_cdiag, gcc_cxxdiag): New
format attributes.
* c-format.c (enum format_type): Add gcc_diag_format_type,
gcc_cdiag_format_type, and gcc_cxxdiag_format_type.
(gcc_diag_length_specs, gcc_cdiag_length_specs,
gcc_cxxdiag_length_specs, gcc_diag_flag_pairs,
gcc_cdiag_flag_pairs, gcc_cxxdiag_flag_pairs, gcc_diag_flag_specs,
gcc_cdiag_flag_specs, gcc_cxxdiag_flag_specs, gcc_diag_char_table,
gcc_cdiag_char_table, gcc_cxxdiag_char_table): New.
(format_types_orig): Add new data.
(find_char_info_specifier_index, init_dynamic_diag_info): New
functions.
(handle_format_attribute): Update to handle new format attributes.
2003-06-29 Aaron W. LaFramboise <awlaframboise@aol.com> 2003-06-29 Aaron W. LaFramboise <awlaframboise@aol.com>
* config/i386/mingw32.h (__GTHREAD_HIDE_WIN32API): Define to 1. * config/i386/mingw32.h (__GTHREAD_HIDE_WIN32API): Define to 1.
......
...@@ -85,6 +85,9 @@ DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn") ...@@ -85,6 +85,9 @@ DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn")
DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow") DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow")
DEF_ATTR_IDENT (ATTR_PRINTF, "printf") DEF_ATTR_IDENT (ATTR_PRINTF, "printf")
DEF_ATTR_IDENT (ATTR_ASM_FPRINTF, "asm_fprintf") DEF_ATTR_IDENT (ATTR_ASM_FPRINTF, "asm_fprintf")
DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag")
DEF_ATTR_IDENT (ATTR_GCC_CDIAG, "gcc_cdiag")
DEF_ATTR_IDENT (ATTR_GCC_CXXDIAG, "gcc_cxxdiag")
DEF_ATTR_IDENT (ATTR_PURE, "pure") DEF_ATTR_IDENT (ATTR_PURE, "pure")
DEF_ATTR_IDENT (ATTR_SCANF, "scanf") DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon") DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
......
...@@ -56,6 +56,8 @@ set_Wformat (int setting) ...@@ -56,6 +56,8 @@ set_Wformat (int setting)
/* This must be in the same order as format_types, with format_type_error /* This must be in the same order as format_types, with format_type_error
last. */ last. */
enum format_type { printf_format_type, asm_fprintf_format_type, enum format_type { printf_format_type, asm_fprintf_format_type,
gcc_diag_format_type, gcc_cdiag_format_type,
gcc_cxxdiag_format_type,
scanf_format_type, strftime_format_type, scanf_format_type, strftime_format_type,
strfmon_format_type, format_type_error }; strfmon_format_type, format_type_error };
...@@ -523,6 +525,18 @@ static const format_length_info asm_fprintf_length_specs[] = ...@@ -523,6 +525,18 @@ static const format_length_info asm_fprintf_length_specs[] =
{ NULL, 0, 0, NULL, 0, 0 } { NULL, 0, 0, NULL, 0, 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, NULL, 0, 0 },
{ NULL, 0, 0, NULL, 0, 0 }
};
/* The custom diagnostics all accept the same length specifiers. */
#define gcc_cdiag_length_specs gcc_diag_length_specs
#define gcc_cxxdiag_length_specs gcc_diag_length_specs
/* This differs from printf_length_specs only in that "Z" is not accepted. */ /* This differs from printf_length_specs only in that "Z" is not accepted. */
static const format_length_info scanf_length_specs[] = static const format_length_info scanf_length_specs[] =
{ {
...@@ -591,6 +605,32 @@ static const format_flag_pair asm_fprintf_flag_pairs[] = ...@@ -591,6 +605,32 @@ static const format_flag_pair asm_fprintf_flag_pairs[] =
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static const format_flag_pair gcc_diag_flag_pairs[] =
{
{ 0, 0, 0, 0 }
};
#define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
#define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
static const format_flag_spec gcc_diag_flag_specs[] =
{
{ 'p', 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 }
};
#define gcc_cdiag_flag_specs gcc_diag_flag_specs
static const format_flag_spec gcc_cxxdiag_flag_specs[] =
{
{ '+', 0, 0, N_("`+' flag"), N_("the `+' printf flag"), STD_C89 },
{ '#', 0, 0, N_("`#' flag"), N_("the `#' printf flag"), STD_C89 },
{ 'p', 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_spec scanf_flag_specs[] = static const format_flag_spec scanf_flag_specs[] =
{ {
{ '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, { '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
...@@ -755,6 +795,72 @@ static const format_char_info asm_fprintf_char_table[] = ...@@ -755,6 +795,72 @@ static const format_char_info asm_fprintf_char_table[] =
{ NULL, 0, 0, NOLENGTHS, NULL, NULL } { NULL, 0, 0, NOLENGTHS, NULL, NULL }
}; };
static const format_char_info gcc_diag_char_table[] =
{
/* C89 conversion specifiers. */
{ "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" },
{ "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" },
/* Custom conversion specifiers. */
/* %H will require "location_t" at runtime. */
{ "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "m", 0, STD_C89, NOARGUMENTS, "", "" },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL }
};
static const format_char_info gcc_cdiag_char_table[] =
{
/* C89 conversion specifiers. */
{ "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" },
{ "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" },
/* Custom conversion specifiers. */
/* %H will require "location_t" at runtime. */
{ "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
/* These will require a "tree" at runtime. */
{ "DFT", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "m", 0, STD_C89, NOARGUMENTS, "", "" },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL }
};
static const format_char_info gcc_cxxdiag_char_table[] =
{
/* C89 conversion specifiers. */
{ "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" },
{ "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" },
/* Custom conversion specifiers. */
/* %H will require "location_t" at runtime. */
{ "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
/* These will require a "tree" at runtime. */
{ "ADEFTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "+#", "" },
/* These accept either an `int' or an `enum tree_code' (which is handled as an `int'.) */
{ "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
{ "m", 0, STD_C89, NOARGUMENTS, "", "" },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL }
};
static const format_char_info scan_char_table[] = static const format_char_info scan_char_table[] =
{ {
/* C89 conversion specifiers. */ /* C89 conversion specifiers. */
...@@ -824,6 +930,24 @@ static const format_kind_info format_types_orig[] = ...@@ -824,6 +930,24 @@ static const format_kind_info format_types_orig[] =
'w', 0, 'p', 0, 'L', 'w', 0, 'p', 0, 'L',
NULL, NULL NULL, NULL
}, },
{ "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "", NULL,
gcc_diag_flag_specs, gcc_diag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
NULL, &integer_type_node
},
{ "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "", NULL,
gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
NULL, &integer_type_node
},
{ "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "+#", NULL,
gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 'p', 0, 'L',
NULL, &integer_type_node
},
{ "scanf", scanf_length_specs, scan_char_table, "*'I", NULL, { "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
scanf_flag_specs, scanf_flag_pairs, 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, FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
...@@ -2330,6 +2454,26 @@ check_format_types (int *status, format_wanted_type *types) ...@@ -2330,6 +2454,26 @@ check_format_types (int *status, format_wanted_type *types)
} }
} }
/* Given a format_char_info array FCI, and a character C, this function
returns the index into the conversion_specs where that specifier's
data is located. If the character isn't found it aborts. */
static unsigned int
find_char_info_specifier_index (const format_char_info *fci, int c)
{
unsigned int i = 0;
while (fci->format_chars)
{
if (strchr (fci->format_chars, c))
return i;
i++; fci++;
}
/* We shouldn't be looking for a non-existent specifier. */
abort ();
}
/* Given a format_length_info array FLI, and a character C, this /* Given a format_length_info array FLI, and a character C, this
function returns the index into the conversion_specs where that function returns the index into the conversion_specs where that
modifier's data is located. If the character isn't found it modifier's data is located. If the character isn't found it
...@@ -2391,6 +2535,118 @@ init_dynamic_asm_fprintf_info (void) ...@@ -2391,6 +2535,118 @@ init_dynamic_asm_fprintf_info (void)
} }
} }
/* Determine the types of "tree" and "location_t" in the code being
compiled for use in GCC's diagnostic custom format attributes. You
must have set dynamic_format_types before calling this function. */
static void
init_dynamic_diag_info (void)
{
static tree t, loc, hwi;
if (!loc || !t || !hwi)
{
static format_char_info *diag_fci, *cdiag_fci, *cxxdiag_fci;
static format_length_info *diag_ls;
unsigned int i;
/* For the GCC-diagnostics custom format specifiers to work, one
must have declared `tree' and/or `location_t' prior to using
those attributes. If we haven't seen these declarations then
you shouldn't use the specifiers requiring these types.
However we don't force a hard ICE because we may see only one
or the other type. */
if ((loc = maybe_get_identifier ("location_t")))
loc = TREE_TYPE (identifier_global_value (loc));
/* We need to grab the underlying `union tree_node' so peek into
an extra type level. */
if ((t = maybe_get_identifier ("tree")))
t = TREE_TYPE (TREE_TYPE (identifier_global_value (t)));
/* Find the underlying type for HOST_WIDE_INT. For the %w
length modifier to work, one must have issued: "typedef
HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
prior to using that modifier. */
if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
hwi = DECL_ORIGINAL_TYPE (identifier_global_value (hwi));
/* Assign the new data for use. */
/* All the GCC diag formats use the same length specs. */
if (! diag_ls)
dynamic_format_types[gcc_diag_format_type].length_char_specs =
dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
diag_ls = xmemdup (gcc_diag_length_specs,
sizeof (gcc_diag_length_specs),
sizeof (gcc_diag_length_specs));
if (hwi)
{
/* HOST_WIDE_INT must be one of 'long' or 'long long'. */
i = find_length_info_modifier_index (diag_ls, 'w');
if (hwi == long_integer_type_node)
diag_ls[i].index = FMT_LEN_l;
else if (hwi == long_long_integer_type_node)
diag_ls[i].index = FMT_LEN_ll;
else
abort ();
}
/* Handle the __gcc_diag__ format specifics. */
if (! diag_fci)
dynamic_format_types[gcc_diag_format_type].conversion_specs =
diag_fci = xmemdup (gcc_diag_char_table,
sizeof(gcc_diag_char_table),
sizeof(gcc_diag_char_table));
if (loc)
{
i = find_char_info_specifier_index (diag_fci, 'H');
diag_fci[i].types[0].type = &loc;
diag_fci[i].pointer_count = 1;
}
/* Handle the __gcc_cdiag__ format specifics. */
if (! cdiag_fci)
dynamic_format_types[gcc_cdiag_format_type].conversion_specs =
cdiag_fci = xmemdup (gcc_cdiag_char_table,
sizeof(gcc_cdiag_char_table),
sizeof(gcc_cdiag_char_table));
if (loc)
{
i = find_char_info_specifier_index (cdiag_fci, 'H');
cdiag_fci[i].types[0].type = &loc;
cdiag_fci[i].pointer_count = 1;
}
if (t)
{
/* All specifiers taking a tree share the same struct. */
i = find_char_info_specifier_index (cdiag_fci, 'D');
cdiag_fci[i].types[0].type = &t;
cdiag_fci[i].pointer_count = 1;
}
/* Handle the __gcc_cxxdiag__ format specifics. */
if (! cxxdiag_fci)
dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
cxxdiag_fci = xmemdup (gcc_cxxdiag_char_table,
sizeof(gcc_cxxdiag_char_table),
sizeof(gcc_cxxdiag_char_table));
if (loc)
{
i = find_char_info_specifier_index (cxxdiag_fci, 'H');
cxxdiag_fci[i].types[0].type = &loc;
cxxdiag_fci[i].pointer_count = 1;
}
if (t)
{
/* All specifiers taking a tree share the same struct. */
i = find_char_info_specifier_index (cxxdiag_fci, 'D');
cxxdiag_fci[i].types[0].type = &t;
cxxdiag_fci[i].pointer_count = 1;
}
}
}
/* Handle a "format" attribute; arguments as in /* Handle a "format" attribute; arguments as in
struct attribute_spec.handler. */ struct attribute_spec.handler. */
tree tree
...@@ -2440,9 +2696,12 @@ handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, ...@@ -2440,9 +2696,12 @@ handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
return NULL_TREE; return NULL_TREE;
} }
/* If this is format type __asm_fprintf__, we have to initialize /* If this is a custom GCC-internal format type, we have to
GCC's notion of HOST_WIDE_INT for checking %wd. */ initialize certain bits a runtime. */
if (info.format_type == asm_fprintf_format_type) if (info.format_type == asm_fprintf_format_type
|| info.format_type == gcc_diag_format_type
|| info.format_type == gcc_cdiag_format_type
|| info.format_type == gcc_cxxdiag_format_type)
{ {
/* Our first time through, we have to make sure that our /* Our first time through, we have to make sure that our
format_type data is allocated dynamically and is modifiable. */ format_type data is allocated dynamically and is modifiable. */
...@@ -2451,7 +2710,18 @@ handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, ...@@ -2451,7 +2710,18 @@ handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
xmemdup (format_types_orig, sizeof (format_types_orig), xmemdup (format_types_orig, sizeof (format_types_orig),
sizeof (format_types_orig)); sizeof (format_types_orig));
init_dynamic_asm_fprintf_info(); /* If this is format __asm_fprintf__, we have to initialize
GCC's notion of HOST_WIDE_INT for checking %wd. */
if (info.format_type == asm_fprintf_format_type)
init_dynamic_asm_fprintf_info();
/* If this is one of the diagnostic attributes, then we have to
intialize `location_t' and `tree' at runtime. */
else if (info.format_type == gcc_diag_format_type
|| info.format_type == gcc_cdiag_format_type
|| info.format_type == gcc_cxxdiag_format_type)
init_dynamic_diag_info();
else
abort();
} }
return NULL_TREE; return NULL_TREE;
......
2003-06-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/format/gcc_diag-1.c: New test.
2003-06-28 Ulrich Weigand <uweigand@de.ibm.com> 2003-06-28 Ulrich Weigand <uweigand@de.ibm.com>
* gcc.c-torture/execute/multi-ix.c: Fix off-by-one bugs. * gcc.c-torture/execute/multi-ix.c: Fix off-by-one bugs.
......
/* Test for GCC diagnositc formats. */
/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
/* { dg-do compile } */
/* { dg-options "-Wformat" } */
#include "format.h"
#define ATTRIBUTE_DIAG(F) __attribute__ ((__format__ (F, 1, 2))) __attribute__ ((__nonnull__));
/* Magic identifiers must be set before the attribute is used. */
typedef long long __gcc_host_wide_int__;
typedef struct location_s
{
const char *file;
int line;
} location_t;
union tree_node;
typedef union tree_node *tree;
extern int diag (const char *, ...) ATTRIBUTE_DIAG(__gcc_diag__);
extern int cdiag (const char *, ...) ATTRIBUTE_DIAG(__gcc_cdiag__);
extern int cxxdiag (const char *, ...) ATTRIBUTE_DIAG(__gcc_cxxdiag__);
void
foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
int *n, short int *hn, long int l, unsigned long int ul,
long int *ln, long double ld, wint_t lc, wchar_t *ls, llong ll,
ullong ull, unsigned int *un, const int *cn, signed char *ss,
unsigned char *us, const signed char *css, unsigned int u1,
unsigned int u2, location_t *loc, tree t1, union tree_node *t2,
tree *t3, tree t4[])
{
/* Acceptable C90 specifiers, flags and modifiers. */
diag ("%%");
cdiag ("%%");
cxxdiag ("%%");
diag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
cdiag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
cxxdiag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
diag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
cdiag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
cxxdiag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
diag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
cdiag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
cxxdiag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
diag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
cdiag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
cxxdiag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
diag ("%.*s", i, s);
cdiag ("%.*s", i, s);
cxxdiag ("%.*s", i, s);
/* Extensions provided in the diagnostic framework. */
diag ("%m");
cdiag ("%m");
cxxdiag ("%m");
diag ("%H", loc);
cdiag ("%H", loc);
cxxdiag ("%H", loc);
cdiag ("%D%F%T", t1, t1, t1);
cdiag ("%D%D%D%D", t1, t2, *t3, t4[5]);
cxxdiag ("%A%D%E%F%T%V", t1, t1, t1, t1, t1, t1);
cxxdiag ("%D%D%D%D", t1, t2, *t3, t4[5]);
cxxdiag ("%#A%#D%#E%#F%#T%#V", t1, t1, t1, t1, t1, t1);
cxxdiag ("%+A%+D%+E%+F%+T%+V", t1, t1, t1, t1, t1, t1);
cxxdiag ("%+#A%+#D%+#E%+#F%+#T%+#V", t1, t1, t1, t1, t1, t1);
cxxdiag ("%C%L%O%P%Q", i, i, i, i, i);
/* Bad stuff with extensions. */
diag ("%m", i); /* { dg-warning "format" "extra arg" } */
cdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
cxxdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
diag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
diag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
diag ("%H"); /* { dg-warning "format" "missing arg" } */
cdiag ("%H"); /* { dg-warning "format" "missing arg" } */
cxxdiag ("%H"); /* { dg-warning "format" "missing arg" } */
diag ("%H", i); /* { dg-warning "format" "wrong arg" } */
cdiag ("%H", i); /* { dg-warning "format" "wrong arg" } */
cxxdiag ("%H", i); /* { dg-warning "format" "wrong arg" } */
diag ("%H", p); /* { dg-warning "format" "wrong arg" } */
cdiag ("%H", p); /* { dg-warning "format" "wrong arg" } */
cxxdiag ("%H", p); /* { dg-warning "format" "wrong arg" } */
diag ("%#H", loc); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%#H", loc); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%#H", loc); /* { dg-warning "format" "bogus modifier" } */
diag ("%+H", loc); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%+H", loc); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%+H", loc); /* { dg-warning "format" "bogus modifier" } */
diag ("%D", t1); /* { dg-warning "format" "bogus tree" } */
cdiag ("%A", t1); /* { dg-warning "format" "bogus tree" } */
cdiag ("%#D", t1); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%+D", t1); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%C"); /* { dg-warning "format" "missing arg" } */
cxxdiag ("%C", l); /* { dg-warning "format" "wrong arg" } */
cxxdiag ("%C", i, i); /* { dg-warning "format" "extra arg" } */
cxxdiag ("%#C", i); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%+C", i); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%D"); /* { dg-warning "format" "missing arg" } */
cxxdiag ("%D"); /* { dg-warning "format" "missing arg" } */
cdiag ("%D", i); /* { dg-warning "format" "wrong arg" } */
cxxdiag ("%D", i); /* { dg-warning "format" "wrong arg" } */
cdiag ("%D", t1, t1); /* { dg-warning "format" "extra arg" } */
cxxdiag ("%D", t1, t1); /* { dg-warning "format" "extra arg" } */
/* Standard specifiers not accepted in the diagnostic framework. */
diag ("%X\n", u); /* { dg-warning "format" "HEX" } */
diag ("%f\n", d); /* { dg-warning "format" "float" } */
diag ("%e\n", d); /* { dg-warning "format" "float" } */
diag ("%E\n", d); /* { dg-warning "format" "float" } */
diag ("%g\n", d); /* { dg-warning "format" "float" } */
diag ("%G\n", d); /* { dg-warning "format" "float" } */
diag ("%n\n", n); /* { dg-warning "format" "counter" } */
diag ("%hd\n", i); /* { dg-warning "format" "conversion" } */
/* Various tests of bad argument types. */
diag ("%-d", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%-d", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%-d", i); /* { dg-warning "format" "bad flag" } */
diag ("% d", i); /* { dg-warning "format" "bad flag" } */
cdiag ("% d", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("% d", i); /* { dg-warning "format" "bad flag" } */
diag ("%#o", u); /* { dg-warning "format" "bad flag" } */
cdiag ("%#o", u); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%#o", u); /* { dg-warning "format" "bad flag" } */
diag ("%0d", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%0d", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%0d", i); /* { dg-warning "format" "bad flag" } */
diag ("%08d", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%08d", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%08d", i); /* { dg-warning "format" "bad flag" } */
diag ("%+d\n", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%+d\n", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%+d\n", i); /* { dg-warning "format" "bad flag" } */
diag ("%3d\n", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%3d\n", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%3d\n", i); /* { dg-warning "format" "bad flag" } */
diag ("%-3d\n", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%-3d\n", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%-3d\n", i); /* { dg-warning "format" "bad flag" } */
diag ("%.7d\n", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%.7d\n", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%.7d\n", i); /* { dg-warning "format" "bad flag" } */
diag ("%+9.4d\n", i); /* { dg-warning "format" "bad flag" } */
cdiag ("%+9.4d\n", i); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%+9.4d\n", i); /* { dg-warning "format" "bad flag" } */
diag ("%.3ld\n", l); /* { dg-warning "format" "bad flag" } */
cdiag ("%.3ld\n", l); /* { dg-warning "format" "bad flag" } */
cxxdiag ("%.3ld\n", l); /* { dg-warning "format" "bad flag" } */
diag ("%d %lu\n", i, ul);
diag ("%d", l); /* { dg-warning "format" "bad argument types" } */
diag ("%wd", l); /* { dg-warning "format" "bad argument types" } */
diag ("%d", ll); /* { dg-warning "format" "bad argument types" } */
diag ("%*s", i, s); /* { dg-warning "format" "bad * argument types" } */
diag ("%*.*s", i, i, s); /* { dg-warning "format" "bad * argument types" } */
diag ("%*d\n", i1, i); /* { dg-warning "format" "bad * argument types" } */
diag ("%.*d\n", i2, i); /* { dg-warning "format" "bad * argument types" } */
diag ("%*.*ld\n", i1, i2, l); /* { dg-warning "format" "bad * argument types" } */
diag ("%ld", i); /* { dg-warning "format" "bad argument types" } */
diag ("%s", n); /* { dg-warning "format" "bad argument types" } */
/* Wrong number of arguments. */
diag ("%d%d", i); /* { dg-warning "arguments" "wrong number of args" } */
diag ("%d", i, i); /* { dg-warning "arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
diag (""); /* { dg-warning "zero-length" "warning for empty format" } */
diag ("\0"); /* { dg-warning "embedded" "warning for embedded NUL" } */
diag ("%d\0", i); /* { dg-warning "embedded" "warning for embedded NUL" } */
diag ("%d\0%d", i, i); /* { dg-warning "embedded|too many" "warning for embedded NUL" } */
diag (NULL); /* { dg-warning "null" "null format string warning" } */
diag ("%"); /* { dg-warning "trailing" "trailing % warning" } */
diag ((const char *)L"foo"); /* { dg-warning "wide" "wide string" } */
diag ("%s", (char *)0); /* { dg-warning "null" "%s with NULL" } */
/* Make sure we still get warnings for regular printf. */
printf ("%d\n", ll); /* { dg-warning "format" "bad argument types" } */
}
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