This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]