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]

Patch for finer grained format checking options


This patch provides some more fine grained format checking options:
-Wno-format-y2k and -Wno-format-extra-args to disable particular
warnings (of use to NetBSD); -Wformat-nonliteral for the warnings for
non-string-literal format strings; and it documents -Wformat=2 as
being -Wformat plus any non-default format warning options, so
presently -Wformat -Wformat-nonliteral.

Bootstrapped with no regressions on i686-pc-linux-gnu.  OK to commit?

gcc/ChangeLog:
2000-11-16  Joseph S. Myers  <jsm28@cam.ac.uk>

	* c-common.c (warn_format, warn_format_y2k,
	warn_format_extra_args, warn_format_nonliteral): Define.
	(check_format_info): Check warn_format_nonliteral and
	warn_format_extra_args.
	(check_format_info_main): Check warn_format_y2k.
	(set_Wformat): New function.
	* c-common.h (warn_format_y2k, warn_format_extra_args,
	warn_format_nonliteral, set_Wformat): Declare.
	* c-decl.c (warn_format): Remove definition.
	(c_decode_option): Handle -Wformat-nonliteral,
	-Wno-format-extra-args and -Wno-format-y2k, and negated versions.
	Use set_Wformat.
	* invoke.texi: Document these new options and -Wformat=2.
	* toplev.c (documented_lang_options): Add these new options.

gcc/cp/ChangeLog:
2000-11-16  Joseph S. Myers  <jsm28@cam.ac.uk>

	* decl2.c (warn_format): Remove definition.
	(lang_decode_option): Handle -Wformat-nonliteral,
	-Wno-format-extra-args and -Wno-format-y2k.  Use set_Wformat.

gcc/testsuite/ChangeLog:
2000-11-16  Joseph S. Myers  <jsm28@cam.ac.uk>

	* gcc.dg/format-no-exargs-1.c, gcc.dg/format-no-y2k-1.c,
	gcc.dg/format-nonlit-1.c, gcc.dg/format-nonlit-2.c: New tests.

--- c-common.c.orig	Wed Nov 15 17:28:45 2000
+++ c-common.c	Thu Nov 16 15:57:55 2000
@@ -154,6 +154,22 @@ int flag_no_nonansi_builtin;

 const char *flag_dump_translation_unit;

+/* Warn about *printf or *scanf format/argument anomalies. */
+
+int warn_format;
+
+/* Warn about Y2K problems with strftime formats.  */
+
+int warn_format_y2k;
+
+/* Warn about excess arguments to formats.  */
+
+int warn_format_extra_args;
+
+/* Warn about non-literal format arguments.  */
+
+int warn_format_nonliteral;
+
 /* Nonzero means warn about possible violations of sequence point rules.  */

 int warn_sequence_point;
@@ -2304,7 +2320,7 @@ check_format_info (status, info, params)
       /* Functions taking a va_list normally pass a non-literal format
 	 string.  These functions typically are declared with
 	 first_arg_num == 0, so avoid warning in those cases.  */
-      if (info->first_arg_num != 0 && warn_format > 1)
+      if (info->first_arg_num != 0 && warn_format_nonliteral)
 	status_warning (status, "format not a string literal, argument types not checked");
     }

@@ -2316,10 +2332,10 @@ check_format_info (status, info, params)
      If the format is an empty string, this should be counted similarly to the
      case of extra format arguments.  */
   if (res.number_extra_args > 0 && res.number_non_literal == 0
-      && res.number_other == 0)
+      && res.number_other == 0 && warn_format_extra_args)
     status_warning (status, "too many arguments for format");
   if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
-      && res.number_other == 0)
+      && res.number_other == 0 && warn_format_extra_args)
     status_warning (status, "unused arguments in $-style format");
   if (res.number_empty > 0 && res.number_non_literal == 0
       && res.number_other == 0)
@@ -2974,23 +2990,24 @@ check_format_info_main (status, res, inf
 	}

       /* Give Y2K warnings.  */
