re PR c/1027 (slightly misleading printf format warning)

PR c/1027
	* c-lang.c (c_initialize_diagnostics): Move from here ...
	* c-objc-common.c: ... to here.  Include "c-pretty-print.h".
	(c_tree_printer): Use pretty-printer to format %T.
	* c-pretty-print.c (pp_c_specifier_qualifier_list): Include space
	before '*' if not C++.
	(pp_c_direct_abstract_declarator): Don't try to print array upper
	bound for flexible array members.
	* c-tree.h: Include "diagnostic.h".
	(c_initialize_diagnostics): Declare.
	* objc/objc-lang.c (LANG_HOOKS_INITIALIZE_DIAGNOSTICS): Define.
	* c-format.c (format_type_warning): New function.  Improve
	diagnostics for incorrect format argument types.
	(check_format_types): Use it.  Add two parameters.  Use the
	TYPE_MAIN_VARIANT of wanted_type.
	(check_format_info_main): Pass new parameters to
	check_format_types.
	(struct format_wanted_type): Update comment.

testsuite:
	* gcc.dg/Wswitch-enum.c, gcc.dg/Wswitch.c,
	gcc.dg/format/branch-1.c, gcc.dg/format/diag-1.c,
	gcc.dg/format/multattr-3.c, gcc.dg/format/xopen-1.c: Update
	expected warning text.
	* gcc.dg/format/diag-2.c: New test.

From-SVN: r83965
This commit is contained in:
Joseph Myers 2004-07-01 09:52:33 +01:00 committed by Joseph Myers
parent d59c7b4bdc
commit ede1a38729
15 changed files with 192 additions and 114 deletions

View File

@ -1,3 +1,24 @@
2004-07-01 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/1027
* c-lang.c (c_initialize_diagnostics): Move from here ...
* c-objc-common.c: ... to here. Include "c-pretty-print.h".
(c_tree_printer): Use pretty-printer to format %T.
* c-pretty-print.c (pp_c_specifier_qualifier_list): Include space
before '*' if not C++.
(pp_c_direct_abstract_declarator): Don't try to print array upper
bound for flexible array members.
* c-tree.h: Include "diagnostic.h".
(c_initialize_diagnostics): Declare.
* objc/objc-lang.c (LANG_HOOKS_INITIALIZE_DIAGNOSTICS): Define.
* c-format.c (format_type_warning): New function. Improve
diagnostics for incorrect format argument types.
(check_format_types): Use it. Add two parameters. Use the
TYPE_MAIN_VARIANT of wanted_type.
(check_format_info_main): Pass new parameters to
check_format_types.
(struct format_wanted_type): Update comment.
2004-07-01 Nick Clifton <nickc@redhat.com>
* target.h (struct gcc_target): Add new field to struct cxx:

View File

