[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-patches
Subject:    Patch for c/1027
From:       "Joseph S. Myers" <jsm () polyomino ! org ! uk>
Date:       2004-06-30 21:02:50
Message-ID: Pine.LNX.4.58.0406302101110.22313 () digraph ! polyomino ! org ! uk
[Download RAW message or body]

This patch hooks up %T in the C and Objective-C front ends to the
pretty-printer for types (arranging for it to use C style for pointers
when in C mode), and uses this to fix bug 1027, improving the
diagnostics for incorrect format argument types along the lines
discussed in that bug report.  It depends on
<http://gcc.gnu.org/ml/gcc-patches/2004-06/msg02366.html> which is
awaiting review of C++ front-end changes.  Bootstrapped with no
regressions on i686-pc-linux-gnu.  OK to commit (the Objective-C
front-end change)?

(There are still other format diagnostics that use the abbreviated
style "arg %d" objected to in the comments on that bug report, which
could be improved, but this patch fixes the issues described in the
original report.)

2004-06-30  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.

testsuite:
2004-06-30  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.


-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

diff -rupN gcc.orig/c-format.c gcc/c-format.c
--- gcc.orig/c-format.c	2004-06-30 09:43:58.000000000 +0000
+++ gcc/c-format.c	2004-06-30 17:00:40.000000000 +0000
@@ -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_checkin
 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_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_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_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 *
       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 *
       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 *
 	    }
 	  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 *
       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 *
 	  && 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 -rupN gcc.orig/c-lang.c gcc/c-lang.c
--- gcc.orig/c-lang.c	2004-06-27 18:47:45.000000000 +0000
+++ gcc/c-lang.c	2004-06-30 17:09:28.000000000 +0000
@@ -34,8 +34,6 @@ Software Foundation, 59 Temple Place - S
 #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 -rupN gcc.orig/c-objc-common.c gcc/c-objc-common.c
--- gcc.orig/c-objc-common.c	2004-06-21 12:29:14.000000000 +0000
+++ gcc/c-objc-common.c	2004-06-30 17:08:56.000000000 +0000
@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - S
 #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"
@@ -249,7 +250,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)
     {
@@ -261,14 +265,22 @@ c_tree_printer (pretty_printer *pp, 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':
@@ -282,7 +294,7 @@ c_tree_printer (pretty_printer *pp, text
       return false;
     }
 
-  pp_string (pp, n);
+  pp_string (cpp, n);
   return true;
 }
 
@@ -320,3 +332,16 @@ has_c_linkage (tree decl ATTRIBUTE_UNUSE
 {
   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 -rupN gcc.orig/c-pretty-print.c gcc/c-pretty-print.c
--- gcc.orig/c-pretty-print.c	2004-06-27 18:47:45.000000000 +0000
+++ gcc/c-pretty-print.c	2004-06-30 16:59:07.000000000 +0000
@@ -384,6 +384,8 @@ pp_c_specifier_qualifier_list (c_pretty_
             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_prett
 
     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 -rupN gcc.orig/c-tree.h gcc/c-tree.h
--- gcc.orig/c-tree.h	2004-06-25 08:53:42.000000000 +0000
+++ gcc/c-tree.h	2004-06-30 17:16:26.000000000 +0000
@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - S
 #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_con
 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 -rupN gcc.orig/objc/objc-lang.c gcc/objc/objc-lang.c
--- gcc.orig/objc/objc-lang.c	2004-06-27 18:47:53.000000000 +0000
+++ gcc/objc/objc-lang.c	2004-06-30 17:09:43.000000000 +0000
@@ -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_ob
 #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 -rupN gcc.orig/testsuite/gcc.dg/Wswitch-enum.c \
                gcc/testsuite/gcc.dg/Wswitch-enum.c
--- gcc.orig/testsuite/gcc.dg/Wswitch-enum.c	2004-05-13 08:47:52.000000000 +0000
+++ gcc/testsuite/gcc.dg/Wswitch-enum.c	2004-06-30 16:30:04.000000000 +0000
@@ -50,13 +50,13 @@ foo (int i, int j, enum e ei, enum e ej,
     {
     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 -rupN gcc.orig/testsuite/gcc.dg/Wswitch.c gcc/testsuite/gcc.dg/Wswitch.c
--- gcc.orig/testsuite/gcc.dg/Wswitch.c	2004-05-13 08:47:52.000000000 +0000
+++ gcc/testsuite/gcc.dg/Wswitch.c	2004-06-30 16:29:42.000000000 +0000
@@ -50,7 +50,7 @@ foo (int i, int j, enum e ei, enum e ej,
     {
     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 -rupN gcc.orig/testsuite/gcc.dg/format/branch-1.c \
                gcc/testsuite/gcc.dg/format/branch-1.c
--- gcc.orig/testsuite/gcc.dg/format/branch-1.c	2001-01-07 10:41:52.000000000 +0000
+++ gcc/testsuite/gcc.dg/format/branch-1.c	2004-06-30 16:20:01.000000000 +0000
@@ -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 -rupN gcc.orig/testsuite/gcc.dg/format/diag-1.c \
                gcc/testsuite/gcc.dg/format/diag-1.c
--- gcc.orig/testsuite/gcc.dg/format/diag-1.c	2001-01-07 10:41:52.000000000 +0000
+++ gcc/testsuite/gcc.dg/format/diag-1.c	2004-06-30 12:59:06.000000000 +0000
@@ -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 -rupN gcc.orig/testsuite/gcc.dg/format/diag-2.c \
                gcc/testsuite/gcc.dg/format/diag-2.c
--- gcc.orig/testsuite/gcc.dg/format/diag-2.c	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/format/diag-2.c	2004-06-30 13:25:23.000000000 +0000
@@ -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" } */
+}
diff -rupN gcc.orig/testsuite/gcc.dg/format/multattr-3.c \
                gcc/testsuite/gcc.dg/format/multattr-3.c
--- gcc.orig/testsuite/gcc.dg/format/multattr-3.c	2001-10-02 07:13:29.000000000 +0000
+++ gcc/testsuite/gcc.dg/format/multattr-3.c	2004-06-30 16:20:18.000000000 +0000
@@ -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 -rupN gcc.orig/testsuite/gcc.dg/format/xopen-1.c \
                gcc/testsuite/gcc.dg/format/xopen-1.c
--- gcc.orig/testsuite/gcc.dg/format/xopen-1.c	2004-05-14 20:44:19.000000000 +0000
+++ gcc/testsuite/gcc.dg/format/xopen-1.c	2004-06-30 16:19:32.000000000 +0000
@@ -89,7 +89,7 @@ foo (int i, unsigned int u, wint_t lc, w
   /* 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);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic