]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/46534 (ICE optimizing printf ("...>10MBstring\n") into puts)
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Dec 2010 18:56:56 +0000 (19:56 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 7 Dec 2010 18:56:56 +0000 (19:56 +0100)
PR middle-end/46534
* builtins.c (expand_builtin_printf): Don't copy and modify string
before build_string_literal, instead modify what
build_string_literal returned.

Backport from mainline
2010-11-18  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/46534
* builtins.c (fold_builtin_printf): Don't copy and modify string
before build_string_literal, instead modify what
build_string_literal returned.

* gcc.c-torture/compile/pr46534.c: New test.

From-SVN: r167558

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr46534.c [new file with mode: 0644]

index 3163042f937370b1a9a3fa458ba0e1e992a13e69..2a9a61fa0cf36cf577ed09d3a64d4c438ec05a1d 100644 (file)
@@ -1,3 +1,18 @@
+2010-12-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/46534
+       * builtins.c (expand_builtin_printf): Don't copy and modify string
+       before build_string_literal, instead modify what
+       build_string_literal returned.
+
+       Backport from mainline
+       2010-11-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/46534
+       * builtins.c (fold_builtin_printf): Don't copy and modify string
+       before build_string_literal, instead modify what
+       build_string_literal returned.
+
 2010-12-05  Richard Guenther  <rguenther@suse.de>
            Ira Rosen  <irar@il.ibm.com>
 
index 5a84ed4d163ec166fecc0b6e20c8a472ec9821a6..34a7d24f44b224702f203f45b33ad66d1d069466 100644 (file)
@@ -5452,14 +5452,30 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
        {
          /* If the format specifier was "string\n", call puts("string").  */
          size_t len = strlen (fmt_str);
-         if ((unsigned char)fmt_str[len - 1] == target_newline)
+         if ((unsigned char)fmt_str[len - 1] == target_newline
+             && (size_t) (int) len == len
+             && (int) len > 0)
            {
+             char *newstr;
+             tree offset_node, string_cst;
+
              /* Create a NUL-terminated string that's one char shorter
                 than the original, stripping off the trailing '\n'.  */
-             char *newstr = XALLOCAVEC (char, len);
-             memcpy (newstr, fmt_str, len - 1);
-             newstr[len - 1] = 0;
-             arg = build_string_literal (len, newstr);
+             arg = build_string_literal (len, fmt_str);
+             string_cst = string_constant (arg, &offset_node);
+#ifdef ENABLE_CHECKING
+             gcc_assert (string_cst
+                         && (TREE_STRING_LENGTH (string_cst)
+                             == (int) len)
+                         && integer_zerop (offset_node)
+                         && (unsigned char)
+                             TREE_STRING_POINTER (string_cst)[len - 1]
+                             == target_newline);
+#endif
+             /* build_string_literal creates a new STRING_CST,
+                modify it in place to avoid double copying.  */
+             newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
+             newstr[len - 1] = '\0';
              if (fn_puts)
                fn = build_call_expr (fn_puts, 1, arg);
            }
@@ -12844,15 +12860,30 @@ fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
        {
          /* If the string was "string\n", call puts("string").  */
          size_t len = strlen (str);
-         if ((unsigned char)str[len - 1] == target_newline)
+         if ((unsigned char)str[len - 1] == target_newline
+             && (size_t) (int) len == len
+             && (int) len > 0)
            {
+             char *newstr;
+             tree offset_node, string_cst;
+
              /* Create a NUL-terminated string that's one char shorter
                 than the original, stripping off the trailing '\n'.  */
-             char *newstr = XALLOCAVEC (char, len);
-             memcpy (newstr, str, len - 1);
-             newstr[len - 1] = 0;
-
-             newarg = build_string_literal (len, newstr);
+             newarg = build_string_literal (len, str);
+             string_cst = string_constant (newarg, &offset_node);
+#ifdef ENABLE_CHECKING
+             gcc_assert (string_cst
+                         && (TREE_STRING_LENGTH (string_cst)
+                             == (int) len)
+                         && integer_zerop (offset_node)
+                         && (unsigned char)
+                             TREE_STRING_POINTER (string_cst)[len - 1]
+                             == target_newline);
+#endif
+             /* build_string_literal creates a new STRING_CST,
+                modify it in place to avoid double copying.  */
+             newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
+             newstr[len - 1] = '\0';
              if (fn_puts)
                call = build_call_expr (fn_puts, 1, newarg);
            }
index d4d6d82075a1de1440041f65d3a191a9a5602387..80b9b208f2bf34ac44e35eae8498a73aa35845d9 100644 (file)
@@ -1,3 +1,10 @@
+2010-12-07  Jakub Jelinek  <jakub@redhat.com>
+
+       Backport from mainline
+       2010-11-18  Jakub Jelinek  <jakub@redhat.com>
+       PR middle-end/46534
+       * gcc.c-torture/compile/pr46534.c: New test.
+
 2010-12-06  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * ada/acats/run_acats (which): Assign output to temporary
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr46534.c b/gcc/testsuite/gcc.c-torture/compile/pr46534.c
new file mode 100644 (file)
index 0000000..3023ad9
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR middle-end/46534 */
+
+extern int printf (const char *, ...);
+
+#define S1 "                    "
+#define S2 S1 S1 S1 S1 S1 S1 S1 S1 S1 S1
+#define S3 S2 S2 S2 S2 S2 S2 S2 S2 S2 S2
+#define S4 S3 S3 S3 S3 S3 S3 S3 S3 S3 S3
+#define S5 S4 S4 S4 S4 S4 S4 S4 S4 S4 S4
+#define S6 S5 S5 S5 S5 S5 S5 S5 S5 S5 S5
+#define S7 S6 S6 S6 S6 S6 S6 S6 S6 S6 S6
+
+void
+foo (void)
+{
+  printf (S7 "\n");
+}