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