Commit ede1a387 by Joseph Myers Committed by Joseph Myers

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
parent d59c7b4b
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> 2004-07-01 Nick Clifton <nickc@redhat.com>
* target.h (struct gcc_target): Add new field to struct cxx: * target.h (struct gcc_target): Add new field to struct cxx:
......
...@@ -488,12 +488,10 @@ typedef struct format_wanted_type ...@@ -488,12 +488,10 @@ typedef struct format_wanted_type
/* Whether the argument, dereferenced once, is read from and so /* Whether the argument, dereferenced once, is read from and so
must not be a NULL pointer. */ must not be a NULL pointer. */
int reading_from_flag; int reading_from_flag;
/* If warnings should be of the form "field precision is not type int", /* If warnings should be of the form "field precision should have
the name to use (in this case "field precision"), otherwise NULL, type 'int'", the name to use (in this case "field precision"),
for "%s format, %s arg" type messages. If (in an extension), this otherwise NULL, for "format expects type 'long'" type
is a pointer type, wanted_type_name should be set to include the messages. */
terminating '*' characters of the type name to give a correct
message. */
const char *name; const char *name;
/* The actual parameter to check against the wanted type. */ /* The actual parameter to check against the wanted type. */
tree param; tree param;
...@@ -1031,7 +1029,9 @@ static void finish_dollar_format_checking (format_check_results *, int); ...@@ -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 *, static const format_flag_spec *get_flag_spec (const format_flag_spec *,
int, const char *); 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 /* 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 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, ...@@ -1667,6 +1667,7 @@ check_format_info_main (format_check_results *res,
const format_char_info *fci = NULL; const format_char_info *fci = NULL;
char flag_chars[256]; char flag_chars[256];
int aflag = 0; int aflag = 0;
const char *format_start = format_chars;
if (*format_chars == 0) if (*format_chars == 0)
{ {
if (format_chars - orig_format_chars != format_length) if (format_chars - orig_format_chars != format_length)
...@@ -2255,7 +2256,8 @@ check_format_info_main (format_check_results *res, ...@@ -2255,7 +2256,8 @@ check_format_info_main (format_check_results *res,
} }
if (first_wanted_type != 0) 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, ...@@ -2264,7 +2266,8 @@ check_format_info_main (format_check_results *res,
/* Check the argument types from a single format conversion (possibly /* Check the argument types from a single format conversion (possibly
including width and precision arguments). */ including width and precision arguments). */
static void 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) for (; types != 0; types = types->next)
{ {
...@@ -2279,6 +2282,7 @@ check_format_types (format_wanted_type *types) ...@@ -2279,6 +2282,7 @@ check_format_types (format_wanted_type *types)
cur_type = TREE_TYPE (cur_param); cur_type = TREE_TYPE (cur_param);
if (cur_type == error_mark_node) if (cur_type == error_mark_node)
continue; continue;
orig_cur_type = cur_type;
char_type_flag = 0; char_type_flag = 0;
wanted_type = types->wanted_type; wanted_type = types->wanted_type;
arg_num = types->arg_num; arg_num = types->arg_num;
...@@ -2292,6 +2296,8 @@ check_format_types (format_wanted_type *types) ...@@ -2292,6 +2296,8 @@ check_format_types (format_wanted_type *types)
if (types->pointer_count == 0) if (types->pointer_count == 0)
wanted_type = lang_hooks.types.type_promotes_to (wanted_type); wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
wanted_type = TYPE_MAIN_VARIANT (wanted_type);
STRIP_NOPS (cur_param); STRIP_NOPS (cur_param);
/* Check the types of any additional pointer arguments /* Check the types of any additional pointer arguments
...@@ -2353,10 +2359,10 @@ check_format_types (format_wanted_type *types) ...@@ -2353,10 +2359,10 @@ check_format_types (format_wanted_type *types)
} }
else else
{ {
if (types->pointer_count == 1) format_type_warning (types->name, format_start, format_length,
warning ("format argument is not a pointer (arg %d)", arg_num); wanted_type, types->pointer_count,
else types->wanted_type_name, orig_cur_type,
warning ("format argument is not a pointer to a pointer (arg %d)", arg_num); arg_num);
break; break;
} }
} }
...@@ -2364,7 +2370,6 @@ check_format_types (format_wanted_type *types) ...@@ -2364,7 +2370,6 @@ check_format_types (format_wanted_type *types)
if (i < types->pointer_count) if (i < types->pointer_count)
continue; continue;
orig_cur_type = cur_type;
cur_type = TYPE_MAIN_VARIANT (cur_type); cur_type = TYPE_MAIN_VARIANT (cur_type);
/* Check whether the argument type is a character type. This leniency /* Check whether the argument type is a character type. This leniency
...@@ -2403,67 +2408,80 @@ check_format_types (format_wanted_type *types) ...@@ -2403,67 +2408,80 @@ check_format_types (format_wanted_type *types)
&& char_type_flag) && char_type_flag)
continue; continue;
/* Now we have a type mismatch. */ /* Now we have a type mismatch. */
{ format_type_warning (types->name, format_start, format_length,
const char *this; wanted_type, types->pointer_count,
const char *that; types->wanted_type_name, orig_cur_type, arg_num);
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) /* Give a warning about a format argument of different type from that
{ expected. DESCR is a description such as "field precision", or
/* There may be a better name for the format, e.g. size_t, NULL for an ordinary format. For an ordinary format, FORMAT_START
but we should allow for programs with a perverse typedef points to where the format starts in the format string and
making size_t something other than what the compiler FORMAT_LENGTH is its length. WANTED_TYPE is the type the argument
thinks. */ should have after POINTER_COUNT pointer dereferences.
if (types->wanted_type_name != 0 WANTED_NAME_NAME is a possibly more friendly name of WANTED_TYPE,
&& strcmp (types->wanted_type_name, that) != 0) or NULL if the ordinary name of the type should be used. ARG_TYPE
this = types->wanted_type_name; is the type of the actual argument. ARG_NUM is the number of that
if (types->name != 0) argument. */
warning ("%s is not type %s (arg %d)", types->name, this, static void
arg_num); format_type_warning (const char *descr, const char *format_start,
else int format_length, tree wanted_type, int pointer_count,
warning ("%s format, %s arg (arg %d)", this, that, arg_num); 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 /* Given a format_char_info array FCI, and a character C, this function
returns the index into the conversion_specs where that specifier's returns the index into the conversion_specs where that specifier's
data is located. If the character isn't found it aborts. */ data is located. If the character isn't found it aborts. */
......
...@@ -34,8 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -34,8 +34,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "diagnostic.h" #include "diagnostic.h"
#include "c-pretty-print.h" #include "c-pretty-print.h"
static void c_initialize_diagnostics (diagnostic_context *);
enum c_language_kind c_language = clk_c; enum c_language_kind c_language = clk_c;
/* ### When changing hooks, consider if ObjC needs changing too!! ### */ /* ### When changing hooks, consider if ObjC needs changing too!! ### */
...@@ -210,17 +208,5 @@ c_types_compatible_p (tree x, tree y) ...@@ -210,17 +208,5 @@ c_types_compatible_p (tree x, tree y)
{ {
return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (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" #include "gtype-c.h"
...@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h" #include "insn-config.h"
#include "integrate.h" #include "integrate.h"
#include "c-tree.h" #include "c-tree.h"
#include "c-pretty-print.h"
#include "function.h" #include "function.h"
#include "flags.h" #include "flags.h"
#include "toplev.h" #include "toplev.h"
...@@ -242,7 +243,10 @@ static bool ...@@ -242,7 +243,10 @@ static bool
c_tree_printer (pretty_printer *pp, text_info *text) c_tree_printer (pretty_printer *pp, text_info *text)
{ {
tree t = va_arg (*text->args_ptr, tree); tree t = va_arg (*text->args_ptr, tree);
tree name;
const char *n = "({anonymous})"; const char *n = "({anonymous})";
c_pretty_printer *cpp = (c_pretty_printer *) pp;
pp->padding = pp_none;
switch (*text->format_spec) switch (*text->format_spec)
{ {
...@@ -254,14 +258,22 @@ c_tree_printer (pretty_printer *pp, text_info *text) ...@@ -254,14 +258,22 @@ c_tree_printer (pretty_printer *pp, text_info *text)
case 'T': case 'T':
if (TYPE_P (t)) if (TYPE_P (t))
t = TYPE_NAME (t); name = TYPE_NAME (t);
if (t && TREE_CODE (t) == TYPE_DECL) else
abort ();
if (name && TREE_CODE (name) == TYPE_DECL)
{ {
if (DECL_NAME (t)) if (DECL_NAME (name))
n = lang_hooks.decl_printable_name (t, 2); 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; break;
case 'E': case 'E':
...@@ -275,7 +287,7 @@ c_tree_printer (pretty_printer *pp, text_info *text) ...@@ -275,7 +287,7 @@ c_tree_printer (pretty_printer *pp, text_info *text)
return false; return false;
} }
pp_string (pp, n); pp_string (cpp, n);
return true; return true;
} }
...@@ -313,3 +325,16 @@ has_c_linkage (tree decl ATTRIBUTE_UNUSED) ...@@ -313,3 +325,16 @@ has_c_linkage (tree decl ATTRIBUTE_UNUSED)
{ {
return true; 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);
}
...@@ -384,6 +384,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t) ...@@ -384,6 +384,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
pp_c_whitespace (pp); pp_c_whitespace (pp);
pp_c_left_paren (pp); pp_c_left_paren (pp);
} }
else if (!c_dialect_cxx ())
pp_c_whitespace (pp);
pp_ptr_operator (pp, t); pp_ptr_operator (pp, t);
} }
break; break;
...@@ -487,7 +489,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t) ...@@ -487,7 +489,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t)
case ARRAY_TYPE: case ARRAY_TYPE:
pp_c_left_bracket (pp); 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_expression (pp, TYPE_MAX_VALUE (TYPE_DOMAIN (t)));
pp_c_right_bracket (pp); pp_c_right_bracket (pp);
pp_direct_abstract_declarator (pp, TREE_TYPE (t)); pp_direct_abstract_declarator (pp, TREE_TYPE (t));
......
...@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define GCC_C_TREE_H #define GCC_C_TREE_H
#include "c-common.h" #include "c-common.h"
#include "diagnostic.h"
/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to /* 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. */ 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); ...@@ -204,6 +205,7 @@ extern tree c_objc_common_truthvalue_conversion (tree expr);
extern void c_objc_common_finish_file (void); extern void c_objc_common_finish_file (void);
extern int defer_fn (tree); extern int defer_fn (tree);
extern bool c_warn_unused_global_decl (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) \ #define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type ((TYPE), \ c_build_qualified_type ((TYPE), \
......
/* Language-dependent hooks for Objective-C. /* 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> Contributed by Ziemowit Laski <zlaski@apple.com>
This file is part of GCC. This file is part of GCC.
...@@ -43,6 +43,8 @@ enum c_language_kind c_language = clk_objc; ...@@ -43,6 +43,8 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_FINISH c_common_finish #define LANG_HOOKS_FINISH c_common_finish
#undef LANG_HOOKS_INIT_OPTIONS #undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS c_common_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 #undef LANG_HOOKS_HANDLE_OPTION
#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option #define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
#undef LANG_HOOKS_HANDLE_FILENAME #undef LANG_HOOKS_HANDLE_FILENAME
......
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> 2004-07-01 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.c-torture/compile/20040323-1.c: XFAIL on Solaris 2. * gcc.c-torture/compile/20040323-1.c: XFAIL on Solaris 2.
......
...@@ -50,13 +50,13 @@ foo (int i, int j, enum e ei, enum e ej, enum e ek, enum e el, ...@@ -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 e1: return 1;
case e2: return 2; 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) switch (ep)
{ {
case e1: return 1; case e1: return 1;
case e2: return 2; 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; default: break;
} }
return 0; return 0;
......
...@@ -50,7 +50,7 @@ foo (int i, int j, enum e ei, enum e ej, enum e ek, enum e el, ...@@ -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 e1: return 1;
case e2: return 2; 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) switch (ep)
{ {
......
...@@ -9,18 +9,18 @@ void ...@@ -9,18 +9,18 @@ void
foo (long l, int nfoo) foo (long l, int nfoo)
{ {
printf ((nfoo > 1) ? "%d foos" : "%d foo", 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) ? "%d foos" : "%d foo", l); /* { dg-warning "int" "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) ? "%ld foos" : "%d foo", l); /* { dg-warning "int" "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" : "%ld foo", l); /* { dg-warning "int" "wrong type in conditional expr" } */
/* Should allow one case to have extra arguments. */ /* Should allow one case to have extra arguments. */
printf ((nfoo > 1) ? "%d foos" : "1 foo", nfoo); 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) ? "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);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "1 foo" : "no 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" : "%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) ? "%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 format" "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 format" "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. */ /* Extra arguments to NULL should be complained about. */
printf (NULL, "foo"); /* { dg-warning "too many" "NULL extra args" } */ printf (NULL, "foo"); /* { dg-warning "too many" "NULL extra args" } */
/* { dg-warning "null" "null format arg" { target *-*-* } 25 } */ /* { dg-warning "null" "null format arg" { target *-*-* } 25 } */
......
...@@ -12,7 +12,7 @@ foo (double d) ...@@ -12,7 +12,7 @@ foo (double d)
printf ("%hhf", d); /* { dg-warning "hh" "%hhf warning" } */ printf ("%hhf", d); /* { dg-warning "hh" "%hhf warning" } */
/* This should get a message referring to `ll', not to `q'. */ /* This should get a message referring to `ll', not to `q'. */
printf ("%llf", d); /* { dg-warning "ll" "%llf warning" } */ printf ("%llf", d); /* { dg-warning "ll" "%llf warning" } */
/* This should get a message referring to `size_t format', not to /* This should get a message referring to 'size_t', not to
`unsigned int format' or similar. */ 'unsigned int' or similar. */
printf ("%zu", d); /* { dg-warning "size_t format" "size_t format warning" } */ printf ("%zu", d); /* { dg-warning "size_t" "size_t format warning" } */
} }
/* 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" } */
}
...@@ -13,16 +13,16 @@ void ...@@ -13,16 +13,16 @@ void
foo (long l, int nfoo) foo (long l, int nfoo)
{ {
printf (ngettext ("%d foo", "%d foos", nfoo), 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", "%d foos", l), l); /* { dg-warning "int" "wrong type in conditional expr" } */
printf (ngettext ("%d foo", "%ld foos", l), l); /* { dg-warning "int format" "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 format" "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. */ /* Should allow one case to have extra arguments. */
printf (ngettext ("1 foo", "%d foos", nfoo), nfoo); 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 ("1 foo", "many foos", nfoo), nfoo); /* { dg-warning "too many" "too many args in all branches" } */
printf (ngettext ("", "%d foos", nfoo), nfoo); printf (ngettext ("", "%d foos", nfoo), nfoo);
printf (ngettext ("1 foo", (nfoo > 0) ? "%d foos" : "no 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 ("%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 ("%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 format" "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 format" "wrong type" } */ printf (ngettext ("%d foo", (nfoo > 0) ? "%d foos" : "%ld foos", nfoo), nfoo); /* { dg-warning "long int" "wrong type" } */
} }
...@@ -89,7 +89,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d, ...@@ -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. */ /* The use of operand number $ formats is an X/Open extension. */
scanf ("%1$d", ip); scanf ("%1$d", ip);
printf ("%1$d", i); 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 ("%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); 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); scanf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", ip, ip, ip, lp, ip, ip, lp);
......
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