Subject: bin/578: cc's -Wformat doesn't grok q modifier
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
List: netbsd-bugs
Date: 11/18/1994 11:05:04
>Number:         578
>Category:       bin
>Synopsis:       cc's -Wformat doesn't grok q modifier
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    gnats-admin (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 18 11:05:02 1994
>Originator:     der Mouse
>Organization:
	Dis-
>Release:        NetBSD/sparc 1.0
>Environment:
	SPARC IPC, not that it matters (this is machine-independent
	code)
>Description:
	gcc -Wformat gripes about formats like %qd, which use the q
	modifier.  But these work, and are necessary to print long
	longs (which occur as quad_t in several syscall interfaces),
	while -Wformat is very useful.  IMO -Wformat should agree with
	printf(), even if that means making it slightly non-ANSI.  (The
	patch below does cause q to produce a gripe in the presence of
	-pedantic.)
>How-To-Repeat:
	(hmm, is this #include going to vanish because send-pr doesn't
	like angle-bracketed stuff? :-)  (It includes stdio.h, in case
	it does vanish.)

	% cat > foo.c
	#include <stdio.h>
	main() { printf("%qd\n",(long long int)1); }
	<EOF>
	% cc -Wformat -o foo foo.c
	foo.c: In function `main':
	foo.c:2: warning: unknown conversion type character `q' in format
	foo.c:2: warning: too many arguments for format
	% foo
	1
	% 
>Fix:
	Apply the following patch to
	/usr/src/gnu/usr.bin/gcc2/cc1/c-typeck.c (this is relative to
	the 1.0 release source).

	--- /sources/1.0-usr-src/gnu/usr.bin/gcc2/cc1/c-typeck.c	Mon Aug  2 14:26:21 1993
	+++ c-typeck.c	Fri Nov 18 13:56:02 1994
	@@ -1319,9 +1319,11 @@
	 #define T_I	&integer_type_node
	 #define T_L	&long_integer_type_node
	 #define T_S	&short_integer_type_node
	+#define T_LL	&long_long_integer_type_node
	 #define T_UI	&unsigned_type_node
	 #define T_UL	&long_unsigned_type_node
	 #define T_US	&short_unsigned_type_node
	+#define T_ULL	&long_long_unsigned_type_node
	 #define T_F	&float_type_node
	 #define T_D	&double_type_node
	 #define T_LD	&long_double_type_node
	@@ -1344,36 +1346,39 @@
	   /* Type of argument if length modifier `L' is used.
	      If NULL, then this modifier is not allowed.  */
	   tree *bigllen;
	+  /* Type of argument if length modifier `q' is used.
	+     If NULL, then this modifier is not allowed.  */
	+  tree *qlen;
	   /* List of other modifier characters allowed with these options.  */
	   char *flag_chars;
	 } format_char_info;
	 
	 static format_char_info print_table[]
	   = {
	-      { "di",		0,	T_I,	T_I,	T_L,	NULL,	"-wp0 +" },
	-      { "oxX",		0,	T_UI,	T_UI,	T_UL,	NULL,	"-wp0#" },
	-      { "u",		0,	T_UI,	T_UI,	T_UL,	NULL,	"-wp0" },
	-      { "feEgG",	0,	T_D,	NULL,	NULL,	T_LD,	"-wp0 +#" },
	-      { "c",		0,	T_I,	NULL,	T_W,	NULL,	"-w" },
	-      { "C",		0,	T_W,	NULL,	NULL,	NULL,	"-w" },
	-      { "s",		1,	T_C,	NULL,	T_W,	NULL,	"-wp" },
	-      { "S",		1,	T_W,	NULL,	NULL,	NULL,	"-wp" },
	-      { "p",		1,	T_V,	NULL,	NULL,	NULL,	"-" },
	-      { "n",		1,	T_I,	T_S,	T_L,	NULL,	"" },
	+      { "di",	0,	T_I,	T_I,	T_L,	NULL,	T_LL,	"-wp0 +" },
	+      { "oxX",	0,	T_UI,	T_UI,	T_UL,	NULL,	T_ULL,	"-wp0#" },
	+      { "u",	0,	T_UI,	T_UI,	T_UL,	NULL,	T_ULL,	"-wp0" },
	+      { "feEgG",0,	T_D,	NULL,	NULL,	T_LD,	NULL,	"-wp0 +#" },
	+      { "c",	0,	T_I,	NULL,	T_W,	NULL,	NULL,	"-w" },
	+      { "C",	0,	T_W,	NULL,	NULL,	NULL,	NULL,	"-w" },
	+      { "s",	1,	T_C,	NULL,	T_W,	NULL,	NULL,	"-wp" },
	+      { "S",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"-wp" },
	+      { "p",	1,	T_V,	NULL,	NULL,	NULL,	NULL,	"-" },
	+      { "n",	1,	T_I,	T_S,	T_L,	NULL,	T_LL,	"" },
	       { NULL }
	     };
	 
	 static format_char_info scan_table[]
	   = {
	-      { "di",		1,	T_I,	T_S,	T_L,	NULL,	"*" },
	-      { "ouxX",		1,	T_UI,	T_US,	T_UL,	NULL,	"*" },	
	-      { "efgEG",	1,	T_F,	NULL,	T_D,	T_LD,	"*" },
	-      { "sc",		1,	T_C,	NULL,	T_W,	NULL,	"*" },
	-      { "[",		1,	T_C,	NULL,	NULL,	NULL,	"*" },
	-      { "C",		1,	T_W,	NULL,	NULL,	NULL,	"*" },
	-      { "S",		1,	T_W,	NULL,	NULL,	NULL,	"*" },
	-      { "p",		2,	T_V,	NULL,	NULL,	NULL,	"*" },
	-      { "n",		1,	T_I,	T_S,	T_L,	NULL,	"" },
	+      { "di",	1,	T_I,	T_S,	T_L,	NULL,	T_LL,	"*" },
	+      { "ouxX",	1,	T_UI,	T_US,	T_UL,	NULL,	T_ULL,	"*" },
	+      { "efgEG",1,	T_F,	NULL,	T_D,	T_LD,	NULL,	"*" },
	+      { "sc",	1,	T_C,	NULL,	T_W,	NULL,	NULL,	"*" },
	+      { "[",	1,	T_C,	NULL,	NULL,	NULL,	NULL,	"*" },
	+      { "C",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"*" },
	+      { "S",	1,	T_W,	NULL,	NULL,	NULL,	NULL,	"*" },
	+      { "p",	2,	T_V,	NULL,	NULL,	NULL,	NULL,	"*" },
	+      { "n",	1,	T_I,	T_S,	T_L,	NULL,	T_LL,	"" },
	       { NULL }
	     };
	 
	@@ -1645,8 +1650,15 @@
	 		}
	 	    }
	 	}
	-      if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'L')
	-	length_char = *format_chars++;
	+      if ( *format_chars == 'h' ||
	+	   *format_chars == 'l' ||
	+	   *format_chars == 'L' ||
	+	   *format_chars == 'q' )
	+	{
	+	  length_char = *format_chars++;
	+	  if (pedantic && (length_char == 'q'))
	+	    pedwarn ("ANSI C does not allow the q format modifier");
	+	}
	       else
	 	length_char = 0;
	       if (suppressed && length_char != 0)
	@@ -1732,6 +1744,7 @@
	 	case 'h': wanted_type = fci->hlen ? *(fci->hlen) : 0; break;
	 	case 'l': wanted_type = fci->llen ? *(fci->llen) : 0; break;
	 	case 'L': wanted_type = fci->bigllen ? *(fci->bigllen) : 0; break;
	+	case 'q': wanted_type = fci->qlen ? *(fci->qlen) : 0; break;
	 	}
	       if (wanted_type == 0)
	 	{
>Audit-Trail:
>Unformatted: