c-common.c (check_missing_format_attribute): New.
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Sun, 24 Jul 2005 21:38:02 +0000 (21:38 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Sun, 24 Jul 2005 21:38:02 +0000 (21:38 +0000)
* c-common.c (check_missing_format_attribute): New.
* c-common.h (check_missing_format_attribute): Likewise.
* c-typeck.c (convert_for_assignment): Use it.

cp:
* call.c (convert_for_arg_passing): Check function pointers when
-Wmissing-format-attribute is activated.
* typeck.c (convert_for_assignment): Likewise.

testsuite:
* g++.dg/warn/miss-format-1.C, g++.dg/warn/miss-format-2.C,
g++.dg/warn/miss-format-3.C, g++.dg/warn/miss-format-4.C,
g++.dg/warn/miss-format-5.C, g++.dg/warn/miss-format-6.C: New.

From-SVN: r102338

14 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/miss-format-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/miss-format-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/miss-format-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/miss-format-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/miss-format-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/miss-format-6.C [new file with mode: 0644]

index d86dc82..42c8c2e 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-24  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * c-common.c (check_missing_format_attribute): New.
+       * c-common.h (check_missing_format_attribute): Likewise.
+       * c-typeck.c (convert_for_assignment): Use it.
+
 2005-07-24  Andreas Schwab  <schwab@suse.de>
 
        * config/m68k/m68k.md ("extendqidi2"): When source is an address
index 8646b4c..10350f3 100644 (file)
@@ -6208,4 +6208,30 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2)
     == lang_hooks.types.signed_type (t2);
 }
 
+/* Check for missing format attributes on function pointers.  LTYPE is
+   the new type or left-hand side type.  RTYPE is the old type or
+   right-hand side type.  Returns TRUE if LTYPE is missing the desired
+   attribute.  */
+
+bool
+check_missing_format_attribute (tree ltype, tree rtype)
+{
+  tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+  tree ra;
+
+  for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+    if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+      break;
+  if (ra)
+    {
+      tree la;
+      for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+       if (is_attribute_p ("format", TREE_PURPOSE (la)))
+         break;
+      return !la;
+    }
+  else
+    return false;
+}
+
 #include "gt-c-common.h"
index 76a9650..4e8485a 100644 (file)
@@ -925,6 +925,7 @@ extern void init_pp_output (FILE *);
 extern void preprocess_file (cpp_reader *);
 extern void pp_file_change (const struct line_map *);
 extern void pp_dir_change (cpp_reader *, const char *);
