This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC]: patch for PR c/22476 -Wmissing-format-attribute
- From: "Kaveh R. Ghazi" <ghazi at caipclassic dot rutgers dot edu>
- To: joseph at codesourcery dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 Jul 2005 09:16:04 -0400 (EDT)
- Subject: [RFC]: patch for PR c/22476 -Wmissing-format-attribute
Hi Joseph,
I tried writing a patch for "PR c/22476 -Wmissing-format-attribute
should pick out function pointer candidates also". As you suggested
in the PR, I've had some success by putting the detection code in
'convert_for_assignment'.
It works great finding 3 out of 4 cases I expected to see. Namely it
finds places for a format attribute through function pointer
assignment, function call parameters and return statements. However
it fails to find the initialization case as expected in testcase
miss-3.c in the patch below.
For that testcase, GCC never calls 'convert_for_assignment'. Instead
it leaves 'digest_init' through another clause and returns
'inside_init'. What I'm wondering is whether 'digest_init' needs an
additional call to 'convert_for_assignment' on 'inside_init' in the
relevant clause or if I have to duplicate the missing attribute
detection code in that clause in 'digest_init'?
Thoughts?
Thanks,
--Kaveh
diff -rup orig/egcc-CVS20050714/gcc/c-typeck.c egcc-CVS20050714/gcc/c-typeck.c
--- orig/egcc-CVS20050714/gcc/c-typeck.c 2005-07-05 20:01:52.000000000 -0400
+++ egcc-CVS20050714/gcc/c-typeck.c 2005-07-14 23:18:19.308809444 -0400
@@ -3793,6 +3794,36 @@ convert_for_assignment (tree type, tree
warning (OPT_Wc___compat, "request for implicit conversion from "
"%qT to %qT not permitted in C++", rhstype, type);
+ /* Check if the right-hand side has a format attribute but the
+ left-hand side doesn't. */
+ if (warn_missing_format_attribute)
+ {
+ tree rattrs = TYPE_ATTRIBUTES (ttr), ra;
+ for (ra = rattrs; ra; ra = TREE_CHAIN (ra))
+ {
+ if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+ break;
+ }
+ if (ra)
+ {
+ tree lattrs = TYPE_ATTRIBUTES (ttl), la;
+ for (la = lattrs; la; la = TREE_CHAIN (la))
+ {
+ if (is_attribute_p ("format", TREE_PURPOSE (la)))
+ break;
+ }
+ if (!la)
+ WARN_FOR_ASSIGNMENT (G_("argument %d of %qE might be "
+ "a candidate for a format attribute"),
+ G_("assignment left-hand side might be "
+ "a candidate for a format attribute"),
+ G_("initialization left-hand side might be "
+ "a candidate for a format attribute"),
+ G_("return type might be "
+ "a candidate for a format attribute"));
+ }
+ }
+
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
diff -rup orig/egcc-CVS20050714/gcc/cp/call.c egcc-CVS20050714/gcc/cp/call.c
--- orig/egcc-CVS20050714/gcc/cp/call.c 2005-07-02 20:01:21.000000000 -0400
+++ egcc-CVS20050714/gcc/cp/call.c 2005-07-14 21:57:43.130030703 -0400
@@ -194,7 +194,8 @@ static void add_candidates (tree, tree,
int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
-static tree build_temp (tree, tree, int, void (**)(const char *, ...));
+typedef void (*diagnostic_fn_t) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
+static tree build_temp (tree, tree, int, diagnostic_fn_t *);
static void check_constructor_callable (tree, tree);
/* Returns nonzero iff the destructor name specified in NAME
@@ -4087,7 +4088,7 @@ check_constructor_callable (tree type, t
static tree
build_temp (tree expr, tree type, int flags,
- void (**diagnostic_fn)(const char *, ...))
+ diagnostic_fn_t *diagnostic_fn)
{
int savew, savee;
@@ -4122,7 +4123,7 @@ convert_like_real (conversion *convs, tr
bool c_cast_p)
{
tree totype = convs->type;
- void (*diagnostic_fn)(const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
+ diagnostic_fn_t diagnostic_fn;
if (convs->bad_p
&& convs->kind != ck_user
diff -rup orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-3.c egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-3.c
--- orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-3.c 2005-07-14 23:04:19.235479456 -0400
+++ egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-3.c 2005-07-14 23:11:41.755136525 -0400
@@ -0,0 +1,26 @@
+/* Test warnings for missing format attributes on function pointers. */
+/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wmissing-format-attribute" } */
+
+#include "format.h"
+
+typedef void (*noattr_t) (const char *, ...);
+typedef noattr_t __attribute__ ((__format__(__printf__, 1, 2))) attr_t;
+
+typedef void (*vnoattr_t) (const char *, va_list);
+typedef vnoattr_t __attribute__ ((__format__(__printf__, 1, 0))) vattr_t;
+
+void
+foo1 (noattr_t na, attr_t a, vnoattr_t vna, vattr_t va)
+{
+ noattr_t na1 = na;
+ noattr_t na2 = a; /* { dg-warning "candidate" "initialization warning" } */
+ attr_t a1 = na;
+ attr_t a2 = a;
+
+ vnoattr_t vna1 = vna;
+ vnoattr_t vna2 = va; /* { dg-warning "candidate" "initialization warning" } */
+ vattr_t va1 = vna;
+ vattr_t va2 = va;
+}
diff -rup orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-4.c egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-4.c
--- orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-4.c 2005-07-14 23:04:20.985296265 -0400
+++ egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-4.c 2005-07-14 23:12:34.500291838 -0400
@@ -0,0 +1,32 @@
+/* Test warnings for missing format attributes on function pointers. */
+/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wmissing-format-attribute" } */
+
+#include "format.h"
+
+typedef void (*noattr_t) (const char *, ...);
+typedef noattr_t __attribute__ ((__format__(__printf__, 1, 2))) attr_t;
+
+typedef void (*vnoattr_t) (const char *, va_list);
+typedef vnoattr_t __attribute__ ((__format__(__printf__, 1, 0))) vattr_t;
+
+void
+foo1 (noattr_t na, attr_t a, vnoattr_t vna, vattr_t va)
+{
+ noattr_t na1, na2;
+ attr_t a1, a2;
+
+ vnoattr_t vna1, vna2;
+ vattr_t va1, va2;
+
+ na1 = na;
+ na2 = a; /* { dg-warning "candidate" "assignment warning" } */
+ a1 = na;
+ a2 = a;
+
+ vna1 = vna;
+ vna2 = va; /* { dg-warning "candidate" "assignment warning" } */
+ va1 = vna;
+ va1 = va;
+}
diff -rup orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-5.c egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-5.c
--- orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-5.c 2005-07-14 23:04:22.705207661 -0400
+++ egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-5.c 2005-07-14 22:54:49.047475585 -0400
@@ -0,0 +1,48 @@
+/* Test warnings for missing format attributes on function pointers. */
+/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wmissing-format-attribute" } */
+
+#include "format.h"
+
+typedef void (*noattr_t) (const char *, ...);
+typedef noattr_t __attribute__ ((__format__(__printf__, 1, 2))) attr_t;
+
+typedef void (*vnoattr_t) (const char *, va_list);
+typedef vnoattr_t __attribute__ ((__format__(__printf__, 1, 0))) vattr_t;
+
+noattr_t
+foo1 (noattr_t na, attr_t a, int i)
+{
+ if (i)
+ return na;
+ else
+ return a; /* { dg-warning "candidate" "return type warning" } */
+}
+
+attr_t
+foo2 (noattr_t na, attr_t a, int i)
+{
+ if (i)
+ return na;
+ else
+ return a;
+}
+
+vnoattr_t
+foo3 (vnoattr_t vna, vattr_t va, int i)
+{
+ if (i)
+ return vna;
+ else
+ return va; /* { dg-warning "candidate" "return type warning" } */
+}
+
+vattr_t
+foo4 (vnoattr_t vna, vattr_t va, int i)
+{
+ if (i)
+ return vna;
+ else
+ return va;
+}
diff -rup orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-6.c egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-6.c
--- orig/egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-6.c 2005-07-14 23:04:24.255023565 -0400
+++ egcc-CVS20050714/gcc/testsuite/gcc.dg/format/miss-6.c 2005-07-14 23:02:07.107520353 -0400
@@ -0,0 +1,31 @@
+/* Test warnings for missing format attributes on function pointers. */
+/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wmissing-format-attribute" } */
+
+#include "format.h"
+
+typedef void (*noattr_t) (const char *, ...);
+typedef noattr_t __attribute__ ((__format__(__printf__, 1, 2))) attr_t;
+
+typedef void (*vnoattr_t) (const char *, va_list);
+typedef vnoattr_t __attribute__ ((__format__(__printf__, 1, 0))) vattr_t;
+
+extern void foo1 (noattr_t);
+extern void foo2 (attr_t);
+extern void foo3 (vnoattr_t);
+extern void foo4 (vattr_t);
+
+void
+foo (noattr_t na, attr_t a, vnoattr_t vna, vattr_t va)
+{
+ foo1 (na);
+ foo1 (a); /* { dg-warning "candidate" "parameter passing warning" } */
+ foo2 (na);
+ foo2 (a);
+
+ foo3 (vna);
+ foo3 (va); /* { dg-warning "candidate" "parameter passing warning" } */
+ foo4 (vna);
+ foo4 (va);
+}