From: Joseph Myers Date: Thu, 1 Jul 2004 08:52:33 +0000 (+0100) Subject: re PR c/1027 (slightly misleading printf format warning) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ede1a3872913df59f3a1f4299ec5f6c7706d3b7b;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02e841262c9..9ddb7a73368 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2004-07-01 Joseph S. Myers + + 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 * target.h (struct gcc_target): Add new field to struct cxx: diff --git a/gcc/c-format.c b/gcc/c-format.c index 5551ad135c4..98274ee649d 100644 --- a/gcc/c-format.c +++ b/gcc/c-format.c @@ -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"); - } + format_type_warning (types->name, format_start, format_length, + wanted_type, types->pointer_count, + types->wanted_type_name, orig_cur_type, arg_num); + } +} - /* 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); - } - } +/* 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. */ diff --git a/gcc/c-lang.c b/gcc/c-lang.c index 03b05b26efa..14ffea6972b 100644 --- a/gcc/c-lang.c +++ b/gcc/c-lang.c @@ -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" diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index 293884af7f6..1ede9c337a6 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -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); +} diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index fd3ef82ac02..e116f7f2984 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -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)); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 4d99c409f3b..23753027df1 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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), \ diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c index aa0f388e843..b59a47b1bc0 100644 --- a/gcc/objc/objc-lang.c +++ b/gcc/objc/objc-lang.c @@ -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 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0fa26ef157d..5ce65dada2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2004-07-01 Joseph S. Myers + + 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 * gcc.c-torture/compile/20040323-1.c: XFAIL on Solaris 2. diff --git a/gcc/testsuite/gcc.dg/Wswitch-enum.c b/gcc/testsuite/gcc.dg/Wswitch-enum.c index b51ecfdcc9e..24fc26261e6 100644 --- a/gcc/testsuite/gcc.dg/Wswitch-enum.c +++ b/gcc/testsuite/gcc.dg/Wswitch-enum.c @@ -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; diff --git a/gcc/testsuite/gcc.dg/Wswitch.c b/gcc/testsuite/gcc.dg/Wswitch.c index e3deeab0f4b..9ba12d6d3c0 100644 --- a/gcc/testsuite/gcc.dg/Wswitch.c +++ b/gcc/testsuite/gcc.dg/Wswitch.c @@ -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) { diff --git a/gcc/testsuite/gcc.dg/format/branch-1.c b/gcc/testsuite/gcc.dg/format/branch-1.c index 2d071040390..cdff9276281 100644 --- a/gcc/testsuite/gcc.dg/format/branch-1.c +++ b/gcc/testsuite/gcc.dg/format/branch-1.c @@ -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 } */ diff --git a/gcc/testsuite/gcc.dg/format/diag-1.c b/gcc/testsuite/gcc.dg/format/diag-1.c index 1c9a246165b..998e35b9b47 100644 --- a/gcc/testsuite/gcc.dg/format/diag-1.c +++ b/gcc/testsuite/gcc.dg/format/diag-1.c @@ -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" } */ } diff --git a/gcc/testsuite/gcc.dg/format/diag-2.c b/gcc/testsuite/gcc.dg/format/diag-2.c new file mode 100644 index 00000000000..e7578d3f031 --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/diag-2.c @@ -0,0 +1,13 @@ +/* Test for format diagnostics. Proper type names (bug 1027). */ +/* Origin: Joseph Myers */ +/* { 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" } */ +} diff --git a/gcc/testsuite/gcc.dg/format/multattr-3.c b/gcc/testsuite/gcc.dg/format/multattr-3.c index 40467fe2d4c..1d4979a4e74 100644 --- a/gcc/testsuite/gcc.dg/format/multattr-3.c +++ b/gcc/testsuite/gcc.dg/format/multattr-3.c @@ -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" } */ } diff --git a/gcc/testsuite/gcc.dg/format/xopen-1.c b/gcc/testsuite/gcc.dg/format/xopen-1.c index 1462a2c8694..9b098fb1ca3 100644 --- a/gcc/testsuite/gcc.dg/format/xopen-1.c +++ b/gcc/testsuite/gcc.dg/format/xopen-1.c @@ -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);