-      {
-	int y2k_level = 0;
-	if (strchr (fci->flags2, '4') != 0)
-	  if (strchr (flag_chars, 'E') != 0)
+      if (warn_format_y2k)
+	{
+	  int y2k_level = 0;
+	  if (strchr (fci->flags2, '4') != 0)
+	    if (strchr (flag_chars, 'E') != 0)
+	      y2k_level = 3;
+	    else
+	      y2k_level = 2;
+	  else if (strchr (fci->flags2, '3') != 0)
 	    y2k_level = 3;
-	  else
+	  else if (strchr (fci->flags2, '2') != 0)
 	    y2k_level = 2;
-	else if (strchr (fci->flags2, '3') != 0)
-	  y2k_level = 3;
-	else if (strchr (fci->flags2, '2') != 0)
-	  y2k_level = 2;
-	if (y2k_level == 3)
-	  status_warning (status, "`%%%c' yields only last 2 digits of year in some locales",
-			  format_char);
-	else if (y2k_level == 2)
-	  status_warning (status, "`%%%c' yields only last 2 digits of year", format_char);
-      }
+	  if (y2k_level == 3)
+	    status_warning (status, "`%%%c' yields only last 2 digits of year in some locales",
+			    format_char);
+	  else if (y2k_level == 2)
+	    status_warning (status, "`%%%c' yields only last 2 digits of year", format_char);
+	}

       if (strchr (fci->flags2, '[') != 0)
 	{
@@ -3307,6 +3324,19 @@ check_format_types (status, types)
 	  }
       }
     }
+}
+
+/* Set format warning options according to a -Wformat=n option.  */
+
+void
+set_Wformat (setting)
+     int setting;
+{
+  warn_format = setting;
+  warn_format_y2k = setting;
+  warn_format_extra_args = setting;
+  if (setting != 1)
+    warn_format_nonliteral = setting;
 }

 /* Print a warning if a constant expression had overflow in folding.
--- c-common.h.orig	Wed Nov 15 02:27:18 2000
+++ c-common.h	Thu Nov 16 15:53:20 2000
@@ -349,6 +349,18 @@ extern int flag_const_strings;

 extern int warn_format;

+/* Warn about Y2K problems with strftime formats.  */
+
+extern int warn_format_y2k;
+
+/* Warn about excess arguments to formats.  */
+
+extern int warn_format_extra_args;
+
+/* Warn about non-literal format arguments.  */
+
+extern int warn_format_nonliteral;
+
 /* Warn about possible violations of sequence point rules.  */

 extern int warn_sequence_point;
@@ -443,6 +455,7 @@ extern void declare_function_name		PARAM
 extern void decl_attributes			PARAMS ((tree, tree, tree));
 extern void init_function_format_info		PARAMS ((void));
 extern void check_function_format		PARAMS ((int *, tree, tree, tree));
+extern void set_Wformat				PARAMS ((int));
 extern void c_apply_type_quals_to_decl		PARAMS ((int, tree));
 /* Print an error message for invalid operands to arith operation CODE.
    NOP_EXPR is used as a special case (see truthvalue_conversion).  */
--- c-decl.c.orig	Wed Nov 15 02:27:18 2000
+++ c-decl.c	Thu Nov 16 16:19:29 2000
@@ -448,10 +448,6 @@ int warn_redundant_decls = 0;

 int warn_nested_externs = 0;

-/* Warn about *printf or *scanf format/argument anomalies.  */
-
-int warn_format;
-
 /* Warn about a subscript that has type char.  */

 int warn_char_subscripts = 0;
@@ -749,11 +745,23 @@ c_decode_option (argc, argv)
   else if (!strcmp (p, "-Wno-traditional"))
     warn_traditional = 0;
   else if (!strncmp (p, "-Wformat=", 9))
-    warn_format = atol (p + 9);
+    set_Wformat (atoi (p + 9));
   else if (!strcmp (p, "-Wformat"))
-    warn_format = 1;
+    set_Wformat (1);
   else if (!strcmp (p, "-Wno-format"))