@ -488,12 +488,10 @@ typedef struct format_wanted_type
/* Whether the argument, dereferenced once, is read from and so
must not be a NULL pointer. */
int reading_from_flag;
/* If warnings should be of the form "field precision is not type int",
the name to use (in this case "field precision"), otherwise NULL,
for "%s format, %s arg" type messages. If (in an extension), this
is a pointer type, wanted_type_name should be set to include the
terminating '*' characters of the type name to give a correct
message. */
/* If warnings should be of the form "field precision should have
type 'int'", the name to use (in this case "field precision"),
otherwise NULL, for "format expects type 'long'" type
messages. */
const char *name;
/* The actual parameter to check against the wanted type. */
tree param;
@ -1031,7 +1029,9 @@ static void finish_dollar_format_checking (format_check_results *, int);
static const format_flag_spec *get_flag_spec (const format_flag_spec *,
int, const char *);
static void check_format_types (format_wanted_type *);
static void check_format_types (format_wanted_type *, const char *, int);
static void format_type_warning (const char *, const char *, int, tree,
int, const char *, tree, int);
/* Decode a format type from a string, returning the type, or
format_type_error if not valid, in which case the caller should print an
@ -1667,6 +1667,7 @@ check_format_info_main (format_check_results *res,
const format_char_info *fci = NULL;
char flag_chars[256];
int aflag = 0;
const char *format_start = format_chars;
if (*format_chars == 0)
{
if (format_chars - orig_format_chars != format_length)
@ -2255,7 +2256,8 @@ check_format_info_main (format_check_results *res,
}
if (first_wanted_type != 0)
check_format_types (first_wanted_type);
check_format_types (first_wanted_type, format_start,
format_chars - format_start);
}
}
@ -2264,7 +2266,8 @@ check_format_info_main (format_check_results *res,
/* Check the argument types from a single format conversion (possibly
including width and precision arguments). */
static void
check_format_types (format_wanted_type *types)
check_format_types (format_wanted_type *types, const char *format_start,
int format_length)
{
for (; types != 0; types = types->next)
{
@ -2279,6 +2282,7 @@ check_format_types (format_wanted_type *types)
cur_type = TREE_TYPE (cur_param);
if (cur_type == error_mark_node)
continue;
orig_cur_type = cur_type;
char_type_flag = 0;
wanted_type = types->wanted_type;
arg_num = types->arg_num;
@ -2292,6 +2296,8 @@ check_format_types (format_wanted_type *types)
if (types->pointer_count == 0)
wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
wanted_type = TYPE_MAIN_VARIANT (wanted_type);
STRIP_NOPS (cur_param);
/* Check the types of any additional pointer arguments
@ -2353,10 +2359,10 @@ check_format_types (format_wanted_type *types)
}
else
{
if (types->pointer_count == 1)
warning ("format argument is not a pointer (arg %d)", arg_num);
else
warning ("format argument is not a pointer to a pointer (arg %d)", arg_num);
format_type_warning (types->name, format_start, format_length,
wanted_type, types->pointer_count,
types->wanted_type_name, orig_cur_type,
arg_num);
break;
}
}
@ -2364,7 +2370,6 @@ check_format_types (format_wanted_type *types)
if (i < types->pointer_count)
continue;
orig_cur_type = cur_type;
cur_type = TYPE_MAIN_VARIANT (cur_type);
/* Check whether the argument type is a character type. This leniency
@ -2403,67 +2408,80 @@ check_format_types (format_wanted_type *types)
&& char_type_flag)
continue;
/* Now we have a type mismatch. */
{
const char *this;
const char *that;
tree tmp;
tmp = TYPE_NAME (wanted_type);
if (TREE_CODE (tmp) == TYPE_DECL)
tmp = DECL_NAME (tmp);
this = IDENTIFIER_POINTER (tmp);
that = 0;
if (TYPE_NAME (orig_cur_type) != 0
&& TREE_CODE (orig_cur_type) != INTEGER_TYPE
&& !(TREE_CODE (orig_cur_type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (orig_cur_type)) == INTEGER_TYPE))
{
tmp = TYPE_NAME (orig_cur_type);
if (TREE_CODE (tmp) == TYPE_DECL)
tmp = DECL_NAME (tmp);
if (tmp)
that = IDENTIFIER_POINTER (tmp);
}
/* A nameless type can't possibly match what the format wants.
So there will be a warning for it.
Make up a string to describe vaguely what it is. */
if (that == 0)
{
if (TREE_CODE (orig_cur_type) == POINTER_TYPE)
that = _("pointer");
else
that = _("different type");
}
/* Make the warning better in case of mismatch of int vs long. */
if (TREE_CODE (orig_cur_type) == INTEGER_TYPE
&& TREE_CODE (wanted_type) == INTEGER_TYPE
&& TYPE_PRECISION (orig_cur_type) == TYPE_PRECISION (wanted_type)
&& TYPE_NAME (orig_cur_type) != 0
&& TREE_CODE (TYPE_NAME (orig_cur_type)) == TYPE_DECL)
that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (orig_cur_type)));
if (strcmp (this, that) != 0)
{
/* There may be a better name for the format, e.g. size_t,
but we should allow for programs with a perverse typedef
making size_t something other than what the compiler
thinks. */
if (types->wanted_type_name != 0
&& strcmp (types->wanted_type_name, that) != 0)
this = types->wanted_type_name;
if (types->name != 0)
warning ("%s is not type %s (arg %d)", types->name, this,
arg_num);
else
warning ("%s format, %s arg (arg %d)", this, that, arg_num);
}
}
format_type_warning (types->name, format_start, format_length,
wanted_type, types->pointer_count,
types->wanted_type_name, orig_cur_type, arg_num);
}
}
/* Give a warning about a format argument of different type from that
expected. DESCR is a description such as "field precision", or
NULL for an ordinary format. For an ordinary format, FORMAT_START
points to where the format starts in the format string and
FORMAT_LENGTH is its length. WANTED_TYPE is the type the argument
should have after POINTER_COUNT pointer dereferences.
WANTED_NAME_NAME is a possibly more friendly name of WANTED_TYPE,
or NULL if the ordinary name of the type should be used. ARG_TYPE
is the type of the actual argument. ARG_NUM is the number of that
argument. */
static void
format_type_warning (const char *descr, const char *format_start,
int format_length, tree wanted_type, int pointer_count,
const char *wanted_type_name, tree arg_type, int arg_num)
{
char *p;
/* If ARG_TYPE is a typedef with a misleading name (for example,
size_t but not the standard size_t expected by printf %zu), avoid
printing the typedef name. */
if (wanted_type_name
&& TYPE_NAME (arg_type)
&& TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (arg_type))
&& !strcmp (wanted_type_name,
lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
arg_type = TYPE_MAIN_VARIANT (arg_type);
/* The format type and name exclude any '*' for pointers, so those
must be formatted manually. For all the types we currently have,
this is adequate, but formats taking pointers to functions or
arrays would require the full type to be built up in order to
print it with %T. */
p = alloca (pointer_count + 2);
if (pointer_count == 0)
p[0] = 0;
else if (c_dialect_cxx ())
{
memset (p, '*', pointer_count);
p[pointer_count] = 0;
}
else
{
p[0] = ' ';
memset (p + 1, '*', pointer_count);
p[pointer_count + 1] = 0;
}
if (wanted_type_name)
{
if (descr)
warning ("%s should have type %<%s%s%>, but argument %d has type %qT",
descr, wanted_type_name, p, arg_num, arg_type);
else
warning ("format %q.*s expects type %<%s%s%>, but argument %d has type %qT",
format_length, format_start, wanted_type_name, p,
arg_num, arg_type);
}
else
{
if (descr)
warning ("%s should have type %<%T%s%>, but argument %d has type %qT",
descr, wanted_type, p, arg_num, arg_type);
else
warning ("format %q.*s expects type %<%T%s%>, but argument %d has type %qT",
format_length, format_start, wanted_type, p, arg_num, arg_type);
}
}
/* 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. */

View File

@ -34,8 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "diagnostic.h"
#include "c-pretty-print.h"
static void c_initialize_diagnostics (diagnostic_context *);
enum c_language_kind c_language = clk_c;
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
@ -210,17 +208,5 @@ c_types_compatible_p (tree x, tree y)
{
return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
}
static void
c_initialize_diagnostics (diagnostic_context *context)
{
pretty_printer *base = context->printer;
c_pretty_printer *pp = xmalloc (sizeof (c_pretty_printer));
memcpy (pp_base (pp), base, sizeof (pretty_printer));
pp_c_pretty_printer_init (pp);
context->printer = (pretty_printer *) pp;
/* It is safe to free this object because it was previously malloc()'d. */
free (base);
}
#include "gtype-c.h"

View File

@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h"
#include "integrate.h"
#include "c-tree.h"
#include "c-pretty-print.h"
#include "function.h"
#include "flags.h"
#include "toplev.h"
@ -242,7 +243,10 @@ static bool
c_tree_printer (pretty_printer *pp, text_info *text)
{
tree t = va_arg (*text->args_ptr, tree);
tree name;
const char *n = "({anonymous})";
c_pretty_printer *cpp = (c_pretty_printer *) pp;
pp->padding = pp_none;
switch (*text->format_spec)
{
@ -254,14 +258,22 @@ c_tree_printer (pretty_printer *pp, text_info *text)
case 'T':
if (TYPE_P (t))
t = TYPE_NAME (t);
if (t && TREE_CODE (t) == TYPE_DECL)
name = TYPE_NAME (t);
else
abort ();
if (name && TREE_CODE (name) == TYPE_DECL)
{
if (DECL_NAME (t))
n = lang_hooks.decl_printable_name (t, 2);
if (DECL_NAME (name))
pp_string (cpp, lang_hooks.decl_printable_name (name, 2));
else
pp_type_id (cpp, t);
return true;
}
else
{
pp_type_id (cpp, t);
return true;
}
else if (t)
n = IDENTIFIER_POINTER (t);
break;
case 'E':
@ -275,7 +287,7 @@ c_tree_printer (pretty_printer *pp, text_info *text)
return false;
}
pp_string (pp, n);
pp_string (cpp, n);
return true;
}
@ -313,3 +325,16 @@ has_c_linkage (tree decl ATTRIBUTE_UNUSED)
{
return true;
}
void
c_initialize_diagnostics (diagnostic_context *context)
{
pretty_printer *base = context->printer;
c_pretty_printer *pp = xmalloc (sizeof (c_pretty_printer));
memcpy (pp_base (pp), base, sizeof (pretty_printer));
pp_c_pretty_printer_init (pp);
context->printer = (pretty_printer *) pp;
/* It is safe to free this object because it was previously malloc()'d. */
free (base);
}

View File

@ -384,6 +384,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
pp_c_whitespace (pp);
pp_c_left_paren (pp);
}
else if (!c_dialect_cxx ())
pp_c_whitespace (pp);
pp_ptr_operator (pp, t);
}
break;
@ -487,7 +489,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t)
case ARRAY_TYPE:
pp_c_left_bracket (pp);
if (TYPE_DOMAIN (t))
if (TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t)))
pp_expression (pp, TYPE_MAX_VALUE (TYPE_DOMAIN (t)));
pp_c_right_bracket (pp);
pp_direct_abstract_declarator (pp, TREE_TYPE (t));