+extern bool check_missing_format_attribute (tree, tree);
 
 /* In order for the format checking to accept the C frontend
    diagnostic framework extensions, you must include this file before
index cb28838..7e98384 100644 (file)
@@ -3802,51 +3802,36 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
-      if (warn_missing_format_attribute)
+      if (warn_missing_format_attribute
+         && check_missing_format_attribute (type, rhstype))
         {
-         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)
-               switch (errtype)
-                 {
-                 case ic_argpass:
-                 case ic_argpass_nonproto:
-                   warning (OPT_Wmissing_format_attribute,
-                            "argument %d of %qE might be "
-                            "a candidate for a format attribute",
-                            parmnum, rname);
-                   break;
-                 case ic_assign:
-                   warning (OPT_Wmissing_format_attribute,
-                            "assignment left-hand side might be "
-                            "a candidate for a format attribute");
-                   break;
-                 case ic_init:
-                   warning (OPT_Wmissing_format_attribute,
-                            "initialization left-hand side might be "
-                            "a candidate for a format attribute");
-                   break;
-                 case ic_return:
-                   warning (OPT_Wmissing_format_attribute,
-                            "return type might be "
-                            "a candidate for a format attribute");
-                   break;
-                 default:
-                   gcc_unreachable ();
-                 }
-           }
+         switch (errtype)
+         {
+         case ic_argpass:
+         case ic_argpass_nonproto:
+           warning (OPT_Wmissing_format_attribute,
+                    "argument %d of %qE might be "
+                    "a candidate for a format attribute",
+                    parmnum, rname);
+           break;
+         case ic_assign:
+           warning (OPT_Wmissing_format_attribute,
+                    "assignment left-hand side might be "
+                    "a candidate for a format attribute");
+           break;
+         case ic_init:
+           warning (OPT_Wmissing_format_attribute,
+                    "initialization left-hand side might be "
+                    "a candidate for a format attribute");
+           break;
+         case ic_return:
+           warning (OPT_Wmissing_format_attribute,
+                    "return type might be "
+                    "a candidate for a format attribute");
+           break;
+         default:
+           gcc_unreachable ();
+         }
        }
       
       /* Any non-function converts to a [const][volatile] void *
index 485de2f..003fbab 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-24  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * call.c (convert_for_arg_passing): Check function pointers when
+       -Wmissing-format-attribute is activated.
+       * typeck.c (convert_for_assignment): Likewise.
+
 2005-07-22  Manfred Hollstein  <mh@suse.com>
 
        * parser.c (cp_parser_declaration): Fix unitialised warnings.
index 4e5ccff..609fe45 100644 (file)
@@ -4601,6 +4601,17 @@ convert_for_arg_passing (tree type, tree val)
           && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
                                   TYPE_SIZE (integer_type_node)))
     val = perform_integral_promotions (val);
+  if (warn_missing_format_attribute)
+    {
+      tree rhstype = TREE_TYPE (val);
+      const enum tree_code coder = TREE_CODE (rhstype);
+      const enum tree_code codel = TREE_CODE (type);
+      if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+         && coder == codel
+         && check_missing_format_attribute (type, rhstype))
+       warning (OPT_Wmissing_format_attribute,
+                "argument of function call might be a candidate for a format attribute");
+    }
   return val;
 }
 
index 9a14f48..62f5297 100644 (file)
@@ -5948,6 +5948,17 @@ convert_for_assignment (tree type, tree rhs,
          return error_mark_node;
        }
     }
+  if (warn_missing_format_attribute)
+    {
+      const enum tree_code codel = TREE_CODE (type);
+      if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+         && coder == codel
+         && check_missing_format_attribute (type, rhstype))
+       warning (OPT_Wmissing_format_attribute,
+                "%s might be a candidate for a format attribute",
+                errtype);
+    }
+  
   return perform_implicit_conversion (strip_top_quals (type), rhs);
 }
 
index 2986250..19d3975 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-24  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * g++.dg/warn/miss-format-1.C, g++.dg/warn/miss-format-2.C,
+       g++.dg/warn/miss-format-3.C, g++.dg/warn/miss-format-4.C,
+       g++.dg/warn/miss-format-5.C, g++.dg/warn/miss-format-6.C: New.
+
 2005-07-23  Jerry DeLisle  <jvdelisle@verizon.net>
 
         * gfortran.fortran-torture/execute/nan_inf_fmt.f90: Revise test to
diff --git a/gcc/testsuite/g++.dg/warn/miss-format-1.C b/gcc/testsuite/g++.dg/warn/miss-format-1.C
new file mode 100644 (file)
index 0000000..f69e18f
--- /dev/null
@@ -0,0 +1,40 @@
+/* Test for warnings for missing format attributes.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-Wmissing-format-attribute" } */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+void
+foo (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  vprintf (fmt, ap); /* { dg-warning "candidate" "printf attribute warning" } */
+  va_end (ap);
+}
+
+void
+bar (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  vscanf (fmt, ap); /* { dg-warning "candidate" "scanf attribute warning" } */
+  va_end (ap);
+}
+
+__attribute__((__format__(__printf__, 1, 2))) void
+foo2 (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  vprintf (fmt, ap);
+  va_end (ap);
+}
+
+void
+vfoo (const char *fmt, va_list arg)
+{
+  vprintf (fmt, arg); /* { dg-warning "candidate" "printf attribute warning 2" } */
+}
diff --git a/gcc/testsuite/g++.dg/warn/miss-format-2.C b/gcc/testsuite/g++.dg/warn/miss-format-2.C
new file mode 100644 (file)
index 0000000..bd7f11b
--- /dev/null
@@ -0,0 +1,17 @@
+/* Test for warnings for missing format attributes.  Don't warn if no
+   relevant parameters for a format attribute; see c/1017.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-Wmissing-format-attribute" } */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+void
+foo (int i, ...)
+{
+  va_list ap;
+  va_start (ap, i);
+  vprintf ("Foo %s bar %s", ap); /* { dg-bogus "candidate" "bogus printf attribute warning" } */
+  va_end (ap);
+}
diff --git a/gcc/testsuite/g++.dg/warn/miss-format-3.C b/gcc/testsuite/g++.dg/warn/miss-format-3.C
new file mode 100644 (file)
index 0000000..0f61400
--- /dev/null
@@ -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 "-Wmissing-format-attribute" } */
+
+#include <stdarg.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 --git a/gcc/testsuite/g++.dg/warn/miss-format-4.C b/gcc/testsuite/g++.dg/warn/miss-format-4.C
new file mode 100644 (file)
index 0000000..1a89abd
--- /dev/null
@@ -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 "-Wmissing-format-attribute" } */
+
+#include <stdarg.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 --git a/gcc/testsuite/g++.dg/warn/miss-format-5.C b/gcc/testsuite/g++.dg/warn/miss-format-5.C
new file mode 100644 (file)
index 0000000..452e812
--- /dev/null
@@ -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 "-Wmissing-format-attribute" } */
+
+#include <stdarg.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 --git a/gcc/testsuite/g++.dg/warn/miss-format-6.C b/gcc/testsuite/g++.dg/warn/miss-format-6.C
new file mode 100644 (file)
index 0000000..f38e4ca
--- /dev/null
@@ -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 "-Wmissing-format-attribute" } */
+
+#include <stdarg.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);
+}