-    warn_format = 0;
+    set_Wformat (0);
+  else if (!strcmp (p, "-Wformat-y2k"))
+    warn_format_y2k = 1;
+  else if (!strcmp (p, "-Wno-format-y2k"))
+    warn_format_y2k = 0;
+  else if (!strcmp (p, "-Wformat-extra-args"))
+    warn_format_extra_args = 1;
+  else if (!strcmp (p, "-Wno-format-extra-args"))
+    warn_format_extra_args = 0;
+  else if (!strcmp (p, "-Wformat-nonliteral"))
+    warn_format_nonliteral = 1;
+  else if (!strcmp (p, "-Wno-format-nonliteral"))
+    warn_format_nonliteral = 0;
   else if (!strcmp (p, "-Wchar-subscripts"))
     warn_char_subscripts = 1;
   else if (!strcmp (p, "-Wno-char-subscripts"))
@@ -832,7 +840,7 @@ c_decode_option (argc, argv)
       warn_return_type = 1;
       set_Wunused (1);
       warn_switch = 1;
-      warn_format = 1;
+      set_Wformat (1);
       warn_char_subscripts = 1;
       warn_parentheses = 1;
       warn_sequence_point = 1;
--- invoke.texi.orig	Mon Nov 13 14:01:26 2000
+++ invoke.texi	Thu Nov 16 16:17:33 2000
@@ -143,7 +143,8 @@ in the following sections.
 -w  -W  -Wall  -Waggregate-return
 -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment
 -Wconversion  -Wdisabled-optimization -Werror
--Wfloat-equal  -Wformat
+-Wfloat-equal  -Wformat  -Wformat=2
+-Wformat-nonliteral
 -Wid-clash-@var{len}  -Wimplicit -Wimplicit-int
 -Wimplicit-function-declaration
 -Werror-implicit-function-declaration
@@ -151,7 +152,8 @@ in the following sections.
 -Wlarger-than-@var{len}  -Wlong-long
 -Wmain  -Wmissing-declarations
 -Wmissing-format-attribute  -Wmissing-noreturn
--Wmultichar  -Wno-import  -Wpacked  -Wpadded
+-Wmultichar  -Wno-format-extra-args -Wno-format-y2k
+-Wno-import  -Wpacked  -Wpadded
 -Wparentheses -Wpointer-arith  -Wredundant-decls
 -Wreturn-type  -Wsequence-point  -Wshadow
 -Wsign-compare  -Wswitch  -Wsystem-headers
@@ -1547,6 +1549,30 @@ comment, or whenever a Backslash-Newline
 Check calls to @code{printf} and @code{scanf}, etc., to make sure that
 the arguments supplied have types appropriate to the format string
 specified.
+
+@samp{-Wformat} is included in @samp{-Wall}.  For more control over some
+aspects of format checking, the options @samp{-Wno-format-y2k},
+@samp{-Wno-format-extra-args}, @samp{-Wformat-nonliteral} and
+@samp{-Wformat=2} are available, but are not included in @samp{-Wall}.
+
+@item -Wno-format-y2k
+If @samp{-Wformat} is specified, do not warn about @code{strftime}
+formats which may yield only a two-digit year.
+
+@item -Wno-format-extra-args
+If @samp{-Wformat} is specified, do not warn about excess arguments to a
+@code{printf} or @code{scanf} format function.  The C standard specifies
+that such arguments are ignored.
+
+@item -Wformat-nonliteral
+If @samp{-Wformat} is specified, also warn if the format string is not a
+string literal and so cannot be checked, unless the format function
+takes its format arguments as a @code{va_list}.
+
+@item -Wformat=2
+Enable @samp{-Wformat} plus format checks not included in
+@samp{-Wformat}.  Currently equivalent to @samp{-Wformat
+-Wformat-nonliteral}.

 @item -Wimplicit-int
 Warn when a declaration does not specify a type.
--- toplev.c.orig	Wed Nov 15 18:47:09 2000
+++ toplev.c	Thu Nov 16 16:00:33 2000
@@ -1227,8 +1227,16 @@ documented_lang_options[] =
   { "-Wno-comments", "" },
   { "-Wconversion", "Warn about possibly confusing type conversions" },
   { "-Wno-conversion", "" },
-  { "-Wformat", "Warn about printf format anomalies" },
+  { "-Wformat", "Warn about printf/scanf/strftime format anomalies" },
   { "-Wno-format", "" },
+  { "-Wformat-y2k", "" },
+  { "-Wno-format-y2k",
+    "Don't warn about strftime formats yielding 2 digit years" },
+  { "-Wformat-extra-args", "" },
+  { "-Wno-format-extra-args",
+    "Don't warn about too many arguments to format functions" },
+  { "-Wformat-nonliteral", "Warn about non-string-literal format strings" },
+  { "-Wno-format-nonliteral", "" },
   { "-Wimplicit-function-declaration",
     "Warn about implicit function declarations" },
   { "-Wno-implicit-function-declaration", "" },
--- cp/decl2.c.orig	Fri Nov 10 07:51:35 2000
+++ cp/decl2.c	Thu Nov 16 16:05:46 2000
@@ -272,10 +272,6 @@ int warn_sign_compare;

 int warn_float_equal = 0;

-/* Warn about *printf or *scanf format/argument anomalies.  */
-
-int warn_format;
-
 /* Warn about functions which might be candidates for format attributes.  */

 int warn_missing_format_attribute;
@@ -735,7 +731,13 @@ lang_decode_option (argc, argv)
       else if (!strcmp (p, "float-equal"))
 	warn_float_equal = setting;
       else if (!strcmp (p, "format"))
-	warn_format = setting;
+	set_Wformat (setting);
+      else if (!strcmp (p, "format-y2k"))
+	warn_format_y2k = setting;
+      else if (!strcmp (p, "format-extra-args"))
+	warn_format_extra_args = setting;
+      else if (!strcmp (p, "format-nonliteral"))
+	warn_format_nonliteral = setting;
       else if (!strcmp (p, "missing-format-attribute"))
 	warn_missing_format_attribute = setting;
       else if (!strcmp (p, "conversion"))
@@ -784,7 +786,7 @@ lang_decode_option (argc, argv)
 	  set_Wunused (setting);
 	  warn_implicit = setting;
 	  warn_switch = setting;
-	  warn_format = setting;
+	  set_Wformat (setting);
 	  warn_parentheses = setting;
 	  warn_missing_braces = setting;
 	  warn_sign_compare = setting;
--- testsuite/gcc.dg/format-no-exargs-1.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/format-no-exargs-1.c	Thu Nov 16 16:26:22 2000
@@ -0,0 +1,14 @@
+/* Test for warnings for extra format arguments being disabled by
+   -Wno-format-extra-args.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wno-format-extra-args" } */
+
+extern int printf (const char *, ...);
+
+void
+foo (int i)
+{
+  printf ("foo", i);
+  printf ("%1$d", i, i);
+}
--- testsuite/gcc.dg/format-no-y2k-1.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/format-no-y2k-1.c	Thu Nov 16 16:23:15 2000
@@ -0,0 +1,16 @@
+/* Test for warnings for Y2K problems being disabled by -Wno-format-y2k.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wno-format-y2k" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct tm;
+
+extern size_t strftime (char *, size_t, const char *, const struct tm *);
+
+void
+foo (char *s, size_t m, const struct tm *tp)
+{
+  strftime (s, m, "%y%c%x", tp);
+}
--- testsuite/gcc.dg/format-nonlit-1.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/format-nonlit-1.c	Thu Nov 16 16:21:41 2000
@@ -0,0 +1,13 @@
+/* Test for warnings for non-string-literal formats.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat -Wformat-nonliteral" } */
+
+extern int printf (const char *, ...);
+
+void
+foo (char *s, int i)
+{
+  printf ((const char *)i, i); /* { dg-warning "argument types" "non-literal" } */
+  printf (s, i); /* { dg-warning "argument types" "non-literal" } */
+}
--- testsuite/gcc.dg/format-nonlit-2.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/format-nonlit-2.c	Thu Nov 16 16:24:46 2000
@@ -0,0 +1,13 @@
+/* Test for warnings for non-string-literal formats.  Test with -Wformat=2.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat=2" } */
+
+extern int printf (const char *, ...);
+
+void
+foo (char *s, int i)
+{
+  printf ((const char *)i, i); /* { dg-warning "argument types" "non-literal" } */
+  printf (s, i); /* { dg-warning "argument types" "non-literal" } */
+}

-- 
Joseph S. Myers
jsm28@cam.ac.uk


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