re PR tree-optimization/78965 (Invalid -fprintf-return-value optimization)
authorJakub Jelinek <jakub@redhat.com>
Tue, 3 Jan 2017 07:23:11 +0000 (08:23 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 3 Jan 2017 07:23:11 +0000 (08:23 +0100)
PR tree-optimization/78965
* gimple-ssa-sprintf.c (pass_sprintf_length::compute_format_length):
Change first argument from const call_info & to call_info &.  For %n
set info.nowrite to false.

* gcc.dg/pr78965.c: New test.

From-SVN: r244014

gcc/ChangeLog
gcc/gimple-ssa-sprintf.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr78965.c [new file with mode: 0644]

index 7e1b2df89183b7ffd30c8a5a407b2d7184251aaf..af5185a7e652f7a56b66a6e314f90b56dec0c046 100644 (file)
@@ -1,5 +1,10 @@
 2017-01-03  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/78965
+       * gimple-ssa-sprintf.c (pass_sprintf_length::compute_format_length):
+       Change first argument from const call_info & to call_info &.  For %n
+       set info.nowrite to false.
+
        PR middle-end/78901
        * gimple-ssa-sprintf.c (try_substitute_return_value): Don't change
        possibly throwing calls.
index ecd2267ae93fbe1ad92847eabf81584301d3b955..5bf0215cf1ec1cfd38803763c885c21095b8e4f8 100644 (file)
@@ -131,7 +131,7 @@ public:
   void handle_gimple_call (gimple_stmt_iterator*);
 
   struct call_info;
-  bool compute_format_length (const call_info &, format_result *);
+  bool compute_format_length (call_info &, format_result *);
 };
 
 bool
@@ -710,7 +710,8 @@ struct pass_sprintf_length::call_info
 
   /* True for bounded functions like snprintf that specify a zero-size
      buffer as a request to compute the size of output without actually
-     writing any.  */
+     writing any.  NOWRITE is cleared in response to the %n directive
+     which has side-effects similar to writing output.  */
   bool nowrite;
 };
 
@@ -2357,7 +2358,7 @@ add_bytes (const pass_sprintf_length::call_info &info,
    that caused the processing to be terminated early).  */
 
 bool
-pass_sprintf_length::compute_format_length (const call_info &info,
+pass_sprintf_length::compute_format_length (call_info &info,
                                            format_result *res)
 {
   /* The variadic argument counter.  */
@@ -2624,6 +2625,9 @@ pass_sprintf_length::compute_format_length (const call_info &info,
          return false;
 
        case 'n':
+         /* %n has side-effects even when nothing is actually printed to
+            any buffer.  */
+         info.nowrite = false;
          break;
 
        case 'c':
index bdaa2fe5d6874fcfa4f3d631644911973b069773..abed28d091847b0f14e2da63d9aeb534b81abea0 100644 (file)
@@ -1,5 +1,8 @@
 2017-01-03  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/78965
+       * gcc.dg/pr78965.c: New test.
+
        PR middle-end/78901
        * g++.dg/opt/pr78901.C: New test.
 
diff --git a/gcc/testsuite/gcc.dg/pr78965.c b/gcc/testsuite/gcc.dg/pr78965.c
new file mode 100644 (file)
index 0000000..9ae1ad4
--- /dev/null
@@ -0,0 +1,14 @@
+/* PR tree-optimization/78965 */
+/* { dg-do run { target c99_runtime } } */
+/* { dg-options "-O2" } */
+/* { dg-add-options c99_runtime } */
+
+int
+main ()
+{
+  int a = 5, b = 6;
+  int c = __builtin_snprintf (0, 0, "a%nb%nc", &a, &b);
+  if (a + b + c != 6)
+    __builtin_abort ();
+  return 0;
+}