PR tree-opt/22237
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Oct 2005 20:46:53 +0000 (20:46 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Oct 2005 20:46:53 +0000 (20:46 +0000)
        * tree-inline.c (declare_return_variable): Handle modify_dest not
        being a DECL.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105057 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c [new file with mode: 0644]
gcc/tree-inline.c

index f7a9c38..79124ff 100644 (file)
@@ -1,3 +1,9 @@
+2005-10-06  Richard Henderson  <rth@redhat.com>
+
+       PR tree-opt/22237
+       * tree-inline.c (declare_return_variable): Handle modify_dest not
+       being a DECL.
+
 2005-10-06  Daniel Berlin  <dberlin@dberlin.org>
        
        Fix PR tree-optimization/22488
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
new file mode 100644 (file)
index 0000000..4403235
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
new file mode 100644 (file)
index 0000000..957a47c
--- /dev/null
@@ -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 afec40d..f22785c 100644 (file)
@@ -1260,10 +1260,21 @@ declare_return_variable (inline_data *id, tree return_slot_addr,
       /* 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)
        {