Patch for -Wconversion diagnostic handling

Joseph S. Myers jsm@polyomino.org.uk
Wed Oct 6 22:35:00 GMT 2004


The -Wconversion warnings do not need the complexity of
warn_for_assignment, as they only apply to the case of argument
passing and with %E each diagnostic needs only a single version
(rather than distinguishing named functions and pointers to
functions).  This patch makes the -Wconversion warnings use warning()
directly, thereby getting rid of some cases (bad for i18n) of messages
being built up from partial sentences, improving diagnostics with the
use of %E and using the word "argument" instead of the shorthand
"arg"; the -Wconversion warnings thereby cease to be errors with
-pedantic-errors (since warn_for_assignment uses pedwarn, though one
target of this patch series is that in some cases it will use warning
instead).

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

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

2004-10-06  Joseph S. Myers  <jsm@polyomino.org.uk>

	* c-typeck.c (convert_arguments): Take expression for called
	function rather than its name.  Handle ObjC selectors directly
	rather than relying on warn_for_assignment to do so.  Call warning
	directly rather than warn_for_assignment.  Use %qE in diagnostics.
	Say "argument" rather than "arg" in diagnostics.
	(build_function_call): Update call to convert_arguments.

testsuite:
2004-10-06  Joseph S. Myers  <jsm@polyomino.org.uk>

	* gcc.dg/Wconversion-2.c, gcc.dg/func-args-1.c: New tests.

