summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0288-2011-05-20-Richard-Guenther-rguenther-suse.de.patch
blob: ff2cb0664124de637b770fe672a8aaeb8046be7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
From 24f5b59f5c9418d39087b36dd0d275f71ac4dca5 Mon Sep 17 00:00:00 2001
From: rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri, 20 May 2011 15:08:56 +0000
Subject: [PATCH] 2011-05-20  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/49079
	* tree-dfa.c (get_ref_base_and_extent): Handle view-converting
	MEM_REFs correctly for the trailing array access detection.
	Special case constants the same way as decls for overall size
	constraining.

	* gcc.dg/torture/pr49079.c: New testcase.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@173955 138bc75d-0d04-0410-961f-82ee72b054a4

index 0efa0eb..dcb39c1 100644
new file mode 100644
index 0000000..1b53d3c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr49079.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct Ustr
+{
+  unsigned char data[1];
+};
+
+static unsigned int
+ustr_xi__embed_val_get(const unsigned char *data)
+{
+  return (unsigned int)data[0];
+}
+
+int __attribute__((noinline)) zero(void) { return 0; }
+
+static unsigned int
+ustr_len(const struct Ustr *s1)
+{
+  return ustr_xi__embed_val_get(s1->data + 1 + zero());
+}
+
+int
+main()
+{
+  if (ustr_len (((struct Ustr *) "\x01" "\x0002" "s2")) != 2)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 6490c5e..2dacd44 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -709,6 +709,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
   tree size_tree = NULL_TREE;
   HOST_WIDE_INT bit_offset = 0;
   bool seen_variable_array_ref = false;
+  tree base_type;
 
   /* First get the final access size from just the outermost expression.  */
   if (TREE_CODE (exp) == COMPONENT_REF)
@@ -739,6 +740,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
      and find the ultimate containing object.  */
   while (1)
     {
+      base_type = TREE_TYPE (exp);
+
       switch (TREE_CODE (exp))
 	{
 	case BIT_FIELD_REF:
@@ -926,9 +929,16 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
      the array.  The simplest way to conservatively deal with this
      is to punt in the case that offset + maxsize reaches the
      base type boundary.  This needs to include possible trailing padding
-     that is there for alignment purposes.
+     that is there for alignment purposes.  */
+
+  if (seen_variable_array_ref
+      && maxsize != -1
+      && (!host_integerp (TYPE_SIZE (base_type), 1)
+	  || (bit_offset + maxsize
+	      == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
+    maxsize = -1;
 
-     That is of course only true if the base object is not a decl.  */
+  /* In case of a decl or constant base object we can do better.  */
 
   if (DECL_P (exp))
     {
@@ -938,12 +948,14 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 	  && host_integerp (DECL_SIZE (exp), 1))
 	maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset;
     }
-  else if (seen_variable_array_ref
-	   && maxsize != -1
-	   && (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
-	       || (bit_offset + maxsize
-		   == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
-    maxsize = -1;
+  else if (CONSTANT_CLASS_P (exp))
+    {
+      /* If maxsize is unknown adjust it according to the size of the
+         base type constant.  */
+      if (maxsize == -1
+	  && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1))
+	maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - bit_offset;
+    }
 
   /* ???  Due to negative offsets in ARRAY_REF we can end up with
      negative bit_offset here.  We might want to store a zero offset
-- 
1.7.0.4