This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix 22237
- From: Richard Henderson <rth at twiddle dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 6 Oct 2005 13:48:08 -0700
- Subject: fix 22237
We already had some code that attempted to handle this case, but it
didn't operate properly unless the lhs of the modify_expr is a bare
decl. Fixed thus.
Tested on powerpc-linux.
r~
* tree-inline.c (declare_return_variable): Handle modify_dest not
being a DECL.
Index: gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
===================================================================
RCS file: gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
diff -N gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c 6 Oct 2005 20:44:07 -0000
@@ -0,0 +1,27 @@
+extern void abort (void);
+
+void *
+memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+ srcp = src;
+ dstp = dst;
+
+ if (dst < src)
+ {
+ if (dst + n > src)
+ abort ();
+ }
+ else
+ {
+ if (src + n > dst)
+ abort ();
+ }
+
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
Index: gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
===================================================================
RCS file: gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
diff -N gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c 6 Oct 2005 20:44:07 -0000
@@ -0,0 +1,44 @@
+extern void abort (void);
+extern void exit (int);
+struct s { unsigned char a[256]; };
+union u { struct { struct s b; int c; } d; struct { int c; struct s b; } e; };
+static union u v;
+static union u v0;
+static struct s *p = &v.d.b;
+static struct s *q = &v.e.b;
+
+static inline struct s rp (void) { return *p; }
+static inline struct s rq (void) { return *q; }
+static void pq (void) { *p = rq(); }
+static void qp (void) { *q = rp(); }
+
+static void
+init (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ sp->a[i] = i;
+}
+
+static void
+check (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (sp->a[i] != i)
+ abort ();
+}
+
+void
+main_test (void)
+{
+ v = v0;
+ init (p);
+ qp ();
+ check (q);
+ v = v0;
+ init (q);
+ pq ();
+ check (p);
+ exit (0);
+}
Index: gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.210
diff -u -p -r1.210 tree-inline.c
--- gcc/tree-inline.c 1 Aug 2005 15:25:28 -0000 1.210
+++ gcc/tree-inline.c 6 Oct 2005 20:44:08 -0000
@@ -1260,10 +1260,21 @@ declare_return_variable (inline_data *id
/* If the callee cannot possibly modify MODIFY_DEST, then we can
reuse it as the result of the call directly. Don't do this if
it would promote MODIFY_DEST to addressable. */
- else if (!TREE_STATIC (modify_dest)
- && !TREE_ADDRESSABLE (modify_dest)
- && !TREE_ADDRESSABLE (result))
- use_it = true;
+ else if (TREE_ADDRESSABLE (result))
+ use_it = false;
+ else
+ {
+ tree base_m = get_base_address (modify_dest);
+
+ /* If the base isn't a decl, then it's a pointer, and we don't
+ know where that's going to go. */
+ if (!DECL_P (base_m))
+ use_it = false;
+ else if (is_global_var (base_m))
+ use_it = false;
+ else if (!TREE_ADDRESSABLE (base_m))
+ use_it = true;
+ }
if (use_it)
{