PR c/77520 - wrong value for extended ASCII characters in -Wformat message
authorMartin Sebor <msebor@redhat.com>
Fri, 9 Sep 2016 23:12:10 +0000 (23:12 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Fri, 9 Sep 2016 23:12:10 +0000 (17:12 -0600)
PR c/77520 - wrong value for extended ASCII characters in -Wformat message
PR c/77521 - %qc format directive should quote non-printable characters

gcc/c-family/ChangeLog:

PR c/77520
PR c/77521
* c-format.c (argument_parser::find_format_char_info): Use %qc
format directive unconditionally.

gcc/ChangeLog:

PR c/77520
PR c/77521
* pretty-print.c (pp_quoted_string): New function.
(pp_format): Call it for %c and %s directives.

gcc/testsuite/ChangeLog:

PR c/77520
PR c/77521
* gcc.dg/pr77520.c: New test.
* gcc.dg/pr77521.c: New test.

From-SVN: r240059

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-format.c
gcc/pretty-print.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr77520.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr77521.c [new file with mode: 0644]

index eb8ad6e5a4ba1cf278dfc01ee647c26f5e091035..6892161897338521c117c606b2ba01397591dc2e 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-09  Martin Sebor  <msebor@redhat.com>
+
+       PR c/77520
+       PR c/77521
+       * pretty-print.c (pp_quoted_string): New function.
+       (pp_format): Call it for %c and %s directives.
+
 2016-09-10  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * doc/tm.texi.in (INITIAL_FRAME_POINTER_OFFSET): Remove.
index ba892487aa8657185bd4d191f39f9c65319f1111..9a78b7aaac85ccc7119afd8cf2b11f5080fcbb11 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-09  Martin Sebor  <msebor@redhat.com>
+
+       PR c/77520
+       PR c/77521
+       * c-format.c (argument_parser::find_format_char_info): Use %qc
+       format directive unconditionally.
+
 2016-09-09  Jason Merrill  <jason@redhat.com>
 
        Implement C++17 new of over-aligned types.
index 09d514ec594c00d4fa82e4ae9f3011189eb204f4..0c173409520f16b09661acdf6d067552fa9f8e48 100644 (file)
@@ -2355,20 +2355,12 @@ argument_parser::find_format_char_info (char format_char)
     ++fci;
   if (fci->format_chars == 0)
     {
-      if (ISGRAPH (format_char))
-       format_warning_at_char (format_string_loc, format_string_cst,
-                               format_chars - orig_format_chars,
-                               OPT_Wformat_,
-                               "unknown conversion type character"
-                               " %qc in format",
-                               format_char);
-      else
-       format_warning_at_char (format_string_loc, format_string_cst,
-                               format_chars - orig_format_chars,
-                               OPT_Wformat_,
-                               "unknown conversion type character"
-                               " 0x%x in format",
-                               format_char);
+      format_warning_at_char (format_string_loc, format_string_cst,
+                             format_chars - orig_format_chars,
+                             OPT_Wformat_,
+                             "unknown conversion type character"
+                             " %qc in format",
+                             format_char);
       return NULL;
     }
 
index 325263efd6a53507ca45a368d1cbd4641284bbf1..a39815ea511e1fbd65bd7abd5d4dd95af8e6664b 100644 (file)
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3.  If not see
 #include <iconv.h>
 #endif
 
+static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
+
 /* Overwrite the given location/range within this text_info's rich_location.
    For use e.g. when implementing "+" in client format decoders.  */
 
@@ -555,8 +557,20 @@ pp_format (pretty_printer *pp, text_info *text)
          break;
 
        case 'c':
-         pp_character (pp, va_arg (*text->args_ptr, int));
-         break;
+         {
+           /* When quoting, print alphanumeric, punctuation, and the space
+              character unchanged, and all others in hexadecimal with the
+              "\x" prefix.  Otherwise print them all unchanged.  */
+           int chr = va_arg (*text->args_ptr, int);
+           if (ISPRINT (chr) || !quote)
+             pp_character (pp, chr);
+           else
+             {
+               const char str [2] = { chr, '\0' };
+               pp_quoted_string (pp, str, 1);
+             }
+           break;
+         }
 
        case 'd':
        case 'i':
@@ -577,7 +591,10 @@ pp_format (pretty_printer *pp, text_info *text)
          break;
 
        case 's':
-         pp_string (pp, va_arg (*text->args_ptr, const char *));
+         if (quote)
+           pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
+         else
+           pp_string (pp, va_arg (*text->args_ptr, const char *));
          break;
 
        case 'p':
@@ -939,6 +956,41 @@ pp_string (pretty_printer *pp, const char *str)
   pp_maybe_wrap_text (pp, str, str + strlen (str));
 }
 
+/* Append the leading N characters of STRING to the output area of
+   PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
+   Setting N = -1 is as if N were set to strlen (STRING).  The STRING
+   may be line-wrapped if in appropriate mode.  */
+static void
+pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
+{
+  gcc_checking_assert (str);
+
+  const char *last = str;
+  const char *ps;
+
+  /* Compute the length if not specified.  */
+  if (n == (size_t) -1)
+    n = strlen (str);
+
+  for (ps = str; n; ++ps, --n)
+    {
+      if (ISPRINT (*ps))
+         continue;
+
+      if (last < ps)
+       pp_maybe_wrap_text (pp, last, ps - 1);
+
+      /* Append the hexadecimal value of the character.  Allocate a buffer
+        that's large enough for a 32-bit char plus the hex prefix.  */
+      char buf [11];
+      int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
+      pp_maybe_wrap_text (pp, buf, buf + n);
+      last = ps + 1;
+    }
+
+  pp_maybe_wrap_text (pp, last, ps);
+}
+
 /* Maybe print out a whitespace if needed.  */
 
 void
index 56ff8bc9ff9eee4acd3d7dd40186b5afab9ed396..3b934a03a904a04b3b93d2f09e4dacb9773479be 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-09  Martin Sebor  <msebor@redhat.com>
+
+       PR c/77520
+       PR c/77521
+       * gcc.dg/pr77520.c: New test.
+       * gcc.dg/pr77521.c: New test.
+
 2016-09-09  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/77506
diff --git a/gcc/testsuite/gcc.dg/pr77520.c b/gcc/testsuite/gcc.dg/pr77520.c
new file mode 100644 (file)
index 0000000..b237639
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR c/77520 - wrong value for extended ASCII characters in -Wformat message
+   Verify that characters in the extended ASCII range are quoted and not
+   allowed to be printed raw.  */
+/* { dg-do compile } */
+/* { dg-options "-Wformat" } */
+
+void f (void)
+{
+  __builtin_printf ("%\x80");   /* { dg-warning "unknown conversion type character .\\\\x80. in format" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr77521.c b/gcc/testsuite/gcc.dg/pr77521.c
new file mode 100644 (file)
index 0000000..f6b1e3e
--- /dev/null
@@ -0,0 +1,8 @@
+/* PR c/77521 - %qc format directive should quote non-printable characters.
+   Verify that non-printable characters in assembly constraints are quoted
+   and not allowed to be printed raw.  */
+
+void f (int a, int b)
+{
+  __asm__ ("combine %2, %0" : "=r" (a) : "0" (a), "\n" (b));   /* { dg-error "invalid punctuation .\\\\x0a. in constraint" } */
+}