diff -rupN GCC.orig/gcc/c-typeck.c GCC/gcc/c-typeck.c
--- GCC.orig/gcc/c-typeck.c	2004-10-03 20:50:28.000000000 +0000
+++ GCC/gcc/c-typeck.c	2004-10-06 16:49:54.000000000 +0000
@@ -1976,7 +1976,7 @@ build_function_call (tree function, tree
      function prototype, or apply default promotions.  */
 
   coerced_params
-    = convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
+    = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
 
   /* Check that the arguments to the function are valid.  */
 
@@ -2014,7 +2014,8 @@ build_function_call (tree function, tree
    It may be 0, if that info is not available.
    It is used only for generating error messages.
 
-   NAME is an IDENTIFIER_NODE or 0.  It is used only for error messages.
+   FUNCTION is a tree for the called function.  It is used only for
+   error messages, where it is formatted with %qE.
 
    This is also where warnings about wrong number of args are generated.
 
@@ -2022,11 +2023,25 @@ build_function_call (tree function, tree
    with the elements of the list in the TREE_VALUE slots of those nodes.  */
 
 static tree
-convert_arguments (tree typelist, tree values, tree name, tree fundecl)
+convert_arguments (tree typelist, tree values, tree function, tree fundecl)
 {
   tree typetail, valtail;
   tree result = NULL;
   int parmnum;
+  tree selector;
+  tree name = NULL_TREE;
+
+  /* Determine the function name for the use of convert_for_assignment
+     and warn_for_assignment called from there.  */
+  if (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+    {
+      function = TREE_OPERAND (function, 0);
+      name = DECL_NAME (function);
+    }
+
+  /* Handle an ObjC selector specially for diagnostics.  */
+  selector = objc_message_selector ();
 
   /* Scan the given expressions and types, producing individual
      converted arguments and pushing them on RESULT in reverse order.  */
@@ -2037,17 +2052,21 @@ convert_arguments (tree typelist, tree v
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
       tree val = TREE_VALUE (valtail);
+      tree rname = function;
+      int argnum = parmnum + 1;
 
       if (type == void_type_node)
 	{
-	  if (name)
-	    error ("too many arguments to function %qs",
-		   IDENTIFIER_POINTER (name));
-	  else
-	    error ("too many arguments to function");
+	  error ("too many arguments to function %qE", function);
 	  break;
 	}
 
+      if (selector && argnum > 2)
+	{
+	  rname = selector;
+	  argnum -= 2;
+	}
+
       /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
       /* Do not use STRIP_NOPS here!  We do not want an enumerator with value 0
 	 to convert automatically to a pointer.  */
@@ -2078,22 +2097,34 @@ convert_arguments (tree typelist, tree v
 
 		  if (INTEGRAL_TYPE_P (type)
 		      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-		    warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as integer "
+			     "rather than floating due to prototype",
+			     argnum, rname);
 		  if (INTEGRAL_TYPE_P (type)
 		      && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-		    warn_for_assignment ("%s as integer rather than complex due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as integer "
+			     "rather than complex due to prototype",
+			     argnum, rname);
 		  else if (TREE_CODE (type) == COMPLEX_TYPE
 			   && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-		    warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as complex "
+			     "rather than floating due to prototype",
+			     argnum, rname);
 		  else if (TREE_CODE (type) == REAL_TYPE
 			   && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-		    warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as floating "
+			     "rather than integer due to prototype",
+			     argnum, rname);
 		  else if (TREE_CODE (type) == COMPLEX_TYPE
 			   && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-		    warn_for_assignment ("%s as complex rather than integer due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as complex "
+			     "rather than integer due to prototype",
+			     argnum, rname);
 		  else if (TREE_CODE (type) == REAL_TYPE
 			   && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-		    warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
+		    warning ("passing argument %d of %qE as floating "
+			     "rather than complex due to prototype",
+			     argnum, rname);
 		  /* ??? At some point, messages should be written about
 		     conversions between complex types, but that's too messy
 		     to do now.  */
@@ -2103,9 +2134,9 @@ convert_arguments (tree typelist, tree v
 		      /* Warn if any argument is passed as `float',
 			 since without a prototype it would be `double'.  */
 		      if (formal_prec == TYPE_PRECISION (float_type_node))
-			warn_for_assignment ("%s as %<float%> rather than "
-					     "%<double%> due to prototype",
-					     (char *) 0, name, parmnum + 1);
+			warning ("passing argument %d of %qE as %<float%> "
+				 "rather than %<double%> due to prototype",
+				 argnum, rname);
 		    }
 		  /* Detect integer changing in width or signedness.
 		     These warnings are only activated with
@@ -2123,7 +2154,8 @@ convert_arguments (tree typelist, tree v
 			   and the actual arg is that enum type.  */
 			;
 		      else if (formal_prec != TYPE_PRECISION (type1))
-			warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1);
+			warning ("passing argument %d of %qE with different "
+				 "width due to prototype", argnum, rname);
 		      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
 			;
 		      /* Don't complain if the formal parameter type
@@ -2149,9 +2181,11 @@ convert_arguments (tree typelist, tree v
 			       && TYPE_UNSIGNED (TREE_TYPE (val)))
 			;
 		      else if (TYPE_UNSIGNED (type))
-			warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);
+			warning ("passing argument %d of %qE as unsigned "
+				 "due to prototype", argnum, rname);
 		      else
-			warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1);
+			warning ("passing argument %d of %qE as signed "
+				 "due to prototype", argnum, rname);
 		    }
 		}
 
@@ -2180,13 +2214,7 @@ convert_arguments (tree typelist, tree v
     }
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
-    {
-      if (name)
-	error ("too few arguments to function %qs",
-	       IDENTIFIER_POINTER (name));
-      else
-	error ("too few arguments to function");
-    }
+    error ("too few arguments to function %qE", function);
 
   return nreverse (result);
 }
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/Wconversion-2.c GCC/gcc/testsuite/gcc.dg/Wconversion-2.c
--- GCC.orig/gcc/testsuite/gcc.dg/Wconversion-2.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/Wconversion-2.c	2004-10-06 09:35:04.000000000 +0000
@@ -0,0 +1,64 @@
+/* Test messages for -Wconversion, including that they are not
+   pedwarns.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors -Wconversion" } */
+
+void fsc(signed char);
+void fsi(signed int);
+void fsll(signed long long);
+void fuc(unsigned char);
+void fui(unsigned int);
+void full(unsigned long long);
+void ff(float);
+void fld(long double);
+void fcf(_Complex float);
+
+struct s {
+  void (*fsc)(signed char);
+  void (*fsi)(signed int);
+  void (*fsll)(signed long long);
+  void (*fuc)(unsigned char);
+  void (*fui)(unsigned int);
+  void (*full)(unsigned long long);
+  void (*ff)(float);
+  void (*fld)(long double);
+  void (*fcf)(_Complex float);
+} x;
+
+signed char sc;
+signed int si;
+signed long long sll;
+unsigned char uc;
+unsigned int ui;
+unsigned long long ull;
+float f;
+long double ld;
+_Complex float cf;
+
+void
+g (void)
+{
+  fsi(f); /* { dg-warning "warning: passing argument 1 of 'fsi' as integer rather than floating due to prototype" } */
+  x.fsi(f); /* { dg-warning "warning: passing argument 1 of 'x.fsi' as integer rather than floating due to prototype" } */
+  fsi(cf); /* { dg-warning "warning: passing argument 1 of 'fsi' as integer rather than complex due to prototype" } */
+  x.fsi(cf); /* { dg-warning "warning: passing argument 1 of 'x.fsi' as integer rather than complex due to prototype" } */
+  fcf(f); /* { dg-warning "warning: passing argument 1 of 'fcf' as complex rather than floating due to prototype" } */
+  x.fcf(f); /* { dg-warning "warning: passing argument 1 of 'x.fcf' as complex rather than floating due to prototype" } */
+  fcf(si); /* { dg-warning "warning: passing argument 1 of 'fcf' as complex rather than integer due to prototype" } */
+  x.fcf(si); /* { dg-warning "warning: passing argument 1 of 'x.fcf' as complex rather than integer due to prototype" } */
+  ff(sc); /* { dg-warning "warning: passing argument 1 of 'ff' as floating rather than integer due to prototype" } */
+  x.ff(sc); /* { dg-warning "warning: passing argument 1 of 'x.ff' as floating rather than integer due to prototype" } */
+  ff(cf); /* { dg-warning "warning: passing argument 1 of 'ff' as floating rather than complex due to prototype" } */
+  x.ff(cf); /* { dg-warning "warning: passing argument 1 of 'x.ff' as floating rather than complex due to prototype" } */
+  ff(1.0); /* { dg-warning "warning: passing argument 1 of 'ff' as 'float' rather than 'double' due to prototype" } */
+  x.ff(1.0); /* { dg-warning "warning: passing argument 1 of 'x.ff' as 'float' rather than 'double' due to prototype" } */
+  fsll(sc); /* { dg-warning "warning: passing argument 1 of 'fsll' with different width due to prototype" } */
+  x.fsll(sc); /* { dg-warning "warning: passing argument 1 of 'x.fsll' with different width due to prototype" } */
+  fsc(sll); /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" } */
+  x.fsc(sll); /* { dg-warning "warning: passing argument 1 of 'x.fsc' with different width due to prototype" } */
+  fsi(ui); /* { dg-warning "warning: passing argument 1 of 'fsi' as signed due to prototype" } */
+  x.fsi(ui); /* { dg-warning "warning: passing argument 1 of 'x.fsi' as signed due to prototype" } */
+  full(sll); /* { dg-warning "warning: passing argument 1 of 'full' as unsigned due to prototype" } */
+  x.full(sll); /* { dg-warning "warning: passing argument 1 of 'x.full' as unsigned due to prototype" } */
+}
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/func-args-1.c GCC/gcc/testsuite/gcc.dg/func-args-1.c
--- GCC.orig/gcc/testsuite/gcc.dg/func-args-1.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/func-args-1.c	2004-10-06 09:19:47.000000000 +0000
@@ -0,0 +1,53 @@
+/* Test messages for wrong number of arguments to function.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void f0(void);
+void f1(int);
+void f1v(int, ...);
+void f2(int, int);
+void f2v(int, int, ...);
+
+struct s {
+  void (*f0)(void);
+  void (*f1)(int);
+  void (*f1v)(int, ...);
+  void (*f2)(int, int);
+  void (*f2v)(int, int, ...);
+} x;
+
+void
+g (int a)
+{
+  f0();
+  x.f0();
+  f0(a); /* { dg-error "error: too many arguments to function 'f0'" } */
+  x.f0(a); /* { dg-error "error: too many arguments to function 'x.f0'" } */
+  f0(a, a); /* { dg-error "error: too many arguments to function 'f0'" } */
+  x.f0(a, a); /* { dg-error "error: too many arguments to function 'x.f0'" } */
+  f1(); /* { dg-error "error: too few arguments to function 'f1'" } */
+  x.f1(); /* { dg-error "error: too few arguments to function 'x.f1'" } */
+  f1(a);
+  x.f1(a);
+  f1(a, a); /* { dg-error "error: too many arguments to function 'f1'" } */
+  x.f1(a, a); /* { dg-error "error: too many arguments to function 'x.f1'" } */
+  f1v(); /* { dg-error "error: too few arguments to function 'f1v'" } */
+  x.f1v(); /* { dg-error "error: too few arguments to function 'x.f1v'" } */
+  f1v(a);
+  x.f1v(a);
+  f1v(a, a);
+  x.f1v(a, a);
+  f2(a); /* { dg-error "error: too few arguments to function 'f2'" } */
+  x.f2(a); /* { dg-error "error: too few arguments to function 'x.f2'" } */
+  f2(a, a);
+  x.f2(a, a);
+  f2(a, a, a); /* { dg-error "error: too many arguments to function 'f2'" } */
+  x.f2(a, a, a); /* { dg-error "error: too many arguments to function 'x.f2'" } */
+  f2v(a); /* { dg-error "error: too few arguments to function 'f2v'" } */
+  x.f2v(a); /* { dg-error "error: too few arguments to function 'x.f2v'" } */
+  f2v(a, a);
+  x.f2v(a, a);
+  f2v(a, a, a);
+  x.f2v(a, a, a);
+}



More information about the Gcc-patches mailing list