View File

@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define GCC_C_TREE_H
#include "c-common.h"
#include "diagnostic.h"
/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
know how big it is. This is sanity-checked in c-decl.c. */
@ -204,6 +205,7 @@ extern tree c_objc_common_truthvalue_conversion (tree expr);
extern void c_objc_common_finish_file (void);
extern int defer_fn (tree);
extern bool c_warn_unused_global_decl (tree);
extern void c_initialize_diagnostics (diagnostic_context *);
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type ((TYPE), \

View File

@ -1,5 +1,5 @@
/* Language-dependent hooks for Objective-C.
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Ziemowit Laski <zlaski@apple.com>
This file is part of GCC.
@ -43,6 +43,8 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_FINISH c_common_finish
#undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS c_common_init_options
#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
#undef LANG_HOOKS_HANDLE_OPTION
#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
#undef LANG_HOOKS_HANDLE_FILENAME

View File

@ -1,3 +1,12 @@
2004-07-01 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/1027
* gcc.dg/Wswitch-enum.c, gcc.dg/Wswitch.c,
gcc.dg/format/branch-1.c, gcc.dg/format/diag-1.c,
gcc.dg/format/multattr-3.c, gcc.dg/format/xopen-1.c: Update
expected warning text.
* gcc.dg/format/diag-2.c: New test.
2004-07-01 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.c-torture/compile/20040323-1.c: XFAIL on Solaris 2.

View File

@ -50,13 +50,13 @@ foo (int i, int j, enum e ei, enum e ej, enum e ek, enum e el,
{
case e1: return 1;
case e2: return 2;
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `enum e'" "excess 3" } */
}
switch (ep)
{
case e1: return 1;
case e2: return 2;
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `enum e'" "excess 3" } */
default: break;
}
return 0;

View File

@ -50,7 +50,7 @@ foo (int i, int j, enum e ei, enum e ej, enum e ek, enum e el,
{
case e1: return 1;
case e2: return 2;
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `enum e'" "excess 3" } */
}
switch (ep)
{

View File

@ -9,18 +9,18 @@ void
foo (long l, int nfoo)
{
printf ((nfoo > 1) ? "%d foos" : "%d foo", nfoo);
printf ((l > 1) ? "%d foos" : "%d foo", l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf ((l > 1) ? "%d foos" : "%d foo", l); /* { dg-warning "int" "wrong type in conditional expr" } */
printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "int" "wrong type in conditional expr" } */
printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "int" "wrong type in conditional expr" } */
/* Should allow one case to have extra arguments. */
printf ((nfoo > 1) ? "%d foos" : "1 foo", nfoo);
printf ((nfoo > 1) ? "many foos" : "1 foo", nfoo); /* { dg-warning "too many" "too many args in all branches" } */
printf ((nfoo > 1) ? "%d foos" : "", nfoo);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "1 foo" : "no foos"), nfoo);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%ld foos"), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf ((nfoo > 1) ? "%ld foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%ld foo" : "%d foos"), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%ld foos"), nfoo); /* { dg-warning "long int" "wrong type" } */
printf ((nfoo > 1) ? "%ld foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo); /* { dg-warning "long int" "wrong type" } */
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%ld foo" : "%d foos"), nfoo); /* { dg-warning "long int" "wrong type" } */
/* Extra arguments to NULL should be complained about. */
printf (NULL, "foo"); /* { dg-warning "too many" "NULL extra args" } */
/* { dg-warning "null" "null format arg" { target *-*-* } 25 } */

View File

@ -12,7 +12,7 @@ foo (double d)
printf ("%hhf", d); /* { dg-warning "hh" "%hhf warning" } */
/* This should get a message referring to `ll', not to `q'. */
printf ("%llf", d); /* { dg-warning "ll" "%llf warning" } */
/* This should get a message referring to `size_t format', not to
`unsigned int format' or similar. */
printf ("%zu", d); /* { dg-warning "size_t format" "size_t format warning" } */
/* This should get a message referring to 'size_t', not to
'unsigned int' or similar. */
printf ("%zu", d); /* { dg-warning "size_t" "size_t format warning" } */
}

View File

@ -0,0 +1,13 @@
/* Test for format diagnostics. Proper type names (bug 1027). */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
#include "format.h"
void
foo (double d)
{
printf ("%s", &d); /* { dg-warning "char \\*" "correct arg type" } */
scanf ("%zu", &d); /* { dg-warning "size_t \\*" "correct arg type" } */
}

View File

@ -13,16 +13,16 @@ void
foo (long l, int nfoo)
{
printf (ngettext ("%d foo", "%d foos", nfoo), nfoo);
printf (ngettext ("%d foo", "%d foos", l), l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf (ngettext ("%d foo", "%ld foos", l), l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf (ngettext ("%ld foo", "%d foos", l), l); /* { dg-warning "int format" "wrong type in conditional expr" } */
printf (ngettext ("%d foo", "%d foos", l), l); /* { dg-warning "int" "wrong type in conditional expr" } */
printf (ngettext ("%d foo", "%ld foos", l), l); /* { dg-warning "int" "wrong type in conditional expr" } */
printf (ngettext ("%ld foo", "%d foos", l), l); /* { dg-warning "int" "wrong type in conditional expr" } */
/* Should allow one case to have extra arguments. */
printf (ngettext ("1 foo", "%d foos", nfoo), nfoo);
printf (ngettext ("1 foo", "many foos", nfoo), nfoo); /* { dg-warning "too many" "too many args in all branches" } */
printf (ngettext ("", "%d foos", nfoo), nfoo);
printf (ngettext ("1 foo", (nfoo > 0) ? "%d foos" : "no foos", nfoo), nfoo);
printf (ngettext ("%d foo", (nfoo > 0) ? "%d foos" : "no foos", nfoo), nfoo);
printf (ngettext ("%ld foo", (nfoo > 0) ? "%d foos" : "no foos", nfoo), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf (ngettext ("%d foo", (nfoo > 0) ? "%ld foos" : "no foos", nfoo), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf (ngettext ("%d foo", (nfoo > 0) ? "%d foos" : "%ld foos", nfoo), nfoo); /* { dg-warning "long int format" "wrong type" } */
printf (ngettext ("%ld foo", (nfoo > 0) ? "%d foos" : "no foos", nfoo), nfoo); /* { dg-warning "long int" "wrong type" } */
printf (ngettext ("%d foo", (nfoo > 0) ? "%ld foos" : "no foos", nfoo), nfoo); /* { dg-warning "long int" "wrong type" } */
printf (ngettext ("%d foo", (nfoo > 0) ? "%d foos" : "%ld foos", nfoo), nfoo); /* { dg-warning "long int" "wrong type" } */
}

View File

@ -89,7 +89,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
/* The use of operand number $ formats is an X/Open extension. */
scanf ("%1$d", ip);
printf ("%1$d", i);
printf ("%1$d", l); /* { dg-warning "arg 2" "mismatched args with $ format" } */
printf ("%1$d", l); /* { dg-warning "arg 2|argument 2" "mismatched args with $ format" } */
printf ("%3$*2$.*1$ld", i2, i, l);
printf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", i, i, i, l, i, i, l);
scanf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", ip, ip, ip, lp, ip, ip, lp);