mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-10 20:50:09 +08:00
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:
parent
d59c7b4bdc
commit
ede1a38729
@ -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:
|
||||
|
162
gcc/c-format.c
162
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");
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
14
gcc/c-lang.c
14
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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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), \
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 } */
|
||||
|
@ -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" } */
|
||||
}
|
||||
|
13
gcc/testsuite/gcc.dg/format/diag-2.c
Normal file
13
gcc/testsuite/gcc.dg/format/diag-2.c
Normal 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" } */
|
||||
}
|
@ -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" } */
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user