This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[4.0 patch] fix PRs 25120 and 20109
- From: "Kaveh R. Ghazi" <ghazi at caipclassic dot rutgers dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Cc: mark at codesourcery dot com
- Date: Sun, 27 Nov 2005 21:50:45 -0500 (EST)
- Subject: [4.0 patch] fix PRs 25120 and 20109
This is the 4.0 version of my patch to fix PRs 25120 and 20109.
The mainline/4.1 patch is here:
http://gcc.gnu.org/ml/gcc-patches/2005-11/msg01905.html
Bootstrapped and tested on i686-unknown-linux-gnu, no regressions.
Okay for 4.0?
Thanks,
--Kaveh
2005-11-27 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR middle-end/20109
PR middle-end/25120
* builtins.c (init_target_chars): New.
(expand_builtin_printf, expand_builtin_fprintf,
expand_builtin_sprintf, fold_builtin_sprintf): Check for matching
format strings using the target charset.
testsuite:
* gcc.dg/charset/builtin2.c: New test.
diff -rup orig/egcc-4.0-SVN20051126/gcc/builtins.c egcc-4.0-SVN20051126/gcc/builtins.c
--- orig/egcc-4.0-SVN20051126/gcc/builtins.c 2005-11-19 20:02:46.000000000 -0500
+++ egcc-4.0-SVN20051126/gcc/builtins.c 2005-11-27 19:21:35.000000000 -0500
@@ -187,7 +187,15 @@ static tree fold_builtin_strncat (tree);
static tree fold_builtin_strspn (tree);
static tree fold_builtin_strcspn (tree);
static tree fold_builtin_sprintf (tree, int);
+static bool init_target_chars (void);
+static unsigned HOST_WIDE_INT target_newline;
+static unsigned HOST_WIDE_INT target_percent;
+static unsigned HOST_WIDE_INT target_c;
+static unsigned HOST_WIDE_INT target_s;
+static char target_percent_c[3];
+static char target_percent_s[3];
+static char target_percent_s_newline[4];
/* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what.
@@ -4680,8 +4688,11 @@ expand_builtin_printf (tree exp, rtx tar
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format specifier was "%s\n", call __builtin_puts(arg). */
- if (strcmp (fmt_str, "%s\n") == 0)
+ if (strcmp (fmt_str, target_percent_s_newline) == 0)
{
if (! arglist
|| ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -4690,7 +4701,7 @@ expand_builtin_printf (tree exp, rtx tar
fn = fn_puts;
}
/* If the format specifier was "%c", call __builtin_putchar(arg). */
- else if (strcmp (fmt_str, "%c") == 0)
+ else if (strcmp (fmt_str, target_percent_c) == 0)
{
if (! arglist
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -4701,7 +4712,7 @@ expand_builtin_printf (tree exp, rtx tar
else
{
/* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, '%'))
+ if (strchr (fmt_str, target_percent))
return 0;
if (arglist)
@@ -4724,7 +4735,7 @@ expand_builtin_printf (tree exp, rtx tar
{
/* If the format specifier was "string\n", call puts("string"). */
size_t len = strlen (fmt_str);
- if (fmt_str[len - 1] == '\n')
+ if ((unsigned char)fmt_str[len - 1] == target_newline)
{
/* Create a NUL-terminated string that's one char shorter
than the original, stripping off the trailing '\n'. */
@@ -4791,8 +4802,11 @@ expand_builtin_fprintf (tree exp, rtx ta
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
- if (strcmp (fmt_str, "%s") == 0)
+ if (strcmp (fmt_str, target_percent_s) == 0)
{
if (! arglist
|| ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -4804,7 +4818,7 @@ expand_builtin_fprintf (tree exp, rtx ta
fn = fn_fputs;
}
/* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
- else if (strcmp (fmt_str, "%c") == 0)
+ else if (strcmp (fmt_str, target_percent_c) == 0)
{
if (! arglist
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -4818,7 +4832,7 @@ expand_builtin_fprintf (tree exp, rtx ta
else
{
/* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, '%'))
+ if (strchr (fmt_str, target_percent))
return 0;
if (arglist)
@@ -4880,8 +4894,11 @@ expand_builtin_sprintf (tree arglist, rt
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format doesn't contain % args or %%, use strcpy. */
- if (strchr (fmt_str, '%') == 0)
+ if (strchr (fmt_str, target_percent) == 0)
{
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
tree exp;
@@ -4896,7 +4913,7 @@ expand_builtin_sprintf (tree arglist, rt
return expand_expr (exp, target, mode, EXPAND_NORMAL);
}
/* If the format is "%s", use strcpy if the result isn't used. */
- else if (strcmp (fmt_str, "%s") == 0)
+ else if (strcmp (fmt_str, target_percent_s) == 0)
{
tree fn, arg, len;
fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -9110,8 +9127,11 @@ fold_builtin_sprintf (tree arglist, int
call = NULL_TREE;
retval = NULL_TREE;
+ if (!init_target_chars())
+ return 0;
+
/* If the format doesn't contain % args or %%, use strcpy. */
- if (strchr (fmt_str, '%') == NULL)
+ if (strchr (fmt_str, target_percent) == NULL)
{
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -9128,7 +9148,7 @@ fold_builtin_sprintf (tree arglist, int
}
/* If the format is "%s", use strcpy if the result isn't used. */
- else if (fmt_str && strcmp (fmt_str, "%s") == 0)
+ else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
{
tree fn, orig;
fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -9159,3 +9179,35 @@ fold_builtin_sprintf (tree arglist, int
else
return call;
}
+
+static bool
+init_target_chars (void)
+{
+ static bool init;
+ if (!init)
+ {
+ target_newline = lang_hooks.to_target_charset ('\n');
+ target_percent = lang_hooks.to_target_charset ('%');
+ target_c = lang_hooks.to_target_charset ('c');
+ target_s = lang_hooks.to_target_charset ('s');
+ if (target_newline == 0 || target_percent == 0 || target_c == 0
+ || target_s == 0)
+ return false;
+
+ target_percent_c[0] = target_percent;
+ target_percent_c[1] = target_c;
+ target_percent_c[2] = '\0';
+
+ target_percent_s[0] = target_percent;
+ target_percent_s[1] = target_s;
+ target_percent_s[2] = '\0';
+
+ target_percent_s_newline[0] = target_percent;
+ target_percent_s_newline[1] = target_s;
+ target_percent_s_newline[2] = target_newline;
+ target_percent_s_newline[3] = '\0';
+
+ init = true;
+ }
+ return true;
+}
diff -rup orig/egcc-4.0-SVN20051126/gcc/testsuite/gcc.dg/charset/builtin2.c egcc-4.0-SVN20051126/gcc/testsuite/gcc.dg/charset/builtin2.c
--- orig/egcc-4.0-SVN20051126/gcc/testsuite/gcc.dg/charset/builtin2.c 2005-11-27 21:29:15.000000000 -0500
+++ egcc-4.0-SVN20051126/gcc/testsuite/gcc.dg/charset/builtin2.c 2005-11-27 21:28:29.000000000 -0500
@@ -0,0 +1,30 @@
+/* Ensure that transformations of *printf are performed correctly
+ regardless of -fexec-charset. See PR 25120. */
+
+/* { dg-do compile } */
+/* { dg-require-iconv "IBM1047" } */
+/* { dg-options "-O2 -fexec-charset=IBM1047" } */
+/* { dg-final { scan-assembler-not "printf" } } */
+/* { dg-final { scan-assembler-not "fprintf" } } */
+/* { dg-final { scan-assembler-not "sprintf" } } */
+
+#include <stdio.h>
+
+void foo (char *dst, const char *src)
+{
+ printf ("\n");
+ printf ("hello world\n");
+ printf ("%c", '\n');
+ printf ("%s\n", "hello world");
+ printf ("%s\n", src);
+
+ fprintf (stdout, "\n");
+ fprintf (stdout, "hello world\n");
+ fprintf (stdout, "%s", "\n");
+ fprintf (stdout, "%s", "hello world\n");
+ fprintf (stdout, "%c", '\n');
+ fprintf (stdout, "%s", src);
+
+ sprintf (dst, "hello world\n");
+ sprintf (dst, "%s", src);
+}