public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH] Fix bogus function cast warning for functions with common arg subset
Date: Fri, 23 Feb 2018 03:40:00 -0000	[thread overview]
Message-ID: <20180223034045.26231-1-siddhesh@sourceware.org> (raw)

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

             reply	other threads:[~2018-02-23  3:40 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-23  3:40 Siddhesh Poyarekar [this message]
2018-02-23 15:50 ` David Malcolm
2018-02-23 16:12   ` Siddhesh Poyarekar
2018-02-23 18:31     ` Richard Biener
2018-02-23 18:52       ` Siddhesh Poyarekar
2018-02-23 20:02         ` Martin Sebor
2018-02-23 20:32           ` Siddhesh Poyarekar
2018-02-23 21:58             ` Martin Sebor
2018-02-26  6:55               ` Siddhesh Poyarekar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180223034045.26231-1-siddhesh@sourceware.org \
    --to=siddhesh@sourceware.org \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).