aboutsummaryrefslogtreecommitdiff
blob: 1b66f8c785533a708e40d66e4df788d384fd9d17 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
http://bugs.gentoo.org/182728
http://gcc.gnu.org/PR30252

2007-06-19  Richard Guenther  <rguenther@suse.de>
	Michael Matz  <matz@suse.de>

	PR tree-optimization/30252
	* tree-ssa-structalias.c (solution_set_add): Make sure to
	preserve all relevant vars.
	(handle_ptr_arith): Make sure to only handle positive
	offsets.
	(push_fields_onto_fieldstack): Create fields for empty
	bases.

Index: gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C
===================================================================
--- gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C	(revision 0)
+++ gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C	(revision 125844)
@@ -0,0 +1,226 @@
+/* { dg-do run } */
+/* { dg-options "-O -fstrict-aliasing" } */
+
+extern "C" void abort (void);
+namespace sigc {
+  template <class T_type>
+  struct type_trait
+  {
+    typedef T_type& pass;
+    typedef const T_type& take;
+    typedef T_type* pointer;
+  };
+  template <class T_base, class T_derived>
+  struct is_base_and_derived
+  {
+    struct big {
+      char memory[64];
+    };
+    static big is_base_class_(...);
+    static char is_base_class_(typename type_trait<T_base>::pointer);
+    static const bool value =
+    sizeof(is_base_class_(reinterpret_cast<typename type_trait<T_derived>::pointer>(0))) ==
+    sizeof(char);
+  };
+  struct nil;
+  struct functor_base {};
+  template <class T_functor, bool I_derives_functor_base=is_base_and_derived<functor_base,T_functor>::value>
+  struct functor_trait
+  {
+  };
+  template <class T_functor>
+  struct functor_trait<T_functor,true>
+  {
+    typedef typename T_functor::result_type result_type;
+    typedef T_functor functor_type;
+  };
+  template <class T_arg1, class T_return>
+  class pointer_functor1 : public functor_base
+  {
+    typedef T_return (*function_type)(T_arg1);
+    function_type func_ptr_;
+  public:
+    typedef T_return result_type;
+    explicit pointer_functor1(function_type _A_func): func_ptr_(_A_func) {}
+    T_return operator()(typename type_trait<T_arg1>::take _A_a1) const
+    { return func_ptr_(_A_a1); }
+  };
+  template <class T_arg1, class T_return>
+  inline pointer_functor1<T_arg1, T_return>
+  ptr_fun1(T_return (*_A_func)(T_arg1))
+  { return pointer_functor1<T_arg1, T_return>(_A_func); }
+  struct adaptor_base : public functor_base {};
+  template <class T_functor,
+    class T_arg1=void,
+    bool I_derives_adaptor_base=is_base_and_derived<adaptor_base,T_functor>::value>
+  struct deduce_result_type
+  { typedef typename functor_trait<T_functor>::result_type type; };
+  template <class T_functor>
+  struct adaptor_functor : public adaptor_base
+  {
+    template <class T_arg1=void>
+    struct deduce_result_type
+    { typedef typename sigc::deduce_result_type<T_functor, T_arg1>::type type; };
+    typedef typename functor_trait<T_functor>::result_type result_type;
+    result_type
+    operator()() const;
+    template <class T_arg1>
+    typename deduce_result_type<T_arg1>::type
+    operator()(T_arg1 _A_arg1) const
+    { return functor_(_A_arg1); }
+    explicit adaptor_functor(const T_functor& _A_functor)
+      : functor_(_A_functor)
+    {}
+    mutable T_functor functor_;
+  };
+  template <class T_functor>
+  typename adaptor_functor<T_functor>::result_type
+  adaptor_functor<T_functor>::operator()() const
+  { return functor_(); }
+  template <class T_functor, bool I_isadaptor = is_base_and_derived<adaptor_base, T_functor>::value> struct adaptor_trait;
+  template <class T_functor>
+  struct adaptor_trait<T_functor, true>
+  {
+    typedef T_functor adaptor_type;
+  };
+  template <class T_functor>
+  struct adaptor_trait<T_functor, false>
+  {
+    typedef typename functor_trait<T_functor>::functor_type functor_type;
+    typedef adaptor_functor<functor_type> adaptor_type;
+  };
+  template <class T_functor>
+  struct adapts : public adaptor_base
+  {
+    typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
+    explicit adapts(const T_functor& _A_functor)
+      : functor_(_A_functor)
+    {}
+    mutable adaptor_type functor_;
+  };
+  template <class T_type>
+  struct reference_wrapper
+  {
+  };
+  template <class T_type>
+  struct unwrap_reference
+  {
+    typedef T_type type;
+  };
+  template <class T_type>
+  class bound_argument
+  {
+  public:
+    bound_argument(const T_type& _A_argument)
+      : visited_(_A_argument)
+    {}
+    inline T_type& invoke()
+    { return visited_; }
+    T_type visited_;
+  };
+  template <class T_wrapped>
+  class bound_argument< reference_wrapper<T_wrapped> >
+  {
+  };
+  template <int I_location, class T_functor, class T_type1=nil>
+  struct bind_functor;
+  template <class T_functor, class T_type1>
+  struct bind_functor<-1, T_functor, T_type1> : public adapts<T_functor>
+  {
+    typedef typename adapts<T_functor>::adaptor_type adaptor_type;
+    typedef typename adaptor_type::result_type result_type;
+    result_type
+    operator()()
+    {
+      return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_type1>::type>::pass> (bound1_.invoke());
+    }
+    bind_functor(typename type_trait<T_functor>::take _A_func, typename type_trait<T_type1>::take _A_bound1)
+      : adapts<T_functor>(_A_func), bound1_(_A_bound1)
+    {}
+    bound_argument<T_type1> bound1_;
+  };
+  template <class T_type1, class T_functor>
+  inline bind_functor<-1, T_functor,
+		      T_type1>
+  bind(const T_functor& _A_func, T_type1 _A_b1)
+  { return bind_functor<-1, T_functor,
+      T_type1>
+      (_A_func, _A_b1);
+  }
+  namespace internal {
+    struct slot_rep;
+    typedef void* (*hook)(slot_rep *);
+    struct slot_rep
+    {
+      hook call_;
+    };
+  }
+  class slot_base : public functor_base
+  {
+  public:
+    typedef internal::slot_rep rep_type;
+    explicit slot_base(rep_type* rep)
+      : rep_(rep)
+    {
+    }
+    mutable rep_type *rep_;
+  };
+  namespace internal {
+    template <class T_functor>
+    struct typed_slot_rep : public slot_rep
+    {
+      typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
+      adaptor_type functor_;
+      inline typed_slot_rep(const T_functor& functor)
+	: functor_(functor)
+      {
+      }
+    };
+    template<class T_functor>
+    struct slot_call0
+    {
+      static void *call_it(slot_rep* rep)
+      {
+	typedef typed_slot_rep<T_functor> typed_slot;
+	typed_slot *typed_rep = static_cast<typed_slot*>(rep);
+	return (typed_rep->functor_)();
+      }
+      static hook address()
+      {
+	return &call_it;
+      }
+    };
+  }
+
+  class slot0 : public slot_base
+  {
+  public:
+    typedef void * (*call_type)(rep_type*);
+    inline void *operator()() const
+    {
+      return slot_base::rep_->call_ (slot_base::rep_);
+    }
+    template <class T_functor>
+    slot0(const T_functor& _A_func)
+      : slot_base(new internal::typed_slot_rep<T_functor>(_A_func))
+    {
+      slot_base::rep_->call_ = internal::slot_call0<T_functor>::address();
+    }
+  };
+}
+struct A
+{
+  static void *foo (void *p) { return p; }
+  typedef sigc::slot0 C;
+  C bar();
+};
+A::C A::bar ()
+{
+  return sigc::bind (sigc::ptr_fun1 (&A::foo), (void*)0);
+}
+int main (void)
+{
+  A a;
+  if (a.bar ()() != 0)
+    abort ();
+}
Index: gcc-4_2-branch/gcc/tree-ssa-structalias.c
===================================================================
--- gcc-4_2-branch/gcc/tree-ssa-structalias.c	(revision 125843)
+++ gcc-4_2-branch/gcc/tree-ssa-structalias.c	(revision 125844)
@@ -708,6 +708,26 @@ solution_set_add (bitmap set, unsigned H
   bitmap result = BITMAP_ALLOC (&iteration_obstack);
   unsigned int i;
   bitmap_iterator bi;
+  unsigned HOST_WIDE_INT min = -1, max = 0;
+
+  /* Compute set of vars we can reach from set + offset.  */
+
+  EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
+    {
+      if (get_varinfo (i)->is_artificial_var
+	  || get_varinfo (i)->has_union
+	  || get_varinfo (i)->is_unknown_size_var)
+	continue;
+
+      if (get_varinfo (i)->offset + offset < min)
+	min = get_varinfo (i)->offset + offset;
+      if (get_varinfo (i)->offset + get_varinfo (i)->size + offset > max)
+	{
+	  max = get_varinfo (i)->offset + get_varinfo (i)->size + offset;
+	  if (max > get_varinfo (i)->fullsize)
+	    max = get_varinfo (i)->fullsize;
+	}
+    }
 
   EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
     {
@@ -715,13 +735,10 @@ solution_set_add (bitmap set, unsigned H
 	 less than end.  Otherwise, it is globbed to a single
 	 variable.  */
 
-      if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize)
+      if (get_varinfo (i)->offset + get_varinfo (i)->size - 1 >= min
+	  && get_varinfo (i)->offset < max)
 	{
-	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset;
-	  varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
-	  if (!v)
-	    continue;
-	  bitmap_set_bit (result, v->id);
+	  bitmap_set_bit (result, i);
 	}
       else if (get_varinfo (i)->is_artificial_var
 	       || get_varinfo (i)->has_union
@@ -3258,7 +3275,7 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc
   unsigned int i = 0;
   unsigned int j = 0;
   VEC (ce_s, heap) *temp = NULL;
-  unsigned int rhsoffset = 0;
+  unsigned HOST_WIDE_INT rhsoffset = 0;
 
   if (TREE_CODE (expr) != PLUS_EXPR
       && TREE_CODE (expr) != MINUS_EXPR)
@@ -3269,9 +3286,12 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc
 
   get_constraint_for (op0, &temp);
   if (POINTER_TYPE_P (TREE_TYPE (op0))
-      && TREE_CODE (op1) == INTEGER_CST
+      && host_integerp (op1, 1)
       && TREE_CODE (expr) == PLUS_EXPR)
     {
+      if ((TREE_INT_CST_LOW (op1) * BITS_PER_UNIT) / BITS_PER_UNIT
+	  != TREE_INT_CST_LOW (op1))
+	return false;
       rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
     }
   else
@@ -3661,6 +3681,7 @@ push_fields_onto_fieldstack (tree type, 
 {
   tree field;
   int count = 0;
+  unsigned HOST_WIDE_INT minoffset = -1;
 
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
@@ -3773,8 +3794,25 @@ push_fields_onto_fieldstack (tree type, 
 	  }
 	else
 	  count += pushed;
+
+	if (bitpos_of_field (field) < minoffset)
+	  minoffset = bitpos_of_field (field);
       }
 
+  /* We need to create a fake subvar for empty bases.  But _only_ for non-empty
+     classes.  */
+  if (minoffset != 0 && count != 0)
+    {
+      fieldoff_s *pair;
+
+      pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+      pair->type = void_type_node;
+      pair->size = build_int_cst (size_type_node, minoffset);
+      pair->decl = NULL;
+      pair->offset = offset;
+      count++;
+    }
+
   return count;
 }