[PATCH] Fix bogus function cast warning for functions with common arg subset
Siddhesh Poyarekar
siddhesh@sourceware.org
Fri Feb 23 03:40:00 GMT 2018
Libraries like gtk/glib[1] and python[2] use functions with common
argument subsets to register callbacks. The working idea behind it is
to have a flag in the structure (or some other pre-determined method)
that specifies how the callback is cast and called.
Fix this by not throwing a warning when functions with different
argument list lengths (of M and N where M < N) have compatible
argument types for the first M arguments.
Tested and bootstrapped on x86_64.
Siddhesh
[1] I haven't checked gtk/glib lately, but I remember the G_CALLBACK
interface does similar things
[2] python has the PyCFunction type member ml_meth in PyMethodDef
which is designed to accept a PyCFunctionWithKeywords (3 void *
arguments instead of 2 in PyCFunction) and ml_meth is then cast
internally to either based on flags in the ml_flags member in
PyMethodDef.
gcc/c:
* c-typcheck.c (c_safe_function_type_cast_p): Don't warn on
unequal number of arguments as long as the common argument
types match.
gcc/cp:
* c-typcheck.c (c_safe_function_type_cast_p): Don't warn on
unequal number of arguments as long as the common argument
types match.
gcc/testsuite:
* c-c++-common/Wcast-function-type.c: New test cases.
---
gcc/c/c-typeck.c | 9 +++++++-
gcc/cp/typeck.c | 9 +++++++-
gcc/testsuite/c-c++-common/Wcast-function-type.c | 29 ++++++++++++++++++++++++
3 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 1eae4ea849c..16887cd3ac4 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5520,7 +5520,14 @@ c_safe_function_type_cast_p (tree t1, tree t2)
t1 && t2;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if (!c_safe_arg_type_equiv_p (TREE_VALUE (t1), TREE_VALUE (t2)))
- return false;
+ {
+ /* Don't warn on unequal number of arguments as long as the common
+ argument types match. This is a common idiom for callbacks. */
+ if (t1 == void_list_node || t2 == void_list_node)
+ return true;
+
+ return false;
+ }
return true;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0e7c63dd197..f35dca3a05e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1221,7 +1221,14 @@ cxx_safe_function_type_cast_p (tree t1, tree t2)
t1 && t2;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if (!cxx_safe_arg_type_equiv_p (TREE_VALUE (t1), TREE_VALUE (t2)))
- return false;
+ {
+ /* Don't warn on unequal number of arguments as long as the common
+ argument types match. This is a common idiom for callbacks. */
+ if (t1 == void_list_node || t2 == void_list_node)
+ return true;
+
+ return false;
+ }
return true;
}
diff --git a/gcc/testsuite/c-c++-common/Wcast-function-type.c b/gcc/testsuite/c-c++-common/Wcast-function-type.c
index 81105762ef7..f38ad3fe73d 100644
--- a/gcc/testsuite/c-c++-common/Wcast-function-type.c
+++ b/gcc/testsuite/c-c++-common/Wcast-function-type.c
@@ -2,6 +2,8 @@
/* { dg-options "-Wcast-function-type" } */
int f(long);
+int g(long, double);
+int h(long, double, double, int);
typedef int (f1)(long);
typedef int (f2)(void*);
@@ -14,11 +16,26 @@ typedef void (f4)();
#endif
typedef void (f5)(void);
+typedef int (f6)(long, void *);
+typedef int (f7)(long, double, double);
+typedef int (f8)(long, void *, double);
+
f1 *a;
f2 *b;
f3 *c;
f4 *d;
f5 *e;
+f6 *i;
+f7 *j;
+f8 *k;
+
+f6 *l;
+f7 *m;
+f8 *n;
+
+f6 *o;
+f7 *p;
+f8 *q;
void
foo (void)
@@ -28,4 +45,16 @@ foo (void)
c = (f3 *) f; /* { dg-bogus "incompatible function types" } */
d = (f4 *) f; /* { dg-warning "incompatible function types" } */
e = (f5 *) f; /* { dg-bogus "incompatible function types" } */
+
+ i = (f6 *) f; /* { dg-bogus "incompatible function types" } */
+ j = (f7 *) f; /* { dg-bogus "incompatible function types" } */
+ k = (f8 *) f; /* { dg-bogus "incompatible function types" } */
+
+ l = (f6 *) g; /* { dg-warning "incompatible function types" } */
+ m = (f7 *) g; /* { dg-bogus "incompatible function types" } */
+ n = (f8 *) g; /* { dg-warning "incompatible function types" } */
+
+ o = (f6 *) h; /* { dg-warning "incompatible function types" } */
+ p = (f7 *) h; /* { dg-bogus "incompatible function types" } */
+ q = (f8 *) h; /* { dg-warning "incompatible function types" } */
}
--
2.14.3
More information about the Gcc-patches
mailing list