File: | build/gcc/value-range.h |
Warning: | line 689, column 10 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Support routines for value ranges. | |||
2 | Copyright (C) 2019-2023 Free Software Foundation, Inc. | |||
3 | Major hacks by Aldy Hernandez <aldyh@redhat.com> and | |||
4 | Andrew MacLeod <amacleod@redhat.com>. | |||
5 | ||||
6 | This file is part of GCC. | |||
7 | ||||
8 | GCC is free software; you can redistribute it and/or modify | |||
9 | it under the terms of the GNU General Public License as published by | |||
10 | the Free Software Foundation; either version 3, or (at your option) | |||
11 | any later version. | |||
12 | ||||
13 | GCC is distributed in the hope that it will be useful, | |||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
16 | GNU General Public License for more details. | |||
17 | ||||
18 | You should have received a copy of the GNU General Public License | |||
19 | along with GCC; see the file COPYING3. If not see | |||
20 | <http://www.gnu.org/licenses/>. */ | |||
21 | ||||
22 | #include "config.h" | |||
23 | #include "system.h" | |||
24 | #include "coretypes.h" | |||
25 | #include "backend.h" | |||
26 | #include "tree.h" | |||
27 | #include "gimple.h" | |||
28 | #include "ssa.h" | |||
29 | #include "tree-pretty-print.h" | |||
30 | #include "value-range-pretty-print.h" | |||
31 | #include "fold-const.h" | |||
32 | #include "gimple-range.h" | |||
33 | ||||
34 | void | |||
35 | irange::accept (const vrange_visitor &v) const | |||
36 | { | |||
37 | v.visit (*this); | |||
38 | } | |||
39 | ||||
40 | void | |||
41 | unsupported_range::accept (const vrange_visitor &v) const | |||
42 | { | |||
43 | v.visit (*this); | |||
44 | } | |||
45 | ||||
46 | // Convenience function only available for integers and pointers. | |||
47 | ||||
48 | wide_int | |||
49 | Value_Range::lower_bound () const | |||
50 | { | |||
51 | if (is_a <irange> (*m_vrange)) | |||
52 | return as_a <irange> (*m_vrange).lower_bound (); | |||
53 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 53, __FUNCTION__)); | |||
54 | } | |||
55 | ||||
56 | // Convenience function only available for integers and pointers. | |||
57 | ||||
58 | wide_int | |||
59 | Value_Range::upper_bound () const | |||
60 | { | |||
61 | if (is_a <irange> (*m_vrange)) | |||
62 | return as_a <irange> (*m_vrange).upper_bound (); | |||
63 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 63, __FUNCTION__)); | |||
64 | } | |||
65 | ||||
66 | void | |||
67 | Value_Range::dump (FILE *out) const | |||
68 | { | |||
69 | if (m_vrange) | |||
70 | m_vrange->dump (out); | |||
71 | else | |||
72 | fprintf (out, "NULL"); | |||
73 | } | |||
74 | ||||
75 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
76 | debug (const Value_Range &r) | |||
77 | { | |||
78 | r.dump (stderrstderr); | |||
79 | fprintf (stderrstderr, "\n"); | |||
80 | } | |||
81 | ||||
82 | // Default vrange definitions. | |||
83 | ||||
84 | bool | |||
85 | vrange::contains_p (tree) const | |||
86 | { | |||
87 | return varying_p (); | |||
88 | } | |||
89 | ||||
90 | bool | |||
91 | vrange::singleton_p (tree *) const | |||
92 | { | |||
93 | return false; | |||
94 | } | |||
95 | ||||
96 | void | |||
97 | vrange::set (tree min, tree, value_range_kind) | |||
98 | { | |||
99 | set_varying (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 99, __FUNCTION__))->typed.type)); | |||
100 | } | |||
101 | ||||
102 | tree | |||
103 | vrange::type () const | |||
104 | { | |||
105 | return void_type_nodeglobal_trees[TI_VOID_TYPE]; | |||
106 | } | |||
107 | ||||
108 | bool | |||
109 | vrange::supports_type_p (const_tree) const | |||
110 | { | |||
111 | return false; | |||
112 | } | |||
113 | ||||
114 | void | |||
115 | vrange::set_undefined () | |||
116 | { | |||
117 | m_kind = VR_UNDEFINED; | |||
118 | } | |||
119 | ||||
120 | void | |||
121 | vrange::set_varying (tree) | |||
122 | { | |||
123 | m_kind = VR_VARYING; | |||
124 | } | |||
125 | ||||
126 | bool | |||
127 | vrange::union_ (const vrange &r) | |||
128 | { | |||
129 | if (r.undefined_p () || varying_p ()) | |||
130 | return false; | |||
131 | if (undefined_p () || r.varying_p ()) | |||
132 | { | |||
133 | operator= (r); | |||
134 | return true; | |||
135 | } | |||
136 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 136, __FUNCTION__)); | |||
137 | return false; | |||
138 | } | |||
139 | ||||
140 | bool | |||
141 | vrange::intersect (const vrange &r) | |||
142 | { | |||
143 | if (undefined_p () || r.varying_p ()) | |||
144 | return false; | |||
145 | if (r.undefined_p ()) | |||
146 | { | |||
147 | set_undefined (); | |||
148 | return true; | |||
149 | } | |||
150 | if (varying_p ()) | |||
151 | { | |||
152 | operator= (r); | |||
153 | return true; | |||
154 | } | |||
155 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 155, __FUNCTION__)); | |||
156 | return false; | |||
157 | } | |||
158 | ||||
159 | bool | |||
160 | vrange::zero_p () const | |||
161 | { | |||
162 | return false; | |||
163 | } | |||
164 | ||||
165 | bool | |||
166 | vrange::nonzero_p () const | |||
167 | { | |||
168 | return false; | |||
169 | } | |||
170 | ||||
171 | void | |||
172 | vrange::set_nonzero (tree type) | |||
173 | { | |||
174 | set_varying (type); | |||
175 | } | |||
176 | ||||
177 | void | |||
178 | vrange::set_zero (tree type) | |||
179 | { | |||
180 | set_varying (type); | |||
181 | } | |||
182 | ||||
183 | void | |||
184 | vrange::set_nonnegative (tree type) | |||
185 | { | |||
186 | set_varying (type); | |||
187 | } | |||
188 | ||||
189 | bool | |||
190 | vrange::fits_p (const vrange &) const | |||
191 | { | |||
192 | return true; | |||
193 | } | |||
194 | ||||
195 | // Assignment operator for generic ranges. Copying incompatible types | |||
196 | // is not allowed. | |||
197 | ||||
198 | vrange & | |||
199 | vrange::operator= (const vrange &src) | |||
200 | { | |||
201 | if (is_a <irange> (src)) | |||
202 | as_a <irange> (*this) = as_a <irange> (src); | |||
203 | else if (is_a <frange> (src)) | |||
204 | as_a <frange> (*this) = as_a <frange> (src); | |||
205 | else | |||
206 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 206, __FUNCTION__)); | |||
207 | return *this; | |||
208 | } | |||
209 | ||||
210 | // Equality operator for generic ranges. | |||
211 | ||||
212 | bool | |||
213 | vrange::operator== (const vrange &src) const | |||
214 | { | |||
215 | if (is_a <irange> (src)) | |||
216 | return as_a <irange> (*this) == as_a <irange> (src); | |||
217 | if (is_a <frange> (src)) | |||
218 | return as_a <frange> (*this) == as_a <frange> (src); | |||
219 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 219, __FUNCTION__)); | |||
220 | } | |||
221 | ||||
222 | // Wrapper for vrange_printer to dump a range to a file. | |||
223 | ||||
224 | void | |||
225 | vrange::dump (FILE *file) const | |||
226 | { | |||
227 | pretty_printer buffer; | |||
228 | pp_needs_newline (&buffer)(&buffer)->need_newline = true; | |||
229 | buffer.buffer->stream = file; | |||
230 | vrange_printer vrange_pp (&buffer); | |||
231 | this->accept (vrange_pp); | |||
232 | pp_flush (&buffer); | |||
233 | } | |||
234 | ||||
235 | bool | |||
236 | irange::supports_type_p (const_tree type) const | |||
237 | { | |||
238 | return supports_p (type); | |||
239 | } | |||
240 | ||||
241 | // Return TRUE if R fits in THIS. | |||
242 | ||||
243 | bool | |||
244 | irange::fits_p (const vrange &r) const | |||
245 | { | |||
246 | return m_max_ranges >= as_a <irange> (r).num_pairs (); | |||
247 | } | |||
248 | ||||
249 | void | |||
250 | irange::set_nonnegative (tree type) | |||
251 | { | |||
252 | set (build_int_cst (type, 0), TYPE_MAX_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 252, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval )); | |||
253 | } | |||
254 | ||||
255 | void | |||
256 | frange::accept (const vrange_visitor &v) const | |||
257 | { | |||
258 | v.visit (*this); | |||
259 | } | |||
260 | ||||
261 | // Flush denormal endpoints to the appropriate 0.0. | |||
262 | ||||
263 | void | |||
264 | frange::flush_denormals_to_zero () | |||
265 | { | |||
266 | if (undefined_p () || known_isnan ()) | |||
267 | return; | |||
268 | ||||
269 | machine_mode mode = TYPE_MODE (type ())((((enum tree_code) ((tree_class_check ((type ()), (tcc_type) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 269, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type ()) : (type ())->type_common.mode); | |||
270 | // Flush [x, -DENORMAL] to [x, -0.0]. | |||
271 | if (real_isdenormal (&m_max, mode) && real_isneg (&m_max)) | |||
272 | { | |||
273 | m_max = dconst0; | |||
274 | if (HONOR_SIGNED_ZEROS (m_type)) | |||
275 | m_max.sign = 1; | |||
276 | } | |||
277 | // Flush [+DENORMAL, x] to [+0.0, x]. | |||
278 | if (real_isdenormal (&m_min, mode) && !real_isneg (&m_min)) | |||
279 | m_min = dconst0; | |||
280 | } | |||
281 | ||||
282 | // Setter for franges. | |||
283 | ||||
284 | void | |||
285 | frange::set (tree type, | |||
286 | const REAL_VALUE_TYPEstruct real_value &min, const REAL_VALUE_TYPEstruct real_value &max, | |||
287 | const nan_state &nan, value_range_kind kind) | |||
288 | { | |||
289 | switch (kind) | |||
290 | { | |||
291 | case VR_UNDEFINED: | |||
292 | set_undefined (); | |||
293 | return; | |||
294 | case VR_VARYING: | |||
295 | case VR_ANTI_RANGE: | |||
296 | set_varying (type); | |||
297 | return; | |||
298 | case VR_RANGE: | |||
299 | break; | |||
300 | default: | |||
301 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 301, __FUNCTION__)); | |||
302 | } | |||
303 | ||||
304 | // Handle NANs. | |||
305 | if (real_isnan (&min) || real_isnan (&max)) | |||
306 | { | |||
307 | gcc_checking_assert (real_identical (&min, &max))((void)(!(real_identical (&min, &max)) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 307, __FUNCTION__), 0 : 0)); | |||
308 | bool sign = real_isneg (&min); | |||
309 | set_nan (type, sign); | |||
310 | return; | |||
311 | } | |||
312 | ||||
313 | m_kind = kind; | |||
314 | m_type = type; | |||
315 | m_min = min; | |||
316 | m_max = max; | |||
317 | if (HONOR_NANS (m_type)) | |||
318 | { | |||
319 | m_pos_nan = nan.pos_p (); | |||
320 | m_neg_nan = nan.neg_p (); | |||
321 | } | |||
322 | else | |||
323 | { | |||
324 | m_pos_nan = false; | |||
325 | m_neg_nan = false; | |||
326 | } | |||
327 | ||||
328 | if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type))((((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_VECTOR_FLOAT ) && ((real_format_for_mode[(((enum mode_class) mode_class [as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code ) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_DECIMAL_FLOAT ) ? (((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_DECIMAL_FLOAT ) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class ) mode_class[as_a <scalar_float_mode> ((mode_to_inner ( ((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_FLOAT ? ((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_FLOAT ) : ((fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 328, __FUNCTION__)), 0)]))->has_signed_zero)) | |||
329 | { | |||
330 | if (real_iszero (&m_min, 1)) | |||
331 | m_min.sign = 0; | |||
332 | if (real_iszero (&m_max, 1)) | |||
333 | m_max.sign = 0; | |||
334 | } | |||
335 | else if (!HONOR_SIGNED_ZEROS (m_type)) | |||
336 | { | |||
337 | if (real_iszero (&m_max, 1)) | |||
338 | m_max.sign = 0; | |||
339 | if (real_iszero (&m_min, 0)) | |||
340 | m_min.sign = 1; | |||
341 | } | |||
342 | ||||
343 | // For -ffinite-math-only we can drop ranges outside the | |||
344 | // representable numbers to min/max for the type. | |||
345 | if (!HONOR_INFINITIES (m_type)) | |||
346 | { | |||
347 | REAL_VALUE_TYPEstruct real_value min_repr = frange_val_min (m_type); | |||
348 | REAL_VALUE_TYPEstruct real_value max_repr = frange_val_max (m_type); | |||
349 | if (real_less (&m_min, &min_repr)) | |||
350 | m_min = min_repr; | |||
351 | else if (real_less (&max_repr, &m_min)) | |||
352 | m_min = max_repr; | |||
353 | if (real_less (&max_repr, &m_max)) | |||
354 | m_max = max_repr; | |||
355 | else if (real_less (&m_max, &min_repr)) | |||
356 | m_max = min_repr; | |||
357 | } | |||
358 | ||||
359 | // Check for swapped ranges. | |||
360 | gcc_checking_assert (real_compare (LE_EXPR, &min, &max))((void)(!(real_compare (LE_EXPR, &min, &max)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 360, __FUNCTION__), 0 : 0)); | |||
361 | ||||
362 | normalize_kind (); | |||
363 | ||||
364 | flush_denormals_to_zero (); | |||
365 | ||||
366 | if (flag_checkingglobal_options.x_flag_checking) | |||
367 | verify_range (); | |||
368 | } | |||
369 | ||||
370 | // Setter for an frange defaulting the NAN possibility to +-NAN when | |||
371 | // HONOR_NANS. | |||
372 | ||||
373 | void | |||
374 | frange::set (tree type, | |||
375 | const REAL_VALUE_TYPEstruct real_value &min, const REAL_VALUE_TYPEstruct real_value &max, | |||
376 | value_range_kind kind) | |||
377 | { | |||
378 | nan_state nan; | |||
379 | set (type, min, max, nan, kind); | |||
380 | } | |||
381 | ||||
382 | void | |||
383 | frange::set (tree min, tree max, value_range_kind kind) | |||
384 | { | |||
385 | set (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 385, __FUNCTION__))->typed.type), | |||
386 | *TREE_REAL_CST_PTR (min)(&(tree_check ((min), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 386, __FUNCTION__, (REAL_CST)))->real_cst.value), *TREE_REAL_CST_PTR (max)(&(tree_check ((max), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 386, __FUNCTION__, (REAL_CST)))->real_cst.value), kind); | |||
387 | } | |||
388 | ||||
389 | // Normalize range to VARYING or UNDEFINED, or vice versa. Return | |||
390 | // TRUE if anything changed. | |||
391 | // | |||
392 | // A range with no known properties can be dropped to VARYING. | |||
393 | // Similarly, a VARYING with any properties should be dropped to a | |||
394 | // VR_RANGE. Normalizing ranges upon changing them ensures there is | |||
395 | // only one representation for a given range. | |||
396 | ||||
397 | bool | |||
398 | frange::normalize_kind () | |||
399 | { | |||
400 | if (m_kind == VR_RANGE | |||
401 | && frange_val_is_min (m_min, m_type) | |||
402 | && frange_val_is_max (m_max, m_type)) | |||
403 | { | |||
404 | if (!HONOR_NANS (m_type) || (m_pos_nan && m_neg_nan)) | |||
405 | { | |||
406 | set_varying (m_type); | |||
407 | return true; | |||
408 | } | |||
409 | } | |||
410 | else if (m_kind == VR_VARYING) | |||
411 | { | |||
412 | if (HONOR_NANS (m_type) && (!m_pos_nan || !m_neg_nan)) | |||
413 | { | |||
414 | m_kind = VR_RANGE; | |||
415 | m_min = frange_val_min (m_type); | |||
416 | m_max = frange_val_max (m_type); | |||
417 | return true; | |||
418 | } | |||
419 | } | |||
420 | else if (m_kind == VR_NAN && !m_pos_nan && !m_neg_nan) | |||
421 | set_undefined (); | |||
422 | return false; | |||
423 | } | |||
424 | ||||
425 | // Union or intersect the zero endpoints of two ranges. For example: | |||
426 | // [-0, x] U [+0, x] => [-0, x] | |||
427 | // [ x, -0] U [ x, +0] => [ x, +0] | |||
428 | // [-0, x] ^ [+0, x] => [+0, x] | |||
429 | // [ x, -0] ^ [ x, +0] => [ x, -0] | |||
430 | // | |||
431 | // UNION_P is true when performing a union, or false when intersecting. | |||
432 | ||||
433 | bool | |||
434 | frange::combine_zeros (const frange &r, bool union_p) | |||
435 | { | |||
436 | gcc_checking_assert (!undefined_p () && !known_isnan ())((void)(!(!undefined_p () && !known_isnan ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 436, __FUNCTION__), 0 : 0)); | |||
437 | ||||
438 | bool changed = false; | |||
439 | if (real_iszero (&m_min) && real_iszero (&r.m_min) | |||
440 | && real_isneg (&m_min) != real_isneg (&r.m_min)) | |||
441 | { | |||
442 | m_min.sign = union_p; | |||
443 | changed = true; | |||
444 | } | |||
445 | if (real_iszero (&m_max) && real_iszero (&r.m_max) | |||
446 | && real_isneg (&m_max) != real_isneg (&r.m_max)) | |||
447 | { | |||
448 | m_max.sign = !union_p; | |||
449 | changed = true; | |||
450 | } | |||
451 | // If the signs are swapped, the resulting range is empty. | |||
452 | if (m_min.sign == 0 && m_max.sign == 1) | |||
453 | { | |||
454 | if (maybe_isnan ()) | |||
455 | m_kind = VR_NAN; | |||
456 | else | |||
457 | set_undefined (); | |||
458 | changed = true; | |||
459 | } | |||
460 | return changed; | |||
461 | } | |||
462 | ||||
463 | // Union two ranges when one is known to be a NAN. | |||
464 | ||||
465 | bool | |||
466 | frange::union_nans (const frange &r) | |||
467 | { | |||
468 | gcc_checking_assert (known_isnan () || r.known_isnan ())((void)(!(known_isnan () || r.known_isnan ()) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 468, __FUNCTION__), 0 : 0)); | |||
469 | ||||
470 | if (known_isnan ()) | |||
471 | { | |||
472 | m_kind = r.m_kind; | |||
473 | m_min = r.m_min; | |||
474 | m_max = r.m_max; | |||
475 | } | |||
476 | m_pos_nan |= r.m_pos_nan; | |||
477 | m_neg_nan |= r.m_neg_nan; | |||
478 | normalize_kind (); | |||
479 | if (flag_checkingglobal_options.x_flag_checking) | |||
480 | verify_range (); | |||
481 | return true; | |||
482 | } | |||
483 | ||||
484 | bool | |||
485 | frange::union_ (const vrange &v) | |||
486 | { | |||
487 | const frange &r = as_a <frange> (v); | |||
488 | ||||
489 | if (r.undefined_p () || varying_p ()) | |||
490 | return false; | |||
491 | if (undefined_p () || r.varying_p ()) | |||
492 | { | |||
493 | *this = r; | |||
494 | return true; | |||
495 | } | |||
496 | ||||
497 | // Combine NAN info. | |||
498 | if (known_isnan () || r.known_isnan ()) | |||
499 | return union_nans (r); | |||
500 | bool changed = false; | |||
501 | if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan) | |||
502 | { | |||
503 | m_pos_nan |= r.m_pos_nan; | |||
504 | m_neg_nan |= r.m_neg_nan; | |||
505 | changed = true; | |||
506 | } | |||
507 | ||||
508 | // Combine endpoints. | |||
509 | if (real_less (&r.m_min, &m_min)) | |||
510 | { | |||
511 | m_min = r.m_min; | |||
512 | changed = true; | |||
513 | } | |||
514 | if (real_less (&m_max, &r.m_max)) | |||
515 | { | |||
516 | m_max = r.m_max; | |||
517 | changed = true; | |||
518 | } | |||
519 | ||||
520 | if (HONOR_SIGNED_ZEROS (m_type)) | |||
521 | changed |= combine_zeros (r, true); | |||
522 | ||||
523 | changed |= normalize_kind (); | |||
524 | if (flag_checkingglobal_options.x_flag_checking) | |||
525 | verify_range (); | |||
526 | return changed; | |||
527 | } | |||
528 | ||||
529 | // Intersect two ranges when one is known to be a NAN. | |||
530 | ||||
531 | bool | |||
532 | frange::intersect_nans (const frange &r) | |||
533 | { | |||
534 | gcc_checking_assert (known_isnan () || r.known_isnan ())((void)(!(known_isnan () || r.known_isnan ()) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 534, __FUNCTION__), 0 : 0)); | |||
535 | ||||
536 | m_pos_nan &= r.m_pos_nan; | |||
537 | m_neg_nan &= r.m_neg_nan; | |||
538 | if (maybe_isnan ()) | |||
539 | m_kind = VR_NAN; | |||
540 | else | |||
541 | set_undefined (); | |||
542 | if (flag_checkingglobal_options.x_flag_checking) | |||
543 | verify_range (); | |||
544 | return true; | |||
545 | } | |||
546 | ||||
547 | bool | |||
548 | frange::intersect (const vrange &v) | |||
549 | { | |||
550 | const frange &r = as_a <frange> (v); | |||
551 | ||||
552 | if (undefined_p () || r.varying_p ()) | |||
553 | return false; | |||
554 | if (r.undefined_p ()) | |||
555 | { | |||
556 | set_undefined (); | |||
557 | return true; | |||
558 | } | |||
559 | if (varying_p ()) | |||
560 | { | |||
561 | *this = r; | |||
562 | return true; | |||
563 | } | |||
564 | ||||
565 | // Combine NAN info. | |||
566 | if (known_isnan () || r.known_isnan ()) | |||
567 | return intersect_nans (r); | |||
568 | bool changed = false; | |||
569 | if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan) | |||
570 | { | |||
571 | m_pos_nan &= r.m_pos_nan; | |||
572 | m_neg_nan &= r.m_neg_nan; | |||
573 | changed = true; | |||
574 | } | |||
575 | ||||
576 | // Combine endpoints. | |||
577 | if (real_less (&m_min, &r.m_min)) | |||
578 | { | |||
579 | m_min = r.m_min; | |||
580 | changed = true; | |||
581 | } | |||
582 | if (real_less (&r.m_max, &m_max)) | |||
583 | { | |||
584 | m_max = r.m_max; | |||
585 | changed = true; | |||
586 | } | |||
587 | // If the endpoints are swapped, the resulting range is empty. | |||
588 | if (real_less (&m_max, &m_min)) | |||
589 | { | |||
590 | if (maybe_isnan ()) | |||
591 | m_kind = VR_NAN; | |||
592 | else | |||
593 | set_undefined (); | |||
594 | if (flag_checkingglobal_options.x_flag_checking) | |||
595 | verify_range (); | |||
596 | return true; | |||
597 | } | |||
598 | ||||
599 | if (HONOR_SIGNED_ZEROS (m_type)) | |||
600 | changed |= combine_zeros (r, false); | |||
601 | ||||
602 | changed |= normalize_kind (); | |||
603 | if (flag_checkingglobal_options.x_flag_checking) | |||
604 | verify_range (); | |||
605 | return changed; | |||
606 | } | |||
607 | ||||
608 | frange & | |||
609 | frange::operator= (const frange &src) | |||
610 | { | |||
611 | m_kind = src.m_kind; | |||
612 | m_type = src.m_type; | |||
613 | m_min = src.m_min; | |||
614 | m_max = src.m_max; | |||
615 | m_pos_nan = src.m_pos_nan; | |||
616 | m_neg_nan = src.m_neg_nan; | |||
617 | ||||
618 | if (flag_checkingglobal_options.x_flag_checking) | |||
619 | verify_range (); | |||
620 | return *this; | |||
621 | } | |||
622 | ||||
623 | bool | |||
624 | frange::operator== (const frange &src) const | |||
625 | { | |||
626 | if (m_kind == src.m_kind) | |||
627 | { | |||
628 | if (undefined_p ()) | |||
629 | return true; | |||
630 | ||||
631 | if (varying_p ()) | |||
632 | return types_compatible_p (m_type, src.m_type); | |||
633 | ||||
634 | if (known_isnan () || src.known_isnan ()) | |||
635 | return false; | |||
636 | ||||
637 | return (real_identical (&m_min, &src.m_min) | |||
638 | && real_identical (&m_max, &src.m_max) | |||
639 | && m_pos_nan == src.m_pos_nan | |||
640 | && m_neg_nan == src.m_neg_nan | |||
641 | && types_compatible_p (m_type, src.m_type)); | |||
642 | } | |||
643 | return false; | |||
644 | } | |||
645 | ||||
646 | // Return TRUE if range contains the TREE_REAL_CST_PTR in CST. | |||
647 | ||||
648 | bool | |||
649 | frange::contains_p (tree cst) const | |||
650 | { | |||
651 | gcc_checking_assert (m_kind != VR_ANTI_RANGE)((void)(!(m_kind != VR_ANTI_RANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 651, __FUNCTION__), 0 : 0)); | |||
652 | const REAL_VALUE_TYPEstruct real_value *rv = TREE_REAL_CST_PTR (cst)(&(tree_check ((cst), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 652, __FUNCTION__, (REAL_CST)))->real_cst.value); | |||
653 | ||||
654 | if (undefined_p ()) | |||
655 | return false; | |||
656 | ||||
657 | if (varying_p ()) | |||
658 | return true; | |||
659 | ||||
660 | if (real_isnan (rv)) | |||
661 | { | |||
662 | // No NAN in range. | |||
663 | if (!m_pos_nan && !m_neg_nan) | |||
664 | return false; | |||
665 | // Both +NAN and -NAN are present. | |||
666 | if (m_pos_nan && m_neg_nan) | |||
667 | return true; | |||
668 | return m_neg_nan == rv->sign; | |||
669 | } | |||
670 | if (known_isnan ()) | |||
671 | return false; | |||
672 | ||||
673 | if (real_compare (GE_EXPR, rv, &m_min) && real_compare (LE_EXPR, rv, &m_max)) | |||
674 | { | |||
675 | // Make sure the signs are equal for signed zeros. | |||
676 | if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (rv)) | |||
677 | return rv->sign == m_min.sign || rv->sign == m_max.sign; | |||
678 | return true; | |||
679 | } | |||
680 | return false; | |||
681 | } | |||
682 | ||||
683 | // If range is a singleton, place it in RESULT and return TRUE. If | |||
684 | // RESULT is NULL, just return TRUE. | |||
685 | // | |||
686 | // A NAN can never be a singleton. | |||
687 | ||||
688 | bool | |||
689 | frange::singleton_p (tree *result) const | |||
690 | { | |||
691 | if (m_kind == VR_RANGE && real_identical (&m_min, &m_max)) | |||
692 | { | |||
693 | // Return false for any singleton that may be a NAN. | |||
694 | if (HONOR_NANS (m_type) && maybe_isnan ()) | |||
695 | return false; | |||
696 | ||||
697 | if (MODE_COMPOSITE_P (TYPE_MODE (m_type))((((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode)]) == MODE_VECTOR_FLOAT ) && ((real_format_for_mode[(((enum mode_class) mode_class [as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code ) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_DECIMAL_FLOAT ) ? (((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_DECIMAL_FLOAT ) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class ) mode_class[as_a <scalar_float_mode> ((mode_to_inner ( ((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_FLOAT ? ((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_FLOAT ) : ((fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)), 0)]))->pnan < ((real_format_for_mode [(((enum mode_class) mode_class[as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_DECIMAL_FLOAT ) ? (((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_DECIMAL_FLOAT ) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class ) mode_class[as_a <scalar_float_mode> ((mode_to_inner ( ((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))]) == MODE_FLOAT ? ((as_a <scalar_float_mode> ((mode_to_inner (((((enum tree_code) ((tree_class_check ((m_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (m_type) : (m_type)->type_common.mode))))) - MIN_MODE_FLOAT ) : ((fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 697, __FUNCTION__)), 0)]))->p)) | |||
698 | { | |||
699 | // For IBM long doubles, if the value is +-Inf or is exactly | |||
700 | // representable in double, the other double could be +0.0 | |||
701 | // or -0.0. Since this means there is more than one way to | |||
702 | // represent a value, return false to avoid propagating it. | |||
703 | // See libgcc/config/rs6000/ibm-ldouble-format for details. | |||
704 | if (real_isinf (&m_min)) | |||
705 | return false; | |||
706 | REAL_VALUE_TYPEstruct real_value r; | |||
707 | real_convert (&r, DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)), &m_min); | |||
708 | if (real_identical (&r, &m_min)) | |||
709 | return false; | |||
710 | } | |||
711 | ||||
712 | if (result) | |||
713 | *result = build_real (m_type, m_min); | |||
714 | return true; | |||
715 | } | |||
716 | return false; | |||
717 | } | |||
718 | ||||
719 | bool | |||
720 | frange::supports_type_p (const_tree type) const | |||
721 | { | |||
722 | return supports_p (type); | |||
723 | } | |||
724 | ||||
725 | void | |||
726 | frange::verify_range () | |||
727 | { | |||
728 | if (!undefined_p ()) | |||
729 | gcc_checking_assert (HONOR_NANS (m_type) || !maybe_isnan ())((void)(!(HONOR_NANS (m_type) || !maybe_isnan ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 729, __FUNCTION__), 0 : 0)); | |||
730 | switch (m_kind) | |||
731 | { | |||
732 | case VR_UNDEFINED: | |||
733 | gcc_checking_assert (!m_type)((void)(!(!m_type) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 733, __FUNCTION__), 0 : 0)); | |||
734 | return; | |||
735 | case VR_VARYING: | |||
736 | gcc_checking_assert (m_type)((void)(!(m_type) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 736, __FUNCTION__), 0 : 0)); | |||
737 | gcc_checking_assert (frange_val_is_min (m_min, m_type))((void)(!(frange_val_is_min (m_min, m_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 737, __FUNCTION__), 0 : 0)); | |||
738 | gcc_checking_assert (frange_val_is_max (m_max, m_type))((void)(!(frange_val_is_max (m_max, m_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 738, __FUNCTION__), 0 : 0)); | |||
739 | if (HONOR_NANS (m_type)) | |||
740 | gcc_checking_assert (m_pos_nan && m_neg_nan)((void)(!(m_pos_nan && m_neg_nan) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 740, __FUNCTION__), 0 : 0)); | |||
741 | else | |||
742 | gcc_checking_assert (!m_pos_nan && !m_neg_nan)((void)(!(!m_pos_nan && !m_neg_nan) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 742, __FUNCTION__), 0 : 0)); | |||
743 | return; | |||
744 | case VR_RANGE: | |||
745 | gcc_checking_assert (m_type)((void)(!(m_type) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 745, __FUNCTION__), 0 : 0)); | |||
746 | break; | |||
747 | case VR_NAN: | |||
748 | gcc_checking_assert (m_type)((void)(!(m_type) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 748, __FUNCTION__), 0 : 0)); | |||
749 | gcc_checking_assert (m_pos_nan || m_neg_nan)((void)(!(m_pos_nan || m_neg_nan) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 749, __FUNCTION__), 0 : 0)); | |||
750 | return; | |||
751 | default: | |||
752 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 752, __FUNCTION__)); | |||
753 | } | |||
754 | ||||
755 | // NANs cannot appear in the endpoints of a range. | |||
756 | gcc_checking_assert (!real_isnan (&m_min) && !real_isnan (&m_max))((void)(!(!real_isnan (&m_min) && !real_isnan (& m_max)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 756, __FUNCTION__), 0 : 0)); | |||
757 | ||||
758 | // Make sure we don't have swapped ranges. | |||
759 | gcc_checking_assert (!real_less (&m_max, &m_min))((void)(!(!real_less (&m_max, &m_min)) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 759, __FUNCTION__), 0 : 0)); | |||
760 | ||||
761 | // [ +0.0, -0.0 ] is nonsensical. | |||
762 | gcc_checking_assert (!(real_iszero (&m_min, 0) && real_iszero (&m_max, 1)))((void)(!(!(real_iszero (&m_min, 0) && real_iszero (&m_max, 1))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 762, __FUNCTION__), 0 : 0)); | |||
763 | ||||
764 | // If all the properties are clear, we better not span the entire | |||
765 | // domain, because that would make us varying. | |||
766 | if (m_pos_nan && m_neg_nan) | |||
767 | gcc_checking_assert (!frange_val_is_min (m_min, m_type)((void)(!(!frange_val_is_min (m_min, m_type) || !frange_val_is_max (m_max, m_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 768, __FUNCTION__), 0 : 0)) | |||
768 | || !frange_val_is_max (m_max, m_type))((void)(!(!frange_val_is_min (m_min, m_type) || !frange_val_is_max (m_max, m_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 768, __FUNCTION__), 0 : 0)); | |||
769 | } | |||
770 | ||||
771 | // We can't do much with nonzeros yet. | |||
772 | void | |||
773 | frange::set_nonzero (tree type) | |||
774 | { | |||
775 | set_varying (type); | |||
776 | } | |||
777 | ||||
778 | // We can't do much with nonzeros yet. | |||
779 | bool | |||
780 | frange::nonzero_p () const | |||
781 | { | |||
782 | return false; | |||
783 | } | |||
784 | ||||
785 | // Set range to [+0.0, +0.0] if honoring signed zeros, or [0.0, 0.0] | |||
786 | // otherwise. | |||
787 | ||||
788 | void | |||
789 | frange::set_zero (tree type) | |||
790 | { | |||
791 | if (HONOR_SIGNED_ZEROS (type)) | |||
792 | { | |||
793 | REAL_VALUE_TYPEstruct real_value dconstm0 = dconst0; | |||
794 | dconstm0.sign = 1; | |||
795 | set (type, dconstm0, dconst0); | |||
796 | clear_nan (); | |||
797 | } | |||
798 | else | |||
799 | set (type, dconst0, dconst0); | |||
800 | } | |||
801 | ||||
802 | // Return TRUE for any zero regardless of sign. | |||
803 | ||||
804 | bool | |||
805 | frange::zero_p () const | |||
806 | { | |||
807 | return (m_kind == VR_RANGE | |||
808 | && real_iszero (&m_min) | |||
809 | && real_iszero (&m_max)); | |||
810 | } | |||
811 | ||||
812 | // Set the range to non-negative numbers, that is [+0.0, +INF]. | |||
813 | // | |||
814 | // The NAN in the resulting range (if HONOR_NANS) has a varying sign | |||
815 | // as there are no guarantees in IEEE 754 wrt to the sign of a NAN, | |||
816 | // except for copy, abs, and copysign. It is the responsibility of | |||
817 | // the caller to set the NAN's sign if desired. | |||
818 | ||||
819 | void | |||
820 | frange::set_nonnegative (tree type) | |||
821 | { | |||
822 | set (type, dconst0, frange_val_max (type)); | |||
823 | } | |||
824 | ||||
825 | // Here we copy between any two irange's. The ranges can be legacy or | |||
826 | // multi-ranges, and copying between any combination works correctly. | |||
827 | ||||
828 | irange & | |||
829 | irange::operator= (const irange &src) | |||
830 | { | |||
831 | if (legacy_mode_p ()) | |||
832 | { | |||
833 | copy_to_legacy (src); | |||
834 | return *this; | |||
835 | } | |||
836 | if (src.legacy_mode_p ()) | |||
837 | { | |||
838 | copy_legacy_to_multi_range (src); | |||
839 | return *this; | |||
840 | } | |||
841 | ||||
842 | unsigned x; | |||
843 | unsigned lim = src.m_num_ranges; | |||
844 | if (lim > m_max_ranges) | |||
845 | lim = m_max_ranges; | |||
846 | ||||
847 | for (x = 0; x < lim * 2; ++x) | |||
848 | m_base[x] = src.m_base[x]; | |||
849 | ||||
850 | // If the range didn't fit, the last range should cover the rest. | |||
851 | if (lim != src.m_num_ranges) | |||
852 | m_base[x - 1] = src.m_base[src.m_num_ranges * 2 - 1]; | |||
853 | ||||
854 | m_num_ranges = lim; | |||
855 | m_kind = src.m_kind; | |||
856 | m_nonzero_mask = src.m_nonzero_mask; | |||
857 | if (flag_checkingglobal_options.x_flag_checking) | |||
858 | verify_range (); | |||
859 | return *this; | |||
860 | } | |||
861 | ||||
862 | // Return TRUE if range is a multi-range that can be represented as a | |||
863 | // VR_ANTI_RANGE. | |||
864 | ||||
865 | bool | |||
866 | irange::maybe_anti_range () const | |||
867 | { | |||
868 | tree ttype = type (); | |||
869 | unsigned int precision = TYPE_PRECISION (ttype)((tree_class_check ((ttype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 869, __FUNCTION__))->type_common.precision); | |||
870 | signop sign = TYPE_SIGN (ttype)((signop) ((tree_class_check ((ttype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 870, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
871 | return (num_pairs () > 1 | |||
872 | && precision > 1 | |||
873 | && lower_bound () == wi::min_value (precision, sign) | |||
874 | && upper_bound () == wi::max_value (precision, sign)); | |||
875 | } | |||
876 | ||||
877 | void | |||
878 | irange::copy_legacy_to_multi_range (const irange &src) | |||
879 | { | |||
880 | gcc_checking_assert (src.legacy_mode_p ())((void)(!(src.legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 880, __FUNCTION__), 0 : 0)); | |||
881 | gcc_checking_assert (!legacy_mode_p ())((void)(!(!legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 881, __FUNCTION__), 0 : 0)); | |||
882 | if (src.undefined_p ()) | |||
883 | set_undefined (); | |||
884 | else if (src.varying_p ()) | |||
885 | set_varying (src.type ()); | |||
886 | else | |||
887 | { | |||
888 | if (range_has_numeric_bounds_p (&src)) | |||
889 | set (src.min (), src.max (), src.kind ()); | |||
890 | else | |||
891 | { | |||
892 | value_range cst (src); | |||
893 | cst.normalize_symbolics (); | |||
894 | gcc_checking_assert (cst.varying_p () || cst.kind () == VR_RANGE)((void)(!(cst.varying_p () || cst.kind () == VR_RANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 894, __FUNCTION__), 0 : 0)); | |||
895 | set (cst.min (), cst.max ()); | |||
896 | } | |||
897 | } | |||
898 | } | |||
899 | ||||
900 | // Copy any type of irange into a legacy. | |||
901 | ||||
902 | void | |||
903 | irange::copy_to_legacy (const irange &src) | |||
904 | { | |||
905 | gcc_checking_assert (legacy_mode_p ())((void)(!(legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 905, __FUNCTION__), 0 : 0)); | |||
906 | // Handle legacy to legacy and other things that are easy to copy. | |||
907 | if (src.legacy_mode_p () || src.varying_p () || src.undefined_p ()) | |||
908 | { | |||
909 | m_num_ranges = src.m_num_ranges; | |||
910 | m_base[0] = src.m_base[0]; | |||
911 | m_base[1] = src.m_base[1]; | |||
912 | m_kind = src.m_kind; | |||
913 | m_nonzero_mask = src.m_nonzero_mask; | |||
914 | return; | |||
915 | } | |||
916 | // Copy multi-range to legacy. | |||
917 | if (src.maybe_anti_range ()) | |||
918 | { | |||
919 | int_range<3> r (src); | |||
920 | r.invert (); | |||
921 | // Use tree variants to save on tree -> wi -> tree conversions. | |||
922 | set (r.tree_lower_bound (0), r.tree_upper_bound (0), VR_ANTI_RANGE); | |||
923 | } | |||
924 | else | |||
925 | set (src.tree_lower_bound (), src.tree_upper_bound ()); | |||
926 | } | |||
927 | ||||
928 | // Swap MIN/MAX if they are out of order and adjust KIND appropriately. | |||
929 | ||||
930 | static void | |||
931 | swap_out_of_order_endpoints (tree &min, tree &max, value_range_kind &kind) | |||
932 | { | |||
933 | gcc_checking_assert (kind != VR_UNDEFINED)((void)(!(kind != VR_UNDEFINED) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 933, __FUNCTION__), 0 : 0)); | |||
934 | if (kind == VR_VARYING) | |||
935 | return; | |||
936 | /* Wrong order for min and max, to swap them and the VR type we need | |||
937 | to adjust them. */ | |||
938 | if (tree_int_cst_lt (max, min)) | |||
939 | { | |||
940 | tree one, tmp; | |||
941 | ||||
942 | /* For one bit precision if max < min, then the swapped | |||
943 | range covers all values, so for VR_RANGE it is varying and | |||
944 | for VR_ANTI_RANGE empty range, so drop to varying as well. */ | |||
945 | if (TYPE_PRECISION (TREE_TYPE (min))((tree_class_check ((((contains_struct_check ((min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 945, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 945, __FUNCTION__))->type_common.precision) == 1) | |||
946 | { | |||
947 | kind = VR_VARYING; | |||
948 | return; | |||
949 | } | |||
950 | ||||
951 | one = build_int_cst (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 951, __FUNCTION__))->typed.type), 1); | |||
952 | tmp = int_const_binop (PLUS_EXPR, max, one); | |||
953 | max = int_const_binop (MINUS_EXPR, min, one); | |||
954 | min = tmp; | |||
955 | ||||
956 | /* There's one corner case, if we had [C+1, C] before we now have | |||
957 | that again. But this represents an empty value range, so drop | |||
958 | to varying in this case. */ | |||
959 | if (tree_int_cst_lt (max, min)) | |||
960 | { | |||
961 | kind = VR_VARYING; | |||
962 | return; | |||
963 | } | |||
964 | kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE; | |||
965 | } | |||
966 | } | |||
967 | ||||
968 | void | |||
969 | irange::irange_set (tree min, tree max) | |||
970 | { | |||
971 | gcc_checking_assert (!POLY_INT_CST_P (min))((void)(!(!(1 > 1 && ((enum tree_code) (min)->base .code) == POLY_INT_CST)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 971, __FUNCTION__), 0 : 0)); | |||
972 | gcc_checking_assert (!POLY_INT_CST_P (max))((void)(!(!(1 > 1 && ((enum tree_code) (max)->base .code) == POLY_INT_CST)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 972, __FUNCTION__), 0 : 0)); | |||
973 | ||||
974 | m_base[0] = min; | |||
975 | m_base[1] = max; | |||
976 | m_num_ranges = 1; | |||
977 | m_kind = VR_RANGE; | |||
978 | m_nonzero_mask = NULLnullptr; | |||
979 | normalize_kind (); | |||
980 | ||||
981 | if (flag_checkingglobal_options.x_flag_checking) | |||
982 | verify_range (); | |||
983 | } | |||
984 | ||||
985 | void | |||
986 | irange::irange_set_1bit_anti_range (tree min, tree max) | |||
987 | { | |||
988 | tree type = TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 988, __FUNCTION__))->typed.type); | |||
989 | gcc_checking_assert (TYPE_PRECISION (type) == 1)((void)(!(((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 989, __FUNCTION__))->type_common.precision) == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 989, __FUNCTION__), 0 : 0)); | |||
990 | ||||
991 | if (operand_equal_p (min, max)) | |||
992 | { | |||
993 | // Since these are 1-bit quantities, they can only be [MIN,MIN] | |||
994 | // or [MAX,MAX]. | |||
995 | if (vrp_val_is_min (min)) | |||
996 | min = max = vrp_val_max (type); | |||
997 | else | |||
998 | min = max = vrp_val_min (type); | |||
999 | set (min, max); | |||
1000 | } | |||
1001 | else | |||
1002 | { | |||
1003 | // The only alternative is [MIN,MAX], which is the empty range. | |||
1004 | gcc_checking_assert (vrp_val_is_min (min))((void)(!(vrp_val_is_min (min)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1004, __FUNCTION__), 0 : 0)); | |||
1005 | gcc_checking_assert (vrp_val_is_max (max))((void)(!(vrp_val_is_max (max)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1005, __FUNCTION__), 0 : 0)); | |||
1006 | set_undefined (); | |||
1007 | } | |||
1008 | if (flag_checkingglobal_options.x_flag_checking) | |||
1009 | verify_range (); | |||
1010 | } | |||
1011 | ||||
1012 | void | |||
1013 | irange::irange_set_anti_range (tree min, tree max) | |||
1014 | { | |||
1015 | gcc_checking_assert (!POLY_INT_CST_P (min))((void)(!(!(1 > 1 && ((enum tree_code) (min)->base .code) == POLY_INT_CST)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1015, __FUNCTION__), 0 : 0)); | |||
1016 | gcc_checking_assert (!POLY_INT_CST_P (max))((void)(!(!(1 > 1 && ((enum tree_code) (max)->base .code) == POLY_INT_CST)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1016, __FUNCTION__), 0 : 0)); | |||
1017 | ||||
1018 | if (TYPE_PRECISION (TREE_TYPE (min))((tree_class_check ((((contains_struct_check ((min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1018, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1018, __FUNCTION__))->type_common.precision) == 1) | |||
1019 | { | |||
1020 | irange_set_1bit_anti_range (min, max); | |||
1021 | return; | |||
1022 | } | |||
1023 | ||||
1024 | // set an anti-range | |||
1025 | tree type = TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1025, __FUNCTION__))->typed.type); | |||
1026 | signop sign = TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1026, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
1027 | int_range<2> type_range (type); | |||
1028 | // Calculate INVERSE([I,J]) as [-MIN, I-1][J+1, +MAX]. | |||
1029 | m_num_ranges = 0; | |||
1030 | wi::overflow_type ovf; | |||
1031 | ||||
1032 | wide_int w_min = wi::to_wide (min); | |||
1033 | if (wi::ne_p (w_min, type_range.lower_bound ())) | |||
1034 | { | |||
1035 | wide_int lim1 = wi::sub (w_min, 1, sign, &ovf); | |||
1036 | gcc_checking_assert (ovf != wi::OVF_OVERFLOW)((void)(!(ovf != wi::OVF_OVERFLOW) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1036, __FUNCTION__), 0 : 0)); | |||
1037 | m_base[0] = type_range.tree_lower_bound (0); | |||
1038 | m_base[1] = wide_int_to_tree (type, lim1); | |||
1039 | m_num_ranges = 1; | |||
1040 | } | |||
1041 | wide_int w_max = wi::to_wide (max); | |||
1042 | if (wi::ne_p (w_max, type_range.upper_bound ())) | |||
1043 | { | |||
1044 | wide_int lim2 = wi::add (w_max, 1, sign, &ovf); | |||
1045 | gcc_checking_assert (ovf != wi::OVF_OVERFLOW)((void)(!(ovf != wi::OVF_OVERFLOW) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1045, __FUNCTION__), 0 : 0)); | |||
1046 | m_base[m_num_ranges * 2] = wide_int_to_tree (type, lim2); | |||
1047 | m_base[m_num_ranges * 2 + 1] = type_range.tree_upper_bound (0); | |||
1048 | ++m_num_ranges; | |||
1049 | } | |||
1050 | ||||
1051 | m_kind = VR_RANGE; | |||
1052 | m_nonzero_mask = NULLnullptr; | |||
1053 | normalize_kind (); | |||
1054 | ||||
1055 | if (flag_checkingglobal_options.x_flag_checking) | |||
1056 | verify_range (); | |||
1057 | } | |||
1058 | ||||
1059 | /* Set value range to the canonical form of {VRTYPE, MIN, MAX, EQUIV}. | |||
1060 | This means adjusting VRTYPE, MIN and MAX representing the case of a | |||
1061 | wrapping range with MAX < MIN covering [MIN, type_max] U [type_min, MAX] | |||
1062 | as anti-rage ~[MAX+1, MIN-1]. Likewise for wrapping anti-ranges. | |||
1063 | In corner cases where MAX+1 or MIN-1 wraps this will fall back | |||
1064 | to varying. | |||
1065 | This routine exists to ease canonicalization in the case where we | |||
1066 | extract ranges from var + CST op limit. */ | |||
1067 | ||||
1068 | void | |||
1069 | irange::set (tree min, tree max, value_range_kind kind) | |||
1070 | { | |||
1071 | if (kind == VR_UNDEFINED) | |||
1072 | { | |||
1073 | irange::set_undefined (); | |||
1074 | return; | |||
1075 | } | |||
1076 | ||||
1077 | if (kind == VR_VARYING | |||
1078 | || POLY_INT_CST_P (min)(1 > 1 && ((enum tree_code) (min)->base.code) == POLY_INT_CST) | |||
1079 | || POLY_INT_CST_P (max)(1 > 1 && ((enum tree_code) (max)->base.code) == POLY_INT_CST)) | |||
1080 | { | |||
1081 | set_varying (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1081, __FUNCTION__))->typed.type)); | |||
1082 | return; | |||
1083 | } | |||
1084 | ||||
1085 | if (TREE_OVERFLOW_P (min)((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (min)->base.code))] == tcc_constant) && ((tree_class_check ((min), (tcc_constant), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1085, __FUNCTION__))->base.public_flag))) | |||
1086 | min = drop_tree_overflow (min); | |||
1087 | if (TREE_OVERFLOW_P (max)((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (max)->base.code))] == tcc_constant) && ((tree_class_check ((max), (tcc_constant), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1087, __FUNCTION__))->base.public_flag))) | |||
1088 | max = drop_tree_overflow (max); | |||
1089 | ||||
1090 | if (!legacy_mode_p ()) | |||
1091 | { | |||
1092 | if (kind == VR_RANGE) | |||
1093 | irange_set (min, max); | |||
1094 | else | |||
1095 | { | |||
1096 | gcc_checking_assert (kind == VR_ANTI_RANGE)((void)(!(kind == VR_ANTI_RANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1096, __FUNCTION__), 0 : 0)); | |||
1097 | irange_set_anti_range (min, max); | |||
1098 | } | |||
1099 | return; | |||
1100 | } | |||
1101 | // Nothing to canonicalize for symbolic ranges. | |||
1102 | if (TREE_CODE (min)((enum tree_code) (min)->base.code) != INTEGER_CST | |||
1103 | || TREE_CODE (max)((enum tree_code) (max)->base.code) != INTEGER_CST) | |||
1104 | { | |||
1105 | m_kind = kind; | |||
1106 | m_base[0] = min; | |||
1107 | m_base[1] = max; | |||
1108 | m_num_ranges = 1; | |||
1109 | m_nonzero_mask = NULLnullptr; | |||
1110 | return; | |||
1111 | } | |||
1112 | ||||
1113 | swap_out_of_order_endpoints (min, max, kind); | |||
1114 | if (kind == VR_VARYING) | |||
1115 | { | |||
1116 | set_varying (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1116, __FUNCTION__))->typed.type)); | |||
1117 | return; | |||
1118 | } | |||
1119 | ||||
1120 | // Anti-ranges that can be represented as ranges should be so. | |||
1121 | if (kind == VR_ANTI_RANGE) | |||
1122 | { | |||
1123 | bool is_min = vrp_val_is_min (min); | |||
1124 | bool is_max = vrp_val_is_max (max); | |||
1125 | ||||
1126 | if (is_min && is_max) | |||
1127 | { | |||
1128 | // Fall through. This will either be normalized as | |||
1129 | // VR_UNDEFINED if the anti-range spans the entire | |||
1130 | // precision, or it will remain an VR_ANTI_RANGE in the case | |||
1131 | // of an -fstrict-enum where [MIN,MAX] is less than the span | |||
1132 | // of underlying precision. | |||
1133 | } | |||
1134 | else if (TYPE_PRECISION (TREE_TYPE (min))((tree_class_check ((((contains_struct_check ((min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1134, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1134, __FUNCTION__))->type_common.precision) == 1) | |||
1135 | { | |||
1136 | irange_set_1bit_anti_range (min, max); | |||
1137 | return; | |||
1138 | } | |||
1139 | else if (is_min) | |||
1140 | { | |||
1141 | tree one = build_int_cst (TREE_TYPE (max)((contains_struct_check ((max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1141, __FUNCTION__))->typed.type), 1); | |||
1142 | min = int_const_binop (PLUS_EXPR, max, one); | |||
1143 | max = vrp_val_max (TREE_TYPE (max)((contains_struct_check ((max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1143, __FUNCTION__))->typed.type)); | |||
1144 | kind = VR_RANGE; | |||
1145 | } | |||
1146 | else if (is_max) | |||
1147 | { | |||
1148 | tree one = build_int_cst (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1148, __FUNCTION__))->typed.type), 1); | |||
1149 | max = int_const_binop (MINUS_EXPR, min, one); | |||
1150 | min = vrp_val_min (TREE_TYPE (min)((contains_struct_check ((min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1150, __FUNCTION__))->typed.type)); | |||
1151 | kind = VR_RANGE; | |||
1152 | } | |||
1153 | } | |||
1154 | ||||
1155 | m_kind = kind; | |||
1156 | m_base[0] = min; | |||
1157 | m_base[1] = max; | |||
1158 | m_num_ranges = 1; | |||
1159 | m_nonzero_mask = NULLnullptr; | |||
1160 | normalize_kind (); | |||
1161 | if (flag_checkingglobal_options.x_flag_checking) | |||
1162 | verify_range (); | |||
1163 | } | |||
1164 | ||||
1165 | // Check the validity of the range. | |||
1166 | ||||
1167 | void | |||
1168 | irange::verify_range () | |||
1169 | { | |||
1170 | gcc_checking_assert (m_discriminator == VR_IRANGE)((void)(!(m_discriminator == VR_IRANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1170, __FUNCTION__), 0 : 0)); | |||
1171 | if (m_kind == VR_UNDEFINED) | |||
1172 | { | |||
1173 | gcc_checking_assert (m_num_ranges == 0)((void)(!(m_num_ranges == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1173, __FUNCTION__), 0 : 0)); | |||
1174 | return; | |||
1175 | } | |||
1176 | if (m_kind == VR_VARYING) | |||
1177 | { | |||
1178 | gcc_checking_assert (!m_nonzero_mask((void)(!(!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == - 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1179, __FUNCTION__), 0 : 0)) | |||
1179 | || wi::to_wide (m_nonzero_mask) == -1)((void)(!(!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == - 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1179, __FUNCTION__), 0 : 0)); | |||
1180 | gcc_checking_assert (m_num_ranges == 1)((void)(!(m_num_ranges == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1180, __FUNCTION__), 0 : 0)); | |||
1181 | gcc_checking_assert (varying_compatible_p ())((void)(!(varying_compatible_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1181, __FUNCTION__), 0 : 0)); | |||
1182 | return; | |||
1183 | } | |||
1184 | if (!legacy_mode_p ()) | |||
1185 | { | |||
1186 | gcc_checking_assert (m_num_ranges != 0)((void)(!(m_num_ranges != 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1186, __FUNCTION__), 0 : 0)); | |||
1187 | gcc_checking_assert (!varying_compatible_p ())((void)(!(!varying_compatible_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1187, __FUNCTION__), 0 : 0)); | |||
1188 | for (unsigned i = 0; i < m_num_ranges; ++i) | |||
1189 | { | |||
1190 | tree lb = tree_lower_bound (i); | |||
1191 | tree ub = tree_upper_bound (i); | |||
1192 | int c = compare_values (lb, ub); | |||
1193 | gcc_checking_assert (c == 0 || c == -1)((void)(!(c == 0 || c == -1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1193, __FUNCTION__), 0 : 0)); | |||
1194 | } | |||
1195 | return; | |||
1196 | } | |||
1197 | if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE) | |||
1198 | { | |||
1199 | gcc_checking_assert (m_num_ranges == 1)((void)(!(m_num_ranges == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1199, __FUNCTION__), 0 : 0)); | |||
1200 | int cmp = compare_values (tree_lower_bound (0), tree_upper_bound (0)); | |||
1201 | gcc_checking_assert (cmp == 0 || cmp == -1 || cmp == -2)((void)(!(cmp == 0 || cmp == -1 || cmp == -2) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1201, __FUNCTION__), 0 : 0)); | |||
1202 | } | |||
1203 | } | |||
1204 | ||||
1205 | // Return the lower bound for a sub-range. PAIR is the sub-range in | |||
1206 | // question. | |||
1207 | ||||
1208 | wide_int | |||
1209 | irange::legacy_lower_bound (unsigned pair) const | |||
1210 | { | |||
1211 | gcc_checking_assert (legacy_mode_p ())((void)(!(legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1211, __FUNCTION__), 0 : 0)); | |||
1212 | if (symbolic_p ()) | |||
1213 | { | |||
1214 | value_range numeric_range (*this); | |||
1215 | numeric_range.normalize_symbolics (); | |||
1216 | return numeric_range.legacy_lower_bound (pair); | |||
1217 | } | |||
1218 | gcc_checking_assert (m_num_ranges > 0)((void)(!(m_num_ranges > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1218, __FUNCTION__), 0 : 0)); | |||
1219 | gcc_checking_assert (pair + 1 <= num_pairs ())((void)(!(pair + 1 <= num_pairs ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1219, __FUNCTION__), 0 : 0)); | |||
1220 | if (m_kind == VR_ANTI_RANGE) | |||
1221 | { | |||
1222 | tree typ = type (), t; | |||
1223 | if (pair == 1 || vrp_val_is_min (min ())) | |||
1224 | t = wide_int_to_tree (typ, wi::to_wide (max ()) + 1); | |||
1225 | else | |||
1226 | t = vrp_val_min (typ); | |||
1227 | return wi::to_wide (t); | |||
1228 | } | |||
1229 | return wi::to_wide (tree_lower_bound (pair)); | |||
1230 | } | |||
1231 | ||||
1232 | // Return the upper bound for a sub-range. PAIR is the sub-range in | |||
1233 | // question. | |||
1234 | ||||
1235 | wide_int | |||
1236 | irange::legacy_upper_bound (unsigned pair) const | |||
1237 | { | |||
1238 | gcc_checking_assert (legacy_mode_p ())((void)(!(legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1238, __FUNCTION__), 0 : 0)); | |||
1239 | if (symbolic_p ()) | |||
1240 | { | |||
1241 | value_range numeric_range (*this); | |||
1242 | numeric_range.normalize_symbolics (); | |||
1243 | return numeric_range.legacy_upper_bound (pair); | |||
1244 | } | |||
1245 | gcc_checking_assert (m_num_ranges > 0)((void)(!(m_num_ranges > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1245, __FUNCTION__), 0 : 0)); | |||
1246 | gcc_checking_assert (pair + 1 <= num_pairs ())((void)(!(pair + 1 <= num_pairs ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1246, __FUNCTION__), 0 : 0)); | |||
1247 | if (m_kind == VR_ANTI_RANGE) | |||
1248 | { | |||
1249 | tree typ = type (), t; | |||
1250 | if (pair == 1 || vrp_val_is_min (min ())) | |||
1251 | t = vrp_val_max (typ); | |||
1252 | else | |||
1253 | t = wide_int_to_tree (typ, wi::to_wide (min ()) - 1); | |||
1254 | return wi::to_wide (t); | |||
1255 | } | |||
1256 | return wi::to_wide (tree_upper_bound (pair)); | |||
1257 | } | |||
1258 | ||||
1259 | bool | |||
1260 | irange::legacy_equal_p (const irange &other) const | |||
1261 | { | |||
1262 | gcc_checking_assert (legacy_mode_p () && other.legacy_mode_p ())((void)(!(legacy_mode_p () && other.legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1262, __FUNCTION__), 0 : 0)); | |||
1263 | ||||
1264 | if (m_kind != other.m_kind) | |||
1265 | return false; | |||
1266 | if (m_kind == VR_UNDEFINED) | |||
1267 | return true; | |||
1268 | if (m_kind == VR_VARYING) | |||
1269 | return range_compatible_p (type (), other.type ()); | |||
1270 | return (vrp_operand_equal_p (tree_lower_bound (0), | |||
1271 | other.tree_lower_bound (0)) | |||
1272 | && vrp_operand_equal_p (tree_upper_bound (0), | |||
1273 | other.tree_upper_bound (0)) | |||
1274 | && (widest_int::from (get_nonzero_bits (), | |||
1275 | TYPE_SIGN (type ())((signop) ((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1275, __FUNCTION__))->base.u.bits.unsigned_flag))) | |||
1276 | == widest_int::from (other.get_nonzero_bits (), | |||
1277 | TYPE_SIGN (other.type ())((signop) ((tree_class_check ((other.type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1277, __FUNCTION__))->base.u.bits.unsigned_flag))))); | |||
1278 | } | |||
1279 | ||||
1280 | bool | |||
1281 | irange::operator== (const irange &other) const | |||
1282 | { | |||
1283 | if (legacy_mode_p ()) | |||
1284 | { | |||
1285 | if (other.legacy_mode_p ()) | |||
1286 | return legacy_equal_p (other); | |||
1287 | value_range tmp (other); | |||
1288 | return legacy_equal_p (tmp); | |||
1289 | } | |||
1290 | if (other.legacy_mode_p ()) | |||
1291 | { | |||
1292 | value_range tmp2 (*this); | |||
1293 | return tmp2.legacy_equal_p (other); | |||
1294 | } | |||
1295 | ||||
1296 | if (m_num_ranges != other.m_num_ranges) | |||
1297 | return false; | |||
1298 | ||||
1299 | if (m_num_ranges == 0) | |||
1300 | return true; | |||
1301 | ||||
1302 | for (unsigned i = 0; i < m_num_ranges; ++i) | |||
1303 | { | |||
1304 | tree lb = tree_lower_bound (i); | |||
1305 | tree ub = tree_upper_bound (i); | |||
1306 | tree lb_other = other.tree_lower_bound (i); | |||
1307 | tree ub_other = other.tree_upper_bound (i); | |||
1308 | if (!operand_equal_p (lb, lb_other, 0) | |||
1309 | || !operand_equal_p (ub, ub_other, 0)) | |||
1310 | return false; | |||
1311 | } | |||
1312 | widest_int nz1 = widest_int::from (get_nonzero_bits (), | |||
1313 | TYPE_SIGN (type ())((signop) ((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1313, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
1314 | widest_int nz2 = widest_int::from (other.get_nonzero_bits (), | |||
1315 | TYPE_SIGN (other.type ())((signop) ((tree_class_check ((other.type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1315, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
1316 | return nz1 == nz2; | |||
1317 | } | |||
1318 | ||||
1319 | /* Return TRUE if this is a symbolic range. */ | |||
1320 | ||||
1321 | bool | |||
1322 | irange::symbolic_p () const | |||
1323 | { | |||
1324 | return (m_num_ranges > 0 | |||
1325 | && (!is_gimple_min_invariant (min ()) | |||
1326 | || !is_gimple_min_invariant (max ()))); | |||
1327 | } | |||
1328 | ||||
1329 | /* Return TRUE if this is a constant range. */ | |||
1330 | ||||
1331 | bool | |||
1332 | irange::constant_p () const | |||
1333 | { | |||
1334 | return (m_num_ranges > 0 | |||
1335 | && TREE_CODE (min ())((enum tree_code) (min ())->base.code) == INTEGER_CST | |||
1336 | && TREE_CODE (max ())((enum tree_code) (max ())->base.code) == INTEGER_CST); | |||
1337 | } | |||
1338 | ||||
1339 | /* If range is a singleton, place it in RESULT and return TRUE. | |||
1340 | Note: A singleton can be any gimple invariant, not just constants. | |||
1341 | So, [&x, &x] counts as a singleton. */ | |||
1342 | ||||
1343 | bool | |||
1344 | irange::singleton_p (tree *result) const | |||
1345 | { | |||
1346 | if (!legacy_mode_p ()) | |||
1347 | { | |||
1348 | if (num_pairs () == 1 && (wi::to_wide (tree_lower_bound ()) | |||
1349 | == wi::to_wide (tree_upper_bound ()))) | |||
1350 | { | |||
1351 | if (result) | |||
1352 | *result = tree_lower_bound (); | |||
1353 | return true; | |||
1354 | } | |||
1355 | return false; | |||
1356 | } | |||
1357 | if (m_kind == VR_ANTI_RANGE) | |||
1358 | { | |||
1359 | if (nonzero_p ()) | |||
1360 | { | |||
1361 | if (TYPE_PRECISION (type ())((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1361, __FUNCTION__))->type_common.precision) == 1) | |||
1362 | { | |||
1363 | if (result) | |||
1364 | *result = max (); | |||
1365 | return true; | |||
1366 | } | |||
1367 | return false; | |||
1368 | } | |||
1369 | if (num_pairs () == 1) | |||
1370 | { | |||
1371 | value_range vr0, vr1; | |||
1372 | ranges_from_anti_range ((const value_range *) this, &vr0, &vr1); | |||
1373 | return vr0.singleton_p (result); | |||
1374 | } | |||
1375 | } | |||
1376 | // Catches non-numeric extremes as well. | |||
1377 | if (m_kind == VR_RANGE | |||
1378 | && vrp_operand_equal_p (min (), max ()) | |||
1379 | && is_gimple_min_invariant (min ())) | |||
1380 | { | |||
1381 | if (result) | |||
1382 | *result = min (); | |||
1383 | return true; | |||
1384 | } | |||
1385 | return false; | |||
1386 | } | |||
1387 | ||||
1388 | /* Return 1 if VAL is inside value range. | |||
1389 | 0 if VAL is not inside value range. | |||
1390 | -2 if we cannot tell either way. | |||
1391 | ||||
1392 | Benchmark compile/20001226-1.c compilation time after changing this | |||
1393 | function. */ | |||
1394 | ||||
1395 | int | |||
1396 | irange::value_inside_range (tree val) const | |||
1397 | { | |||
1398 | if (varying_p ()) | |||
1399 | return 1; | |||
1400 | ||||
1401 | if (undefined_p ()) | |||
1402 | return 0; | |||
1403 | ||||
1404 | if (!legacy_mode_p () && TREE_CODE (val)((enum tree_code) (val)->base.code) == INTEGER_CST) | |||
1405 | return contains_p (val); | |||
1406 | ||||
1407 | int cmp1 = operand_less_p (val, min ()); | |||
1408 | if (cmp1 == -2) | |||
1409 | return -2; | |||
1410 | if (cmp1 == 1) | |||
1411 | return m_kind != VR_RANGE; | |||
1412 | ||||
1413 | int cmp2 = operand_less_p (max (), val); | |||
1414 | if (cmp2 == -2) | |||
1415 | return -2; | |||
1416 | ||||
1417 | if (m_kind == VR_RANGE) | |||
1418 | return !cmp2; | |||
1419 | else | |||
1420 | return !!cmp2; | |||
1421 | } | |||
1422 | ||||
1423 | /* Return TRUE if it is possible that range contains VAL. */ | |||
1424 | ||||
1425 | bool | |||
1426 | irange::may_contain_p (tree val) const | |||
1427 | { | |||
1428 | return value_inside_range (val) != 0; | |||
1429 | } | |||
1430 | ||||
1431 | /* Return TRUE if range contains INTEGER_CST. */ | |||
1432 | /* Return 1 if VAL is inside value range. | |||
1433 | 0 if VAL is not inside value range. | |||
1434 | ||||
1435 | Benchmark compile/20001226-1.c compilation time after changing this | |||
1436 | function. */ | |||
1437 | ||||
1438 | ||||
1439 | bool | |||
1440 | irange::contains_p (tree cst) const | |||
1441 | { | |||
1442 | if (undefined_p ()) | |||
1443 | return false; | |||
1444 | ||||
1445 | if (legacy_mode_p ()) | |||
1446 | { | |||
1447 | gcc_checking_assert (TREE_CODE (cst) == INTEGER_CST)((void)(!(((enum tree_code) (cst)->base.code) == INTEGER_CST ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1447, __FUNCTION__), 0 : 0)); | |||
1448 | if (symbolic_p ()) | |||
1449 | { | |||
1450 | value_range numeric_range (*this); | |||
1451 | numeric_range.normalize_symbolics (); | |||
1452 | return numeric_range.contains_p (cst); | |||
1453 | } | |||
1454 | return value_inside_range (cst) == 1; | |||
1455 | } | |||
1456 | ||||
1457 | gcc_checking_assert (TREE_CODE (cst) == INTEGER_CST)((void)(!(((enum tree_code) (cst)->base.code) == INTEGER_CST ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1457, __FUNCTION__), 0 : 0)); | |||
1458 | ||||
1459 | // See if we can exclude CST based on the nonzero bits. | |||
1460 | if (m_nonzero_mask) | |||
1461 | { | |||
1462 | wide_int cstw = wi::to_wide (cst); | |||
1463 | if (cstw != 0 && wi::bit_and (wi::to_wide (m_nonzero_mask), cstw) == 0) | |||
1464 | return false; | |||
1465 | } | |||
1466 | ||||
1467 | signop sign = TYPE_SIGN (TREE_TYPE (cst))((signop) ((tree_class_check ((((contains_struct_check ((cst) , (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1467, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1467, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
1468 | wide_int v = wi::to_wide (cst); | |||
1469 | for (unsigned r = 0; r < m_num_ranges; ++r) | |||
1470 | { | |||
1471 | if (wi::lt_p (v, lower_bound (r), sign)) | |||
1472 | return false; | |||
1473 | if (wi::le_p (v, upper_bound (r), sign)) | |||
1474 | return true; | |||
1475 | } | |||
1476 | ||||
1477 | return false; | |||
1478 | } | |||
1479 | ||||
1480 | ||||
1481 | /* Normalize addresses into constants. */ | |||
1482 | ||||
1483 | void | |||
1484 | irange::normalize_addresses () | |||
1485 | { | |||
1486 | if (undefined_p ()) | |||
1487 | return; | |||
1488 | ||||
1489 | if (!POINTER_TYPE_P (type ())(((enum tree_code) (type ())->base.code) == POINTER_TYPE || ((enum tree_code) (type ())->base.code) == REFERENCE_TYPE ) || range_has_numeric_bounds_p (this)) | |||
1490 | return; | |||
1491 | ||||
1492 | if (!range_includes_zero_p (this)) | |||
1493 | { | |||
1494 | gcc_checking_assert (TREE_CODE (min ()) == ADDR_EXPR((void)(!(((enum tree_code) (min ())->base.code) == ADDR_EXPR || ((enum tree_code) (max ())->base.code) == ADDR_EXPR) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1495, __FUNCTION__), 0 : 0)) | |||
1495 | || TREE_CODE (max ()) == ADDR_EXPR)((void)(!(((enum tree_code) (min ())->base.code) == ADDR_EXPR || ((enum tree_code) (max ())->base.code) == ADDR_EXPR) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1495, __FUNCTION__), 0 : 0)); | |||
1496 | set_nonzero (type ()); | |||
1497 | return; | |||
1498 | } | |||
1499 | set_varying (type ()); | |||
1500 | } | |||
1501 | ||||
1502 | /* Normalize symbolics and addresses into constants. */ | |||
1503 | ||||
1504 | void | |||
1505 | irange::normalize_symbolics () | |||
1506 | { | |||
1507 | if (varying_p () || undefined_p ()) | |||
1508 | return; | |||
1509 | ||||
1510 | tree ttype = type (); | |||
1511 | bool min_symbolic = !is_gimple_min_invariant (min ()); | |||
1512 | bool max_symbolic = !is_gimple_min_invariant (max ()); | |||
1513 | if (!min_symbolic && !max_symbolic) | |||
1514 | { | |||
1515 | normalize_addresses (); | |||
1516 | return; | |||
1517 | } | |||
1518 | ||||
1519 | // [SYM, SYM] -> VARYING | |||
1520 | if (min_symbolic && max_symbolic) | |||
1521 | { | |||
1522 | set_varying (ttype); | |||
1523 | return; | |||
1524 | } | |||
1525 | if (kind () == VR_RANGE) | |||
1526 | { | |||
1527 | // [SYM, NUM] -> [-MIN, NUM] | |||
1528 | if (min_symbolic) | |||
1529 | { | |||
1530 | set (vrp_val_min (ttype), max ()); | |||
1531 | return; | |||
1532 | } | |||
1533 | // [NUM, SYM] -> [NUM, +MAX] | |||
1534 | set (min (), vrp_val_max (ttype)); | |||
1535 | return; | |||
1536 | } | |||
1537 | gcc_checking_assert (kind () == VR_ANTI_RANGE)((void)(!(kind () == VR_ANTI_RANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1537, __FUNCTION__), 0 : 0)); | |||
1538 | // ~[SYM, NUM] -> [NUM + 1, +MAX] | |||
1539 | if (min_symbolic) | |||
1540 | { | |||
1541 | if (!vrp_val_is_max (max ())) | |||
1542 | { | |||
1543 | tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1); | |||
1544 | set (n, vrp_val_max (ttype)); | |||
1545 | return; | |||
1546 | } | |||
1547 | set_varying (ttype); | |||
1548 | return; | |||
1549 | } | |||
1550 | // ~[NUM, SYM] -> [-MIN, NUM - 1] | |||
1551 | if (!vrp_val_is_min (min ())) | |||
1552 | { | |||
1553 | tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1); | |||
1554 | set (vrp_val_min (ttype), n); | |||
1555 | return; | |||
1556 | } | |||
1557 | set_varying (ttype); | |||
1558 | } | |||
1559 | ||||
1560 | /* Intersect the two value-ranges { *VR0TYPE, *VR0MIN, *VR0MAX } and | |||
1561 | { VR1TYPE, VR0MIN, VR0MAX } and store the result | |||
1562 | in { *VR0TYPE, *VR0MIN, *VR0MAX }. This may not be the smallest | |||
1563 | possible such range. The resulting range is not canonicalized. */ | |||
1564 | ||||
1565 | static void | |||
1566 | intersect_ranges (enum value_range_kind *vr0type, | |||
1567 | tree *vr0min, tree *vr0max, | |||
1568 | enum value_range_kind vr1type, | |||
1569 | tree vr1min, tree vr1max) | |||
1570 | { | |||
1571 | bool mineq = vrp_operand_equal_p (*vr0min, vr1min); | |||
1572 | bool maxeq = vrp_operand_equal_p (*vr0max, vr1max); | |||
1573 | ||||
1574 | /* [] is vr0, () is vr1 in the following classification comments. */ | |||
1575 | if (mineq && maxeq) | |||
1576 | { | |||
1577 | /* [( )] */ | |||
1578 | if (*vr0type == vr1type) | |||
1579 | /* Nothing to do for equal ranges. */ | |||
1580 | ; | |||
1581 | else if ((*vr0type == VR_RANGE | |||
1582 | && vr1type == VR_ANTI_RANGE) | |||
1583 | || (*vr0type == VR_ANTI_RANGE | |||
1584 | && vr1type == VR_RANGE)) | |||
1585 | { | |||
1586 | /* For anti-range with range intersection the result is empty. */ | |||
1587 | *vr0type = VR_UNDEFINED; | |||
1588 | *vr0min = NULL_TREE(tree) nullptr; | |||
1589 | *vr0max = NULL_TREE(tree) nullptr; | |||
1590 | } | |||
1591 | else | |||
1592 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1592, __FUNCTION__)); | |||
1593 | } | |||
1594 | else if (operand_less_p (*vr0max, vr1min) == 1 | |||
1595 | || operand_less_p (vr1max, *vr0min) == 1) | |||
1596 | { | |||
1597 | /* [ ] ( ) or ( ) [ ] | |||
1598 | If the ranges have an empty intersection, the result of the | |||
1599 | intersect operation is the range for intersecting an | |||
1600 | anti-range with a range or empty when intersecting two ranges. */ | |||
1601 | if (*vr0type == VR_RANGE | |||
1602 | && vr1type == VR_ANTI_RANGE) | |||
1603 | ; | |||
1604 | else if (*vr0type == VR_ANTI_RANGE | |||
1605 | && vr1type == VR_RANGE) | |||
1606 | { | |||
1607 | *vr0type = vr1type; | |||
1608 | *vr0min = vr1min; | |||
1609 | *vr0max = vr1max; | |||
1610 | } | |||
1611 | else if (*vr0type == VR_RANGE | |||
1612 | && vr1type == VR_RANGE) | |||
1613 | { | |||
1614 | *vr0type = VR_UNDEFINED; | |||
1615 | *vr0min = NULL_TREE(tree) nullptr; | |||
1616 | *vr0max = NULL_TREE(tree) nullptr; | |||
1617 | } | |||
1618 | else if (*vr0type == VR_ANTI_RANGE | |||
1619 | && vr1type == VR_ANTI_RANGE) | |||
1620 | { | |||
1621 | /* If the anti-ranges are adjacent to each other merge them. */ | |||
1622 | if (TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) == INTEGER_CST | |||
1623 | && TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST | |||
1624 | && operand_less_p (*vr0max, vr1min) == 1 | |||
1625 | && integer_onep (int_const_binop (MINUS_EXPR, | |||
1626 | vr1min, *vr0max))) | |||
1627 | *vr0max = vr1max; | |||
1628 | else if (TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST | |||
1629 | && TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) == INTEGER_CST | |||
1630 | && operand_less_p (vr1max, *vr0min) == 1 | |||
1631 | && integer_onep (int_const_binop (MINUS_EXPR, | |||
1632 | *vr0min, vr1max))) | |||
1633 | *vr0min = vr1min; | |||
1634 | /* Else arbitrarily take VR0. */ | |||
1635 | } | |||
1636 | } | |||
1637 | else if ((maxeq || operand_less_p (vr1max, *vr0max) == 1) | |||
1638 | && (mineq || operand_less_p (*vr0min, vr1min) == 1)) | |||
1639 | { | |||
1640 | /* [ ( ) ] or [( ) ] or [ ( )] */ | |||
1641 | if (*vr0type == VR_RANGE | |||
1642 | && vr1type == VR_RANGE) | |||
1643 | { | |||
1644 | /* If both are ranges the result is the inner one. */ | |||
1645 | *vr0type = vr1type; | |||
1646 | *vr0min = vr1min; | |||
1647 | *vr0max = vr1max; | |||
1648 | } | |||
1649 | else if (*vr0type == VR_RANGE | |||
1650 | && vr1type == VR_ANTI_RANGE) | |||
1651 | { | |||
1652 | /* Choose the right gap if the left one is empty. */ | |||
1653 | if (mineq) | |||
1654 | { | |||
1655 | if (TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) != INTEGER_CST) | |||
1656 | *vr0min = vr1max; | |||
1657 | else if (TYPE_PRECISION (TREE_TYPE (vr1max))((tree_class_check ((((contains_struct_check ((vr1max), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1657, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1657, __FUNCTION__))->type_common.precision) == 1 | |||
1658 | && !TYPE_UNSIGNED (TREE_TYPE (vr1max))((tree_class_check ((((contains_struct_check ((vr1max), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1658, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1658, __FUNCTION__))->base.u.bits.unsigned_flag)) | |||
1659 | *vr0min | |||
1660 | = int_const_binop (MINUS_EXPR, vr1max, | |||
1661 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1661, __FUNCTION__))->typed.type), -1)); | |||
1662 | else | |||
1663 | *vr0min | |||
1664 | = int_const_binop (PLUS_EXPR, vr1max, | |||
1665 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1665, __FUNCTION__))->typed.type), 1)); | |||
1666 | } | |||
1667 | /* Choose the left gap if the right one is empty. */ | |||
1668 | else if (maxeq) | |||
1669 | { | |||
1670 | if (TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) != INTEGER_CST) | |||
1671 | *vr0max = vr1min; | |||
1672 | else if (TYPE_PRECISION (TREE_TYPE (vr1min))((tree_class_check ((((contains_struct_check ((vr1min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1672, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1672, __FUNCTION__))->type_common.precision) == 1 | |||
1673 | && !TYPE_UNSIGNED (TREE_TYPE (vr1min))((tree_class_check ((((contains_struct_check ((vr1min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1673, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1673, __FUNCTION__))->base.u.bits.unsigned_flag)) | |||
1674 | *vr0max | |||
1675 | = int_const_binop (PLUS_EXPR, vr1min, | |||
1676 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1676, __FUNCTION__))->typed.type), -1)); | |||
1677 | else | |||
1678 | *vr0max | |||
1679 | = int_const_binop (MINUS_EXPR, vr1min, | |||
1680 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1680, __FUNCTION__))->typed.type), 1)); | |||
1681 | } | |||
1682 | /* Choose the anti-range if the range is effectively varying. */ | |||
1683 | else if (vrp_val_is_min (*vr0min) | |||
1684 | && vrp_val_is_max (*vr0max)) | |||
1685 | { | |||
1686 | *vr0type = vr1type; | |||
1687 | *vr0min = vr1min; | |||
1688 | *vr0max = vr1max; | |||
1689 | } | |||
1690 | /* Else choose the range. */ | |||
1691 | } | |||
1692 | else if (*vr0type == VR_ANTI_RANGE | |||
1693 | && vr1type == VR_ANTI_RANGE) | |||
1694 | /* If both are anti-ranges the result is the outer one. */ | |||
1695 | ; | |||
1696 | else if (*vr0type == VR_ANTI_RANGE | |||
1697 | && vr1type == VR_RANGE) | |||
1698 | { | |||
1699 | /* The intersection is empty. */ | |||
1700 | *vr0type = VR_UNDEFINED; | |||
1701 | *vr0min = NULL_TREE(tree) nullptr; | |||
1702 | *vr0max = NULL_TREE(tree) nullptr; | |||
1703 | } | |||
1704 | else | |||
1705 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1705, __FUNCTION__)); | |||
1706 | } | |||
1707 | else if ((maxeq || operand_less_p (*vr0max, vr1max) == 1) | |||
1708 | && (mineq || operand_less_p (vr1min, *vr0min) == 1)) | |||
1709 | { | |||
1710 | /* ( [ ] ) or ([ ] ) or ( [ ]) */ | |||
1711 | if (*vr0type == VR_RANGE | |||
1712 | && vr1type == VR_RANGE) | |||
1713 | /* Choose the inner range. */ | |||
1714 | ; | |||
1715 | else if (*vr0type == VR_ANTI_RANGE | |||
1716 | && vr1type == VR_RANGE) | |||
1717 | { | |||
1718 | /* Choose the right gap if the left is empty. */ | |||
1719 | if (mineq) | |||
1720 | { | |||
1721 | *vr0type = VR_RANGE; | |||
1722 | if (TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) != INTEGER_CST) | |||
1723 | *vr0min = *vr0max; | |||
1724 | else if (TYPE_PRECISION (TREE_TYPE (*vr0max))((tree_class_check ((((contains_struct_check ((*vr0max), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1724, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1724, __FUNCTION__))->type_common.precision) == 1 | |||
1725 | && !TYPE_UNSIGNED (TREE_TYPE (*vr0max))((tree_class_check ((((contains_struct_check ((*vr0max), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1725, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1725, __FUNCTION__))->base.u.bits.unsigned_flag)) | |||
1726 | *vr0min | |||
1727 | = int_const_binop (MINUS_EXPR, *vr0max, | |||
1728 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1728, __FUNCTION__))->typed.type), -1)); | |||
1729 | else | |||
1730 | *vr0min | |||
1731 | = int_const_binop (PLUS_EXPR, *vr0max, | |||
1732 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1732, __FUNCTION__))->typed.type), 1)); | |||
1733 | *vr0max = vr1max; | |||
1734 | } | |||
1735 | /* Choose the left gap if the right is empty. */ | |||
1736 | else if (maxeq) | |||
1737 | { | |||
1738 | *vr0type = VR_RANGE; | |||
1739 | if (TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) != INTEGER_CST) | |||
1740 | *vr0max = *vr0min; | |||
1741 | else if (TYPE_PRECISION (TREE_TYPE (*vr0min))((tree_class_check ((((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1741, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1741, __FUNCTION__))->type_common.precision) == 1 | |||
1742 | && !TYPE_UNSIGNED (TREE_TYPE (*vr0min))((tree_class_check ((((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1742, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1742, __FUNCTION__))->base.u.bits.unsigned_flag)) | |||
1743 | *vr0max | |||
1744 | = int_const_binop (PLUS_EXPR, *vr0min, | |||
1745 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1745, __FUNCTION__))->typed.type), -1)); | |||
1746 | else | |||
1747 | *vr0max | |||
1748 | = int_const_binop (MINUS_EXPR, *vr0min, | |||
1749 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1749, __FUNCTION__))->typed.type), 1)); | |||
1750 | *vr0min = vr1min; | |||
1751 | } | |||
1752 | /* Choose the anti-range if the range is effectively varying. */ | |||
1753 | else if (vrp_val_is_min (vr1min) | |||
1754 | && vrp_val_is_max (vr1max)) | |||
1755 | ; | |||
1756 | /* Choose the anti-range if it is ~[0,0], that range is special | |||
1757 | enough to special case when vr1's range is relatively wide. | |||
1758 | At least for types bigger than int - this covers pointers | |||
1759 | and arguments to functions like ctz. */ | |||
1760 | else if (*vr0min == *vr0max | |||
1761 | && integer_zerop (*vr0min) | |||
1762 | && ((TYPE_PRECISION (TREE_TYPE (*vr0min))((tree_class_check ((((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1762, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1762, __FUNCTION__))->type_common.precision) | |||
1763 | >= TYPE_PRECISION (integer_type_node)((tree_class_check ((integer_types[itk_int]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1763, __FUNCTION__))->type_common.precision)) | |||
1764 | || POINTER_TYPE_P (TREE_TYPE (*vr0min))(((enum tree_code) (((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1764, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1764, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
1765 | && TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST | |||
1766 | && TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST | |||
1767 | && (wi::clz (wi::to_wide (vr1max) - wi::to_wide (vr1min)) | |||
1768 | < TYPE_PRECISION (TREE_TYPE (*vr0min))((tree_class_check ((((contains_struct_check ((*vr0min), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1768, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1768, __FUNCTION__))->type_common.precision) / 2)) | |||
1769 | ; | |||
1770 | /* Else choose the range. */ | |||
1771 | else | |||
1772 | { | |||
1773 | *vr0type = vr1type; | |||
1774 | *vr0min = vr1min; | |||
1775 | *vr0max = vr1max; | |||
1776 | } | |||
1777 | } | |||
1778 | else if (*vr0type == VR_ANTI_RANGE | |||
1779 | && vr1type == VR_ANTI_RANGE) | |||
1780 | { | |||
1781 | /* If both are anti-ranges the result is the outer one. */ | |||
1782 | *vr0type = vr1type; | |||
1783 | *vr0min = vr1min; | |||
1784 | *vr0max = vr1max; | |||
1785 | } | |||
1786 | else if (vr1type == VR_ANTI_RANGE | |||
1787 | && *vr0type == VR_RANGE) | |||
1788 | { | |||
1789 | /* The intersection is empty. */ | |||
1790 | *vr0type = VR_UNDEFINED; | |||
1791 | *vr0min = NULL_TREE(tree) nullptr; | |||
1792 | *vr0max = NULL_TREE(tree) nullptr; | |||
1793 | } | |||
1794 | else | |||
1795 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1795, __FUNCTION__)); | |||
1796 | } | |||
1797 | else if ((operand_less_p (vr1min, *vr0max) == 1 | |||
1798 | || operand_equal_p (vr1min, *vr0max, 0)) | |||
1799 | && operand_less_p (*vr0min, vr1min) == 1 | |||
1800 | && operand_less_p (*vr0max, vr1max) == 1) | |||
1801 | { | |||
1802 | /* [ ( ] ) or [ ]( ) */ | |||
1803 | if (*vr0type == VR_ANTI_RANGE | |||
1804 | && vr1type == VR_ANTI_RANGE) | |||
1805 | *vr0max = vr1max; | |||
1806 | else if (*vr0type == VR_RANGE | |||
1807 | && vr1type == VR_RANGE) | |||
1808 | *vr0min = vr1min; | |||
1809 | else if (*vr0type == VR_RANGE | |||
1810 | && vr1type == VR_ANTI_RANGE) | |||
1811 | { | |||
1812 | if (TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST) | |||
1813 | *vr0max = int_const_binop (MINUS_EXPR, vr1min, | |||
1814 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1814, __FUNCTION__))->typed.type), 1)); | |||
1815 | else | |||
1816 | *vr0max = vr1min; | |||
1817 | } | |||
1818 | else if (*vr0type == VR_ANTI_RANGE | |||
1819 | && vr1type == VR_RANGE) | |||
1820 | { | |||
1821 | *vr0type = VR_RANGE; | |||
1822 | if (TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) == INTEGER_CST) | |||
1823 | *vr0min = int_const_binop (PLUS_EXPR, *vr0max, | |||
1824 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1824, __FUNCTION__))->typed.type), 1)); | |||
1825 | else | |||
1826 | *vr0min = *vr0max; | |||
1827 | *vr0max = vr1max; | |||
1828 | } | |||
1829 | else | |||
1830 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1830, __FUNCTION__)); | |||
1831 | } | |||
1832 | else if ((operand_less_p (*vr0min, vr1max) == 1 | |||
1833 | || operand_equal_p (*vr0min, vr1max, 0)) | |||
1834 | && operand_less_p (vr1min, *vr0min) == 1 | |||
1835 | && operand_less_p (vr1max, *vr0max) == 1) | |||
1836 | { | |||
1837 | /* ( [ ) ] or ( )[ ] */ | |||
1838 | if (*vr0type == VR_ANTI_RANGE | |||
1839 | && vr1type == VR_ANTI_RANGE) | |||
1840 | *vr0min = vr1min; | |||
1841 | else if (*vr0type == VR_RANGE | |||
1842 | && vr1type == VR_RANGE) | |||
1843 | *vr0max = vr1max; | |||
1844 | else if (*vr0type == VR_RANGE | |||
1845 | && vr1type == VR_ANTI_RANGE) | |||
1846 | { | |||
1847 | if (TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST) | |||
1848 | *vr0min = int_const_binop (PLUS_EXPR, vr1max, | |||
1849 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1849, __FUNCTION__))->typed.type), 1)); | |||
1850 | else | |||
1851 | *vr0min = vr1max; | |||
1852 | } | |||
1853 | else if (*vr0type == VR_ANTI_RANGE | |||
1854 | && vr1type == VR_RANGE) | |||
1855 | { | |||
1856 | *vr0type = VR_RANGE; | |||
1857 | if (TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) == INTEGER_CST) | |||
1858 | *vr0max = int_const_binop (MINUS_EXPR, *vr0min, | |||
1859 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1859, __FUNCTION__))->typed.type), 1)); | |||
1860 | else | |||
1861 | *vr0max = *vr0min; | |||
1862 | *vr0min = vr1min; | |||
1863 | } | |||
1864 | else | |||
1865 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1865, __FUNCTION__)); | |||
1866 | } | |||
1867 | ||||
1868 | /* If we know the intersection is empty, there's no need to | |||
1869 | conservatively add anything else to the set. */ | |||
1870 | if (*vr0type == VR_UNDEFINED) | |||
1871 | return; | |||
1872 | ||||
1873 | /* As a fallback simply use { *VRTYPE, *VR0MIN, *VR0MAX } as | |||
1874 | result for the intersection. That's always a conservative | |||
1875 | correct estimate unless VR1 is a constant singleton range | |||
1876 | in which case we choose that. */ | |||
1877 | if (vr1type == VR_RANGE | |||
1878 | && is_gimple_min_invariant (vr1min) | |||
1879 | && vrp_operand_equal_p (vr1min, vr1max)) | |||
1880 | { | |||
1881 | *vr0type = vr1type; | |||
1882 | *vr0min = vr1min; | |||
1883 | *vr0max = vr1max; | |||
1884 | } | |||
1885 | } | |||
1886 | ||||
1887 | /* Helper for the intersection operation for value ranges. Given two | |||
1888 | ranges VR0 and VR1, set VR0 to the intersection of both ranges. | |||
1889 | This may not be the smallest possible such range. */ | |||
1890 | ||||
1891 | void | |||
1892 | irange::legacy_intersect (irange *vr0, const irange *vr1) | |||
1893 | { | |||
1894 | gcc_checking_assert (vr0->legacy_mode_p ())((void)(!(vr0->legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1894, __FUNCTION__), 0 : 0)); | |||
1895 | gcc_checking_assert (vr1->legacy_mode_p ())((void)(!(vr1->legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1895, __FUNCTION__), 0 : 0)); | |||
1896 | /* If either range is VR_VARYING the other one wins. */ | |||
1897 | if (vr1->varying_p ()) | |||
1898 | return; | |||
1899 | if (vr0->varying_p ()) | |||
1900 | { | |||
1901 | vr0->set (vr1->min (), vr1->max (), vr1->kind ()); | |||
1902 | return; | |||
1903 | } | |||
1904 | ||||
1905 | /* When either range is VR_UNDEFINED the resulting range is | |||
1906 | VR_UNDEFINED, too. */ | |||
1907 | if (vr0->undefined_p ()) | |||
1908 | return; | |||
1909 | if (vr1->undefined_p ()) | |||
1910 | { | |||
1911 | vr0->set_undefined (); | |||
1912 | return; | |||
1913 | } | |||
1914 | ||||
1915 | value_range_kind vr0kind = vr0->kind (); | |||
1916 | tree vr0min = vr0->min (); | |||
1917 | tree vr0max = vr0->max (); | |||
1918 | ||||
1919 | intersect_ranges (&vr0kind, &vr0min, &vr0max, | |||
1920 | vr1->kind (), vr1->min (), vr1->max ()); | |||
1921 | ||||
1922 | /* Make sure to canonicalize the result though as the inversion of a | |||
1923 | VR_RANGE can still be a VR_RANGE. */ | |||
1924 | if (vr0kind == VR_UNDEFINED) | |||
1925 | vr0->set_undefined (); | |||
1926 | else if (vr0kind == VR_VARYING) | |||
1927 | { | |||
1928 | /* If we failed, use the original VR0. */ | |||
1929 | return; | |||
1930 | } | |||
1931 | else | |||
1932 | vr0->set (vr0min, vr0max, vr0kind); | |||
1933 | } | |||
1934 | ||||
1935 | /* Union the two value-ranges { *VR0TYPE, *VR0MIN, *VR0MAX } and | |||
1936 | { VR1TYPE, VR0MIN, VR0MAX } and store the result | |||
1937 | in { *VR0TYPE, *VR0MIN, *VR0MAX }. This may not be the smallest | |||
1938 | possible such range. The resulting range is not canonicalized. */ | |||
1939 | ||||
1940 | static void | |||
1941 | union_ranges (enum value_range_kind *vr0type, | |||
1942 | tree *vr0min, tree *vr0max, | |||
1943 | enum value_range_kind vr1type, | |||
1944 | tree vr1min, tree vr1max) | |||
1945 | { | |||
1946 | int cmpmin = compare_values (*vr0min, vr1min); | |||
1947 | int cmpmax = compare_values (*vr0max, vr1max); | |||
1948 | bool mineq = cmpmin == 0; | |||
1949 | bool maxeq = cmpmax == 0; | |||
1950 | ||||
1951 | /* [] is vr0, () is vr1 in the following classification comments. */ | |||
1952 | if (mineq && maxeq) | |||
1953 | { | |||
1954 | /* [( )] */ | |||
1955 | if (*vr0type == vr1type) | |||
1956 | /* Nothing to do for equal ranges. */ | |||
1957 | ; | |||
1958 | else if ((*vr0type == VR_RANGE | |||
1959 | && vr1type == VR_ANTI_RANGE) | |||
1960 | || (*vr0type == VR_ANTI_RANGE | |||
1961 | && vr1type == VR_RANGE)) | |||
1962 | { | |||
1963 | /* For anti-range with range union the result is varying. */ | |||
1964 | goto give_up; | |||
1965 | } | |||
1966 | else | |||
1967 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 1967, __FUNCTION__)); | |||
1968 | } | |||
1969 | else if (operand_less_p (*vr0max, vr1min) == 1 | |||
1970 | || operand_less_p (vr1max, *vr0min) == 1) | |||
1971 | { | |||
1972 | /* [ ] ( ) or ( ) [ ] | |||
1973 | If the ranges have an empty intersection, result of the union | |||
1974 | operation is the anti-range or if both are anti-ranges | |||
1975 | it covers all. */ | |||
1976 | if (*vr0type == VR_ANTI_RANGE | |||
1977 | && vr1type == VR_ANTI_RANGE) | |||
1978 | goto give_up; | |||
1979 | else if (*vr0type == VR_ANTI_RANGE | |||
1980 | && vr1type == VR_RANGE) | |||
1981 | ; | |||
1982 | else if (*vr0type == VR_RANGE | |||
1983 | && vr1type == VR_ANTI_RANGE) | |||
1984 | { | |||
1985 | *vr0type = vr1type; | |||
1986 | *vr0min = vr1min; | |||
1987 | *vr0max = vr1max; | |||
1988 | } | |||
1989 | else if (*vr0type == VR_RANGE | |||
1990 | && vr1type == VR_RANGE) | |||
1991 | { | |||
1992 | /* The result is the convex hull of both ranges. */ | |||
1993 | if (operand_less_p (*vr0max, vr1min) == 1) | |||
1994 | { | |||
1995 | /* If the result can be an anti-range, create one. */ | |||
1996 | if (TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) == INTEGER_CST | |||
1997 | && TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST | |||
1998 | && vrp_val_is_min (*vr0min) | |||
1999 | && vrp_val_is_max (vr1max)) | |||
2000 | { | |||
2001 | tree min = int_const_binop (PLUS_EXPR, | |||
2002 | *vr0max, | |||
2003 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2003, __FUNCTION__))->typed.type), 1)); | |||
2004 | tree max = int_const_binop (MINUS_EXPR, | |||
2005 | vr1min, | |||
2006 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2006, __FUNCTION__))->typed.type), 1)); | |||
2007 | if (!operand_less_p (max, min)) | |||
2008 | { | |||
2009 | *vr0type = VR_ANTI_RANGE; | |||
2010 | *vr0min = min; | |||
2011 | *vr0max = max; | |||
2012 | } | |||
2013 | else | |||
2014 | *vr0max = vr1max; | |||
2015 | } | |||
2016 | else | |||
2017 | *vr0max = vr1max; | |||
2018 | } | |||
2019 | else | |||
2020 | { | |||
2021 | /* If the result can be an anti-range, create one. */ | |||
2022 | if (TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST | |||
2023 | && TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) == INTEGER_CST | |||
2024 | && vrp_val_is_min (vr1min) | |||
2025 | && vrp_val_is_max (*vr0max)) | |||
2026 | { | |||
2027 | tree min = int_const_binop (PLUS_EXPR, | |||
2028 | vr1max, | |||
2029 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2029, __FUNCTION__))->typed.type), 1)); | |||
2030 | tree max = int_const_binop (MINUS_EXPR, | |||
2031 | *vr0min, | |||
2032 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2032, __FUNCTION__))->typed.type), 1)); | |||
2033 | if (!operand_less_p (max, min)) | |||
2034 | { | |||
2035 | *vr0type = VR_ANTI_RANGE; | |||
2036 | *vr0min = min; | |||
2037 | *vr0max = max; | |||
2038 | } | |||
2039 | else | |||
2040 | *vr0min = vr1min; | |||
2041 | } | |||
2042 | else | |||
2043 | *vr0min = vr1min; | |||
2044 | } | |||
2045 | } | |||
2046 | else | |||
2047 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2047, __FUNCTION__)); | |||
2048 | } | |||
2049 | else if ((maxeq || cmpmax == 1) | |||
2050 | && (mineq || cmpmin == -1)) | |||
2051 | { | |||
2052 | /* [ ( ) ] or [( ) ] or [ ( )] */ | |||
2053 | if (*vr0type == VR_RANGE | |||
2054 | && vr1type == VR_RANGE) | |||
2055 | ; | |||
2056 | else if (*vr0type == VR_ANTI_RANGE | |||
2057 | && vr1type == VR_ANTI_RANGE) | |||
2058 | { | |||
2059 | *vr0type = vr1type; | |||
2060 | *vr0min = vr1min; | |||
2061 | *vr0max = vr1max; | |||
2062 | } | |||
2063 | else if (*vr0type == VR_ANTI_RANGE | |||
2064 | && vr1type == VR_RANGE) | |||
2065 | { | |||
2066 | /* Arbitrarily choose the right or left gap. */ | |||
2067 | if (!mineq && TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST) | |||
2068 | *vr0max = int_const_binop (MINUS_EXPR, vr1min, | |||
2069 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2069, __FUNCTION__))->typed.type), 1)); | |||
2070 | else if (!maxeq && TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST) | |||
2071 | *vr0min = int_const_binop (PLUS_EXPR, vr1max, | |||
2072 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2072, __FUNCTION__))->typed.type), 1)); | |||
2073 | else | |||
2074 | goto give_up; | |||
2075 | } | |||
2076 | else if (*vr0type == VR_RANGE | |||
2077 | && vr1type == VR_ANTI_RANGE) | |||
2078 | /* The result covers everything. */ | |||
2079 | goto give_up; | |||
2080 | else | |||
2081 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2081, __FUNCTION__)); | |||
2082 | } | |||
2083 | else if ((maxeq || cmpmax == -1) | |||
2084 | && (mineq || cmpmin == 1)) | |||
2085 | { | |||
2086 | /* ( [ ] ) or ([ ] ) or ( [ ]) */ | |||
2087 | if (*vr0type == VR_RANGE | |||
2088 | && vr1type == VR_RANGE) | |||
2089 | { | |||
2090 | *vr0type = vr1type; | |||
2091 | *vr0min = vr1min; | |||
2092 | *vr0max = vr1max; | |||
2093 | } | |||
2094 | else if (*vr0type == VR_ANTI_RANGE | |||
2095 | && vr1type == VR_ANTI_RANGE) | |||
2096 | ; | |||
2097 | else if (*vr0type == VR_RANGE | |||
2098 | && vr1type == VR_ANTI_RANGE) | |||
2099 | { | |||
2100 | *vr0type = VR_ANTI_RANGE; | |||
2101 | if (!mineq && TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) == INTEGER_CST) | |||
2102 | { | |||
2103 | *vr0max = int_const_binop (MINUS_EXPR, *vr0min, | |||
2104 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2104, __FUNCTION__))->typed.type), 1)); | |||
2105 | *vr0min = vr1min; | |||
2106 | } | |||
2107 | else if (!maxeq && TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) == INTEGER_CST) | |||
2108 | { | |||
2109 | *vr0min = int_const_binop (PLUS_EXPR, *vr0max, | |||
2110 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2110, __FUNCTION__))->typed.type), 1)); | |||
2111 | *vr0max = vr1max; | |||
2112 | } | |||
2113 | else | |||
2114 | goto give_up; | |||
2115 | } | |||
2116 | else if (*vr0type == VR_ANTI_RANGE | |||
2117 | && vr1type == VR_RANGE) | |||
2118 | /* The result covers everything. */ | |||
2119 | goto give_up; | |||
2120 | else | |||
2121 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2121, __FUNCTION__)); | |||
2122 | } | |||
2123 | else if (cmpmin == -1 | |||
2124 | && cmpmax == -1 | |||
2125 | && (operand_less_p (vr1min, *vr0max) == 1 | |||
2126 | || operand_equal_p (vr1min, *vr0max, 0))) | |||
2127 | { | |||
2128 | /* [ ( ] ) or [ ]( ) */ | |||
2129 | if (*vr0type == VR_RANGE | |||
2130 | && vr1type == VR_RANGE) | |||
2131 | *vr0max = vr1max; | |||
2132 | else if (*vr0type == VR_ANTI_RANGE | |||
2133 | && vr1type == VR_ANTI_RANGE) | |||
2134 | *vr0min = vr1min; | |||
2135 | else if (*vr0type == VR_ANTI_RANGE | |||
2136 | && vr1type == VR_RANGE) | |||
2137 | { | |||
2138 | if (TREE_CODE (vr1min)((enum tree_code) (vr1min)->base.code) == INTEGER_CST) | |||
2139 | *vr0max = int_const_binop (MINUS_EXPR, vr1min, | |||
2140 | build_int_cst (TREE_TYPE (vr1min)((contains_struct_check ((vr1min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2140, __FUNCTION__))->typed.type), 1)); | |||
2141 | else | |||
2142 | goto give_up; | |||
2143 | } | |||
2144 | else if (*vr0type == VR_RANGE | |||
2145 | && vr1type == VR_ANTI_RANGE) | |||
2146 | { | |||
2147 | if (TREE_CODE (*vr0max)((enum tree_code) (*vr0max)->base.code) == INTEGER_CST) | |||
2148 | { | |||
2149 | *vr0type = vr1type; | |||
2150 | *vr0min = int_const_binop (PLUS_EXPR, *vr0max, | |||
2151 | build_int_cst (TREE_TYPE (*vr0max)((contains_struct_check ((*vr0max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2151, __FUNCTION__))->typed.type), 1)); | |||
2152 | *vr0max = vr1max; | |||
2153 | } | |||
2154 | else | |||
2155 | goto give_up; | |||
2156 | } | |||
2157 | else | |||
2158 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2158, __FUNCTION__)); | |||
2159 | } | |||
2160 | else if (cmpmin == 1 | |||
2161 | && cmpmax == 1 | |||
2162 | && (operand_less_p (*vr0min, vr1max) == 1 | |||
2163 | || operand_equal_p (*vr0min, vr1max, 0))) | |||
2164 | { | |||
2165 | /* ( [ ) ] or ( )[ ] */ | |||
2166 | if (*vr0type == VR_RANGE | |||
2167 | && vr1type == VR_RANGE) | |||
2168 | *vr0min = vr1min; | |||
2169 | else if (*vr0type == VR_ANTI_RANGE | |||
2170 | && vr1type == VR_ANTI_RANGE) | |||
2171 | *vr0max = vr1max; | |||
2172 | else if (*vr0type == VR_ANTI_RANGE | |||
2173 | && vr1type == VR_RANGE) | |||
2174 | { | |||
2175 | if (TREE_CODE (vr1max)((enum tree_code) (vr1max)->base.code) == INTEGER_CST) | |||
2176 | *vr0min = int_const_binop (PLUS_EXPR, vr1max, | |||
2177 | build_int_cst (TREE_TYPE (vr1max)((contains_struct_check ((vr1max), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2177, __FUNCTION__))->typed.type), 1)); | |||
2178 | else | |||
2179 | goto give_up; | |||
2180 | } | |||
2181 | else if (*vr0type == VR_RANGE | |||
2182 | && vr1type == VR_ANTI_RANGE) | |||
2183 | { | |||
2184 | if (TREE_CODE (*vr0min)((enum tree_code) (*vr0min)->base.code) == INTEGER_CST) | |||
2185 | { | |||
2186 | *vr0type = vr1type; | |||
2187 | *vr0max = int_const_binop (MINUS_EXPR, *vr0min, | |||
2188 | build_int_cst (TREE_TYPE (*vr0min)((contains_struct_check ((*vr0min), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2188, __FUNCTION__))->typed.type), 1)); | |||
2189 | *vr0min = vr1min; | |||
2190 | } | |||
2191 | else | |||
2192 | goto give_up; | |||
2193 | } | |||
2194 | else | |||
2195 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2195, __FUNCTION__)); | |||
2196 | } | |||
2197 | else | |||
2198 | goto give_up; | |||
2199 | ||||
2200 | return; | |||
2201 | ||||
2202 | give_up: | |||
2203 | *vr0type = VR_VARYING; | |||
2204 | *vr0min = NULL_TREE(tree) nullptr; | |||
2205 | *vr0max = NULL_TREE(tree) nullptr; | |||
2206 | } | |||
2207 | ||||
2208 | /* Helper for meet operation for value ranges. Given two ranges VR0 | |||
2209 | and VR1, set VR0 to the union of both ranges. This may not be the | |||
2210 | smallest possible such range. */ | |||
2211 | ||||
2212 | void | |||
2213 | irange::legacy_union (irange *vr0, const irange *vr1) | |||
2214 | { | |||
2215 | gcc_checking_assert (vr0->legacy_mode_p ())((void)(!(vr0->legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2215, __FUNCTION__), 0 : 0)); | |||
2216 | gcc_checking_assert (vr1->legacy_mode_p ())((void)(!(vr1->legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2216, __FUNCTION__), 0 : 0)); | |||
2217 | ||||
2218 | /* VR0 has the resulting range if VR1 is undefined or VR0 is varying. */ | |||
2219 | if (vr1->undefined_p () | |||
2220 | || vr0->varying_p ()) | |||
2221 | return; | |||
2222 | ||||
2223 | /* VR1 has the resulting range if VR0 is undefined or VR1 is varying. */ | |||
2224 | if (vr0->undefined_p ()) | |||
2225 | { | |||
2226 | vr0->set (vr1->min (), vr1->max (), vr1->kind ()); | |||
2227 | return; | |||
2228 | } | |||
2229 | ||||
2230 | if (vr1->varying_p ()) | |||
2231 | { | |||
2232 | vr0->set_varying (vr1->type ()); | |||
2233 | return; | |||
2234 | } | |||
2235 | ||||
2236 | value_range_kind vr0kind = vr0->kind (); | |||
2237 | tree vr0min = vr0->min (); | |||
2238 | tree vr0max = vr0->max (); | |||
2239 | ||||
2240 | union_ranges (&vr0kind, &vr0min, &vr0max, | |||
2241 | vr1->kind (), vr1->min (), vr1->max ()); | |||
2242 | ||||
2243 | if (vr0kind == VR_UNDEFINED) | |||
2244 | vr0->set_undefined (); | |||
2245 | else if (vr0kind == VR_VARYING) | |||
2246 | { | |||
2247 | /* Failed to find an efficient meet. Before giving up and | |||
2248 | setting the result to VARYING, see if we can at least derive | |||
2249 | a non-zero range. */ | |||
2250 | if (range_includes_zero_p (vr0) == 0 | |||
2251 | && range_includes_zero_p (vr1) == 0) | |||
2252 | vr0->set_nonzero (vr0->type ()); | |||
2253 | else | |||
2254 | vr0->set_varying (vr0->type ()); | |||
2255 | } | |||
2256 | else | |||
2257 | vr0->set (vr0min, vr0max, vr0kind); | |||
2258 | } | |||
2259 | ||||
2260 | /* Meet operation for value ranges. Given two value ranges VR0 and | |||
2261 | VR1, store in VR0 a range that contains both VR0 and VR1. This | |||
2262 | may not be the smallest possible such range. | |||
2263 | Return TRUE if the original value changes. */ | |||
2264 | ||||
2265 | bool | |||
2266 | irange::legacy_verbose_union_ (const irange *other) | |||
2267 | { | |||
2268 | if (legacy_mode_p ()) | |||
2269 | { | |||
2270 | if (!other->legacy_mode_p ()) | |||
2271 | { | |||
2272 | int_range<1> tmp = *other; | |||
2273 | legacy_union (this, &tmp); | |||
2274 | return true; | |||
2275 | } | |||
2276 | if (dump_file && (dump_flags & TDF_DETAILS)) | |||
2277 | { | |||
2278 | fprintf (dump_file, "Meeting\n "); | |||
2279 | dump_value_range (dump_file, this); | |||
2280 | fprintf (dump_file, "\nand\n "); | |||
2281 | dump_value_range (dump_file, other); | |||
2282 | fprintf (dump_file, "\n"); | |||
2283 | } | |||
2284 | ||||
2285 | legacy_union (this, other); | |||
2286 | ||||
2287 | if (dump_file && (dump_flags & TDF_DETAILS)) | |||
2288 | { | |||
2289 | fprintf (dump_file, "to\n "); | |||
2290 | dump_value_range (dump_file, this); | |||
2291 | fprintf (dump_file, "\n"); | |||
2292 | } | |||
2293 | return true; | |||
2294 | } | |||
2295 | ||||
2296 | if (other->legacy_mode_p ()) | |||
2297 | { | |||
2298 | int_range<2> wider = *other; | |||
2299 | return irange_union (wider); | |||
2300 | } | |||
2301 | else | |||
2302 | return irange_union (*other); | |||
2303 | } | |||
2304 | ||||
2305 | bool | |||
2306 | irange::legacy_verbose_intersect (const irange *other) | |||
2307 | { | |||
2308 | if (legacy_mode_p ()) | |||
2309 | { | |||
2310 | if (!other->legacy_mode_p ()) | |||
2311 | { | |||
2312 | int_range<1> tmp = *other; | |||
2313 | legacy_intersect (this, &tmp); | |||
2314 | return true; | |||
2315 | } | |||
2316 | if (dump_file && (dump_flags & TDF_DETAILS)) | |||
2317 | { | |||
2318 | fprintf (dump_file, "Intersecting\n "); | |||
2319 | dump_value_range (dump_file, this); | |||
2320 | fprintf (dump_file, "\nand\n "); | |||
2321 | dump_value_range (dump_file, other); | |||
2322 | fprintf (dump_file, "\n"); | |||
2323 | } | |||
2324 | ||||
2325 | legacy_intersect (this, other); | |||
2326 | ||||
2327 | if (dump_file && (dump_flags & TDF_DETAILS)) | |||
2328 | { | |||
2329 | fprintf (dump_file, "to\n "); | |||
2330 | dump_value_range (dump_file, this); | |||
2331 | fprintf (dump_file, "\n"); | |||
2332 | } | |||
2333 | return true; | |||
2334 | } | |||
2335 | ||||
2336 | if (other->legacy_mode_p ()) | |||
2337 | { | |||
2338 | int_range<2> wider; | |||
2339 | wider = *other; | |||
2340 | return irange_intersect (wider); | |||
2341 | } | |||
2342 | else | |||
2343 | return irange_intersect (*other); | |||
2344 | } | |||
2345 | ||||
2346 | // Perform an efficient union with R when both ranges have only a single pair. | |||
2347 | // Excluded are VARYING and UNDEFINED ranges. | |||
2348 | ||||
2349 | bool | |||
2350 | irange::irange_single_pair_union (const irange &r) | |||
2351 | { | |||
2352 | gcc_checking_assert (!undefined_p () && !varying_p ())((void)(!(!undefined_p () && !varying_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2352, __FUNCTION__), 0 : 0)); | |||
2353 | gcc_checking_assert (!r.undefined_p () && !varying_p ())((void)(!(!r.undefined_p () && !varying_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2353, __FUNCTION__), 0 : 0)); | |||
2354 | ||||
2355 | signop sign = TYPE_SIGN (TREE_TYPE (m_base[0]))((signop) ((tree_class_check ((((contains_struct_check ((m_base [0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2355, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2355, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
2356 | // Check if current lower bound is also the new lower bound. | |||
2357 | if (wi::le_p (wi::to_wide (m_base[0]), wi::to_wide (r.m_base[0]), sign)) | |||
2358 | { | |||
2359 | // If current upper bound is new upper bound, we're done. | |||
2360 | if (wi::le_p (wi::to_wide (r.m_base[1]), wi::to_wide (m_base[1]), sign)) | |||
2361 | return union_nonzero_bits (r); | |||
2362 | // Otherwise R has the new upper bound. | |||
2363 | // Check for overlap/touching ranges, or single target range. | |||
2364 | if (m_max_ranges == 1 | |||
2365 | || wi::to_widest (m_base[1]) + 1 >= wi::to_widest (r.m_base[0])) | |||
2366 | m_base[1] = r.m_base[1]; | |||
2367 | else | |||
2368 | { | |||
2369 | // This is a dual range result. | |||
2370 | m_base[2] = r.m_base[0]; | |||
2371 | m_base[3] = r.m_base[1]; | |||
2372 | m_num_ranges = 2; | |||
2373 | } | |||
2374 | union_nonzero_bits (r); | |||
2375 | return true; | |||
2376 | } | |||
2377 | ||||
2378 | // Set the new lower bound to R's lower bound. | |||
2379 | tree lb = m_base[0]; | |||
2380 | m_base[0] = r.m_base[0]; | |||
2381 | ||||
2382 | // If R fully contains THIS range, just set the upper bound. | |||
2383 | if (wi::ge_p (wi::to_wide (r.m_base[1]), wi::to_wide (m_base[1]), sign)) | |||
2384 | m_base[1] = r.m_base[1]; | |||
2385 | // Check for overlapping ranges, or target limited to a single range. | |||
2386 | else if (m_max_ranges == 1 | |||
2387 | || wi::to_widest (r.m_base[1]) + 1 >= wi::to_widest (lb)) | |||
2388 | ; | |||
2389 | else | |||
2390 | { | |||
2391 | // Left with 2 pairs. | |||
2392 | m_num_ranges = 2; | |||
2393 | m_base[2] = lb; | |||
2394 | m_base[3] = m_base[1]; | |||
2395 | m_base[1] = r.m_base[1]; | |||
2396 | } | |||
2397 | union_nonzero_bits (r); | |||
2398 | return true; | |||
2399 | } | |||
2400 | ||||
2401 | // union_ for multi-ranges. | |||
2402 | ||||
2403 | bool | |||
2404 | irange::irange_union (const irange &r) | |||
2405 | { | |||
2406 | gcc_checking_assert (!legacy_mode_p () && !r.legacy_mode_p ())((void)(!(!legacy_mode_p () && !r.legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2406, __FUNCTION__), 0 : 0)); | |||
2407 | ||||
2408 | if (r.undefined_p ()) | |||
2409 | return false; | |||
2410 | ||||
2411 | if (undefined_p ()) | |||
2412 | { | |||
2413 | operator= (r); | |||
2414 | if (flag_checkingglobal_options.x_flag_checking) | |||
2415 | verify_range (); | |||
2416 | return true; | |||
2417 | } | |||
2418 | ||||
2419 | if (varying_p ()) | |||
2420 | return false; | |||
2421 | ||||
2422 | if (r.varying_p ()) | |||
2423 | { | |||
2424 | set_varying (type ()); | |||
2425 | return true; | |||
2426 | } | |||
2427 | ||||
2428 | // Special case one range union one range. | |||
2429 | if (m_num_ranges == 1 && r.m_num_ranges == 1) | |||
2430 | return irange_single_pair_union (r); | |||
2431 | ||||
2432 | // If this ranges fully contains R, then we need do nothing. | |||
2433 | if (irange_contains_p (r)) | |||
2434 | return union_nonzero_bits (r); | |||
2435 | ||||
2436 | // Do not worry about merging and such by reserving twice as many | |||
2437 | // pairs as needed, and then simply sort the 2 ranges into this | |||
2438 | // intermediate form. | |||
2439 | // | |||
2440 | // The intermediate result will have the property that the beginning | |||
2441 | // of each range is <= the beginning of the next range. There may | |||
2442 | // be overlapping ranges at this point. I.e. this would be valid | |||
2443 | // [-20, 10], [-10, 0], [0, 20], [40, 90] as it satisfies this | |||
2444 | // constraint : -20 < -10 < 0 < 40. When the range is rebuilt into r, | |||
2445 | // the merge is performed. | |||
2446 | // | |||
2447 | // [Xi,Yi]..[Xn,Yn] U [Xj,Yj]..[Xm,Ym] --> [Xk,Yk]..[Xp,Yp] | |||
2448 | auto_vec<tree, 20> res (m_num_ranges * 2 + r.m_num_ranges * 2); | |||
2449 | unsigned i = 0, j = 0, k = 0; | |||
2450 | ||||
2451 | while (i < m_num_ranges * 2 && j < r.m_num_ranges * 2) | |||
2452 | { | |||
2453 | // lower of Xi and Xj is the lowest point. | |||
2454 | if (wi::to_widest (m_base[i]) <= wi::to_widest (r.m_base[j])) | |||
2455 | { | |||
2456 | res.quick_push (m_base[i]); | |||
2457 | res.quick_push (m_base[i + 1]); | |||
2458 | k += 2; | |||
2459 | i += 2; | |||
2460 | } | |||
2461 | else | |||
2462 | { | |||
2463 | res.quick_push (r.m_base[j]); | |||
2464 | res.quick_push (r.m_base[j + 1]); | |||
2465 | k += 2; | |||
2466 | j += 2; | |||
2467 | } | |||
2468 | } | |||
2469 | for ( ; i < m_num_ranges * 2; i += 2) | |||
2470 | { | |||
2471 | res.quick_push (m_base[i]); | |||
2472 | res.quick_push (m_base[i + 1]); | |||
2473 | k += 2; | |||
2474 | } | |||
2475 | for ( ; j < r.m_num_ranges * 2; j += 2) | |||
2476 | { | |||
2477 | res.quick_push (r.m_base[j]); | |||
2478 | res.quick_push (r.m_base[j + 1]); | |||
2479 | k += 2; | |||
2480 | } | |||
2481 | ||||
2482 | // Now normalize the vector removing any overlaps. | |||
2483 | i = 2; | |||
2484 | for (j = 2; j < k ; j += 2) | |||
2485 | { | |||
2486 | // Current upper+1 is >= lower bound next pair, then we merge ranges. | |||
2487 | if (wi::to_widest (res[i - 1]) + 1 >= wi::to_widest (res[j])) | |||
2488 | { | |||
2489 | // New upper bounds is greater of current or the next one. | |||
2490 | if (wi::to_widest (res[j + 1]) > wi::to_widest (res[i - 1])) | |||
2491 | res[i - 1] = res[j + 1]; | |||
2492 | } | |||
2493 | else | |||
2494 | { | |||
2495 | // This is a new distinct range, but no point in copying it | |||
2496 | // if it is already in the right place. | |||
2497 | if (i != j) | |||
2498 | { | |||
2499 | res[i++] = res[j]; | |||
2500 | res[i++] = res[j + 1]; | |||
2501 | } | |||
2502 | else | |||
2503 | i += 2; | |||
2504 | } | |||
2505 | } | |||
2506 | ||||
2507 | // At this point, the vector should have i ranges, none overlapping. | |||
2508 | // Now it simply needs to be copied, and if there are too many | |||
2509 | // ranges, merge some. We wont do any analysis as to what the | |||
2510 | // "best" merges are, simply combine the final ranges into one. | |||
2511 | if (i > m_max_ranges * 2) | |||
2512 | { | |||
2513 | res[m_max_ranges * 2 - 1] = res[i - 1]; | |||
2514 | i = m_max_ranges * 2; | |||
2515 | } | |||
2516 | ||||
2517 | for (j = 0; j < i ; j++) | |||
2518 | m_base[j] = res [j]; | |||
2519 | m_num_ranges = i / 2; | |||
2520 | ||||
2521 | m_kind = VR_RANGE; | |||
2522 | union_nonzero_bits (r); | |||
2523 | return true; | |||
2524 | } | |||
2525 | ||||
2526 | // Return TRUE if THIS fully contains R. No undefined or varying cases. | |||
2527 | ||||
2528 | bool | |||
2529 | irange::irange_contains_p (const irange &r) const | |||
2530 | { | |||
2531 | gcc_checking_assert (!undefined_p () && !varying_p ())((void)(!(!undefined_p () && !varying_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2531, __FUNCTION__), 0 : 0)); | |||
2532 | gcc_checking_assert (!r.undefined_p () && !varying_p ())((void)(!(!r.undefined_p () && !varying_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2532, __FUNCTION__), 0 : 0)); | |||
2533 | ||||
2534 | // In order for THIS to fully contain R, all of the pairs within R must | |||
2535 | // be fully contained by the pairs in this object. | |||
2536 | signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]))((signop) ((tree_class_check ((((contains_struct_check ((m_base [0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2536, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2536, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
2537 | unsigned ri = 0; | |||
2538 | unsigned i = 0; | |||
2539 | tree rl = r.m_base[0]; | |||
2540 | tree ru = r.m_base[1]; | |||
2541 | tree l = m_base[0]; | |||
2542 | tree u = m_base[1]; | |||
2543 | while (1) | |||
2544 | { | |||
2545 | // If r is contained within this range, move to the next R | |||
2546 | if (wi::ge_p (wi::to_wide (rl), wi::to_wide (l), sign) | |||
2547 | && wi::le_p (wi::to_wide (ru), wi::to_wide (u), sign)) | |||
2548 | { | |||
2549 | // This pair is OK, Either done, or bump to the next. | |||
2550 | if (++ri >= r.num_pairs ()) | |||
2551 | return true; | |||
2552 | rl = r.m_base[ri * 2]; | |||
2553 | ru = r.m_base[ri * 2 + 1]; | |||
2554 | continue; | |||
2555 | } | |||
2556 | // Otherwise, check if this's pair occurs before R's. | |||
2557 | if (wi::lt_p (wi::to_wide (u), wi::to_wide (rl), sign)) | |||
2558 | { | |||
2559 | // There's still at least one pair of R left. | |||
2560 | if (++i >= num_pairs ()) | |||
2561 | return false; | |||
2562 | l = m_base[i * 2]; | |||
2563 | u = m_base[i * 2 + 1]; | |||
2564 | continue; | |||
2565 | } | |||
2566 | return false; | |||
2567 | } | |||
2568 | return false; | |||
2569 | } | |||
2570 | ||||
2571 | ||||
2572 | // Intersect for multi-ranges. Return TRUE if anything changes. | |||
2573 | ||||
2574 | bool | |||
2575 | irange::irange_intersect (const irange &r) | |||
2576 | { | |||
2577 | gcc_checking_assert (!legacy_mode_p () && !r.legacy_mode_p ())((void)(!(!legacy_mode_p () && !r.legacy_mode_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2577, __FUNCTION__), 0 : 0)); | |||
2578 | gcc_checking_assert (undefined_p () || r.undefined_p ()((void)(!(undefined_p () || r.undefined_p () || range_compatible_p (type (), r.type ())) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2579, __FUNCTION__), 0 : 0)) | |||
2579 | || range_compatible_p (type (), r.type ()))((void)(!(undefined_p () || r.undefined_p () || range_compatible_p (type (), r.type ())) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2579, __FUNCTION__), 0 : 0)); | |||
2580 | ||||
2581 | if (undefined_p ()) | |||
2582 | return false; | |||
2583 | if (r.undefined_p ()) | |||
2584 | { | |||
2585 | set_undefined (); | |||
2586 | return true; | |||
2587 | } | |||
2588 | if (r.varying_p ()) | |||
2589 | return false; | |||
2590 | if (varying_p ()) | |||
2591 | { | |||
2592 | operator= (r); | |||
2593 | return true; | |||
2594 | } | |||
2595 | ||||
2596 | if (r.num_pairs () == 1) | |||
2597 | { | |||
2598 | bool res = intersect (r.lower_bound (), r.upper_bound ()); | |||
2599 | if (undefined_p ()) | |||
2600 | return true; | |||
2601 | ||||
2602 | res |= intersect_nonzero_bits (r); | |||
2603 | return res; | |||
2604 | } | |||
2605 | ||||
2606 | // If R fully contains this, then intersection will change nothing. | |||
2607 | if (r.irange_contains_p (*this)) | |||
2608 | return intersect_nonzero_bits (r); | |||
2609 | ||||
2610 | signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]))((signop) ((tree_class_check ((((contains_struct_check ((m_base [0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2610, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2610, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
2611 | unsigned bld_pair = 0; | |||
2612 | unsigned bld_lim = m_max_ranges; | |||
2613 | int_range_max r2 (*this); | |||
2614 | unsigned r2_lim = r2.num_pairs (); | |||
2615 | unsigned i2 = 0; | |||
2616 | for (unsigned i = 0; i < r.num_pairs (); ) | |||
2617 | { | |||
2618 | // If r1's upper is < r2's lower, we can skip r1's pair. | |||
2619 | tree ru = r.m_base[i * 2 + 1]; | |||
2620 | tree r2l = r2.m_base[i2 * 2]; | |||
2621 | if (wi::lt_p (wi::to_wide (ru), wi::to_wide (r2l), sign)) | |||
2622 | { | |||
2623 | i++; | |||
2624 | continue; | |||
2625 | } | |||
2626 | // Likewise, skip r2's pair if its excluded. | |||
2627 | tree r2u = r2.m_base[i2 * 2 + 1]; | |||
2628 | tree rl = r.m_base[i * 2]; | |||
2629 | if (wi::lt_p (wi::to_wide (r2u), wi::to_wide (rl), sign)) | |||
2630 | { | |||
2631 | i2++; | |||
2632 | if (i2 < r2_lim) | |||
2633 | continue; | |||
2634 | // No more r2, break. | |||
2635 | break; | |||
2636 | } | |||
2637 | ||||
2638 | // Must be some overlap. Find the highest of the lower bounds, | |||
2639 | // and set it, unless the build limits lower bounds is already | |||
2640 | // set. | |||
2641 | if (bld_pair < bld_lim) | |||
2642 | { | |||
2643 | if (wi::ge_p (wi::to_wide (rl), wi::to_wide (r2l), sign)) | |||
2644 | m_base[bld_pair * 2] = rl; | |||
2645 | else | |||
2646 | m_base[bld_pair * 2] = r2l; | |||
2647 | } | |||
2648 | else | |||
2649 | // Decrease and set a new upper. | |||
2650 | bld_pair--; | |||
2651 | ||||
2652 | // ...and choose the lower of the upper bounds. | |||
2653 | if (wi::le_p (wi::to_wide (ru), wi::to_wide (r2u), sign)) | |||
2654 | { | |||
2655 | m_base[bld_pair * 2 + 1] = ru; | |||
2656 | bld_pair++; | |||
2657 | // Move past the r1 pair and keep trying. | |||
2658 | i++; | |||
2659 | continue; | |||
2660 | } | |||
2661 | else | |||
2662 | { | |||
2663 | m_base[bld_pair * 2 + 1] = r2u; | |||
2664 | bld_pair++; | |||
2665 | i2++; | |||
2666 | if (i2 < r2_lim) | |||
2667 | continue; | |||
2668 | // No more r2, break. | |||
2669 | break; | |||
2670 | } | |||
2671 | // r2 has the higher lower bound. | |||
2672 | } | |||
2673 | ||||
2674 | // At the exit of this loop, it is one of 2 things: | |||
2675 | // ran out of r1, or r2, but either means we are done. | |||
2676 | m_num_ranges = bld_pair; | |||
2677 | if (m_num_ranges == 0) | |||
2678 | { | |||
2679 | set_undefined (); | |||
2680 | return true; | |||
2681 | } | |||
2682 | ||||
2683 | m_kind = VR_RANGE; | |||
2684 | intersect_nonzero_bits (r); | |||
2685 | return true; | |||
2686 | } | |||
2687 | ||||
2688 | ||||
2689 | // Multirange intersect for a specified wide_int [lb, ub] range. | |||
2690 | // Return TRUE if intersect changed anything. | |||
2691 | // | |||
2692 | // NOTE: It is the caller's responsibility to intersect the nonzero masks. | |||
2693 | ||||
2694 | bool | |||
2695 | irange::intersect (const wide_int& lb, const wide_int& ub) | |||
2696 | { | |||
2697 | // Undefined remains undefined. | |||
2698 | if (undefined_p ()) | |||
2699 | return false; | |||
2700 | ||||
2701 | if (legacy_mode_p ()) | |||
2702 | { | |||
2703 | intersect (int_range<1> (type (), lb, ub)); | |||
2704 | return true; | |||
2705 | } | |||
2706 | ||||
2707 | tree range_type = type(); | |||
2708 | signop sign = TYPE_SIGN (range_type)((signop) ((tree_class_check ((range_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2708, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
2709 | ||||
2710 | gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (lb))((void)(!(((tree_class_check ((range_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2710, __FUNCTION__))->type_common.precision) == wi::get_precision (lb)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2710, __FUNCTION__), 0 : 0)); | |||
2711 | gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (ub))((void)(!(((tree_class_check ((range_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2711, __FUNCTION__))->type_common.precision) == wi::get_precision (ub)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2711, __FUNCTION__), 0 : 0)); | |||
2712 | ||||
2713 | // If this range is fully contained, then intersection will do nothing. | |||
2714 | if (wi::ge_p (lower_bound (), lb, sign) | |||
2715 | && wi::le_p (upper_bound (), ub, sign)) | |||
2716 | return false; | |||
2717 | ||||
2718 | unsigned bld_index = 0; | |||
2719 | unsigned pair_lim = num_pairs (); | |||
2720 | for (unsigned i = 0; i < pair_lim; i++) | |||
2721 | { | |||
2722 | tree pairl = m_base[i * 2]; | |||
2723 | tree pairu = m_base[i * 2 + 1]; | |||
2724 | // Once UB is less than a pairs lower bound, we're done. | |||
2725 | if (wi::lt_p (ub, wi::to_wide (pairl), sign)) | |||
2726 | break; | |||
2727 | // if LB is greater than this pairs upper, this pair is excluded. | |||
2728 | if (wi::lt_p (wi::to_wide (pairu), lb, sign)) | |||
2729 | continue; | |||
2730 | ||||
2731 | // Must be some overlap. Find the highest of the lower bounds, | |||
2732 | // and set it | |||
2733 | if (wi::gt_p (lb, wi::to_wide (pairl), sign)) | |||
2734 | m_base[bld_index * 2] = wide_int_to_tree (range_type, lb); | |||
2735 | else | |||
2736 | m_base[bld_index * 2] = pairl; | |||
2737 | ||||
2738 | // ...and choose the lower of the upper bounds and if the base pair | |||
2739 | // has the lower upper bound, need to check next pair too. | |||
2740 | if (wi::lt_p (ub, wi::to_wide (pairu), sign)) | |||
2741 | { | |||
2742 | m_base[bld_index++ * 2 + 1] = wide_int_to_tree (range_type, ub); | |||
2743 | break; | |||
2744 | } | |||
2745 | else | |||
2746 | m_base[bld_index++ * 2 + 1] = pairu; | |||
2747 | } | |||
2748 | ||||
2749 | m_num_ranges = bld_index; | |||
2750 | if (m_num_ranges == 0) | |||
2751 | { | |||
2752 | set_undefined (); | |||
2753 | return true; | |||
2754 | } | |||
2755 | ||||
2756 | m_kind = VR_RANGE; | |||
2757 | // No need to call normalize_kind(), as the caller will do this | |||
2758 | // while intersecting the nonzero mask. | |||
2759 | if (flag_checkingglobal_options.x_flag_checking) | |||
2760 | verify_range (); | |||
2761 | return true; | |||
2762 | } | |||
2763 | ||||
2764 | ||||
2765 | // Signed 1-bits are strange. You can't subtract 1, because you can't | |||
2766 | // represent the number 1. This works around that for the invert routine. | |||
2767 | ||||
2768 | static wide_int inline | |||
2769 | subtract_one (const wide_int &x, tree type, wi::overflow_type &overflow) | |||
2770 | { | |||
2771 | if (TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2771, __FUNCTION__))->base.u.bits.unsigned_flag)) == SIGNED) | |||
2772 | return wi::add (x, -1, SIGNED, &overflow); | |||
2773 | else | |||
2774 | return wi::sub (x, 1, UNSIGNED, &overflow); | |||
2775 | } | |||
2776 | ||||
2777 | // The analogous function for adding 1. | |||
2778 | ||||
2779 | static wide_int inline | |||
2780 | add_one (const wide_int &x, tree type, wi::overflow_type &overflow) | |||
2781 | { | |||
2782 | if (TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2782, __FUNCTION__))->base.u.bits.unsigned_flag)) == SIGNED) | |||
2783 | return wi::sub (x, -1, SIGNED, &overflow); | |||
2784 | else | |||
2785 | return wi::add (x, 1, UNSIGNED, &overflow); | |||
2786 | } | |||
2787 | ||||
2788 | // Return the inverse of a range. | |||
2789 | ||||
2790 | void | |||
2791 | irange::invert () | |||
2792 | { | |||
2793 | if (legacy_mode_p ()) | |||
2794 | { | |||
2795 | // We can't just invert VR_RANGE and VR_ANTI_RANGE because we may | |||
2796 | // create non-canonical ranges. Use the constructors instead. | |||
2797 | if (m_kind == VR_RANGE) | |||
2798 | *this = value_range (min (), max (), VR_ANTI_RANGE); | |||
2799 | else if (m_kind == VR_ANTI_RANGE) | |||
2800 | *this = value_range (min (), max ()); | |||
2801 | else | |||
2802 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2802, __FUNCTION__)); | |||
2803 | return; | |||
2804 | } | |||
2805 | ||||
2806 | gcc_checking_assert (!undefined_p () && !varying_p ())((void)(!(!undefined_p () && !varying_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2806, __FUNCTION__), 0 : 0)); | |||
2807 | ||||
2808 | // We always need one more set of bounds to represent an inverse, so | |||
2809 | // if we're at the limit, we can't properly represent things. | |||
2810 | // | |||
2811 | // For instance, to represent the inverse of a 2 sub-range set | |||
2812 | // [5, 10][20, 30], we would need a 3 sub-range set | |||
2813 | // [-MIN, 4][11, 19][31, MAX]. | |||
2814 | // | |||
2815 | // In this case, return the most conservative thing. | |||
2816 | // | |||
2817 | // However, if any of the extremes of the range are -MIN/+MAX, we | |||
2818 | // know we will not need an extra bound. For example: | |||
2819 | // | |||
2820 | // INVERT([-MIN,20][30,40]) => [21,29][41,+MAX] | |||
2821 | // INVERT([-MIN,20][30,MAX]) => [21,29] | |||
2822 | tree ttype = type (); | |||
2823 | unsigned prec = TYPE_PRECISION (ttype)((tree_class_check ((ttype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2823, __FUNCTION__))->type_common.precision); | |||
2824 | signop sign = TYPE_SIGN (ttype)((signop) ((tree_class_check ((ttype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2824, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
2825 | wide_int type_min = wi::min_value (prec, sign); | |||
2826 | wide_int type_max = wi::max_value (prec, sign); | |||
2827 | m_nonzero_mask = NULLnullptr; | |||
2828 | if (m_num_ranges == m_max_ranges | |||
2829 | && lower_bound () != type_min | |||
2830 | && upper_bound () != type_max) | |||
2831 | { | |||
2832 | m_base[1] = wide_int_to_tree (ttype, type_max); | |||
2833 | m_num_ranges = 1; | |||
2834 | return; | |||
2835 | } | |||
2836 | // The algorithm is as follows. To calculate INVERT ([a,b][c,d]), we | |||
2837 | // generate [-MIN, a-1][b+1, c-1][d+1, MAX]. | |||
2838 | // | |||
2839 | // If there is an over/underflow in the calculation for any | |||
2840 | // sub-range, we eliminate that subrange. This allows us to easily | |||
2841 | // calculate INVERT([-MIN, 5]) with: [-MIN, -MIN-1][6, MAX]. And since | |||
2842 | // we eliminate the underflow, only [6, MAX] remains. | |||
2843 | unsigned i = 0; | |||
2844 | wi::overflow_type ovf; | |||
2845 | // Construct leftmost range. | |||
2846 | int_range_max orig_range (*this); | |||
2847 | unsigned nitems = 0; | |||
2848 | wide_int tmp; | |||
2849 | // If this is going to underflow on the MINUS 1, don't even bother | |||
2850 | // checking. This also handles subtracting one from an unsigned 0, | |||
2851 | // which doesn't set the underflow bit. | |||
2852 | if (type_min != orig_range.lower_bound ()) | |||
2853 | { | |||
2854 | m_base[nitems++] = wide_int_to_tree (ttype, type_min); | |||
2855 | tmp = subtract_one (orig_range.lower_bound (), ttype, ovf); | |||
2856 | m_base[nitems++] = wide_int_to_tree (ttype, tmp); | |||
2857 | if (ovf) | |||
2858 | nitems = 0; | |||
2859 | } | |||
2860 | i++; | |||
2861 | // Construct middle ranges if applicable. | |||
2862 | if (orig_range.num_pairs () > 1) | |||
2863 | { | |||
2864 | unsigned j = i; | |||
2865 | for (; j < (orig_range.num_pairs () * 2) - 1; j += 2) | |||
2866 | { | |||
2867 | // The middle ranges cannot have MAX/MIN, so there's no need | |||
2868 | // to check for unsigned overflow on the +1 and -1 here. | |||
2869 | tmp = wi::add (wi::to_wide (orig_range.m_base[j]), 1, sign, &ovf); | |||
2870 | m_base[nitems++] = wide_int_to_tree (ttype, tmp); | |||
2871 | tmp = subtract_one (wi::to_wide (orig_range.m_base[j + 1]), | |||
2872 | ttype, ovf); | |||
2873 | m_base[nitems++] = wide_int_to_tree (ttype, tmp); | |||
2874 | if (ovf) | |||
2875 | nitems -= 2; | |||
2876 | } | |||
2877 | i = j; | |||
2878 | } | |||
2879 | // Construct rightmost range. | |||
2880 | // | |||
2881 | // However, if this will overflow on the PLUS 1, don't even bother. | |||
2882 | // This also handles adding one to an unsigned MAX, which doesn't | |||
2883 | // set the overflow bit. | |||
2884 | if (type_max != wi::to_wide (orig_range.m_base[i])) | |||
2885 | { | |||
2886 | tmp = add_one (wi::to_wide (orig_range.m_base[i]), ttype, ovf); | |||
2887 | m_base[nitems++] = wide_int_to_tree (ttype, tmp); | |||
2888 | m_base[nitems++] = wide_int_to_tree (ttype, type_max); | |||
2889 | if (ovf) | |||
2890 | nitems -= 2; | |||
2891 | } | |||
2892 | m_num_ranges = nitems / 2; | |||
2893 | ||||
2894 | // We disallow undefined or varying coming in, so the result can | |||
2895 | // only be a VR_RANGE. | |||
2896 | gcc_checking_assert (m_kind == VR_RANGE)((void)(!(m_kind == VR_RANGE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2896, __FUNCTION__), 0 : 0)); | |||
2897 | ||||
2898 | if (flag_checkingglobal_options.x_flag_checking) | |||
2899 | verify_range (); | |||
2900 | } | |||
2901 | ||||
2902 | // Return the nonzero bits inherent in the range. | |||
2903 | ||||
2904 | wide_int | |||
2905 | irange::get_nonzero_bits_from_range () const | |||
2906 | { | |||
2907 | // For legacy symbolics. | |||
2908 | if (!constant_p ()) | |||
2909 | return wi::shwi (-1, TYPE_PRECISION (type ())((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2909, __FUNCTION__))->type_common.precision)); | |||
2910 | ||||
2911 | wide_int min = lower_bound (); | |||
2912 | wide_int max = upper_bound (); | |||
2913 | wide_int xorv = min ^ max; | |||
2914 | if (xorv != 0) | |||
2915 | { | |||
2916 | unsigned prec = TYPE_PRECISION (type ())((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2916, __FUNCTION__))->type_common.precision); | |||
2917 | xorv = wi::mask (prec - wi::clz (xorv), false, prec); | |||
2918 | } | |||
2919 | return min | xorv; | |||
2920 | } | |||
2921 | ||||
2922 | // If the the nonzero mask can be trivially converted to a range, do | |||
2923 | // so and return TRUE. | |||
2924 | ||||
2925 | bool | |||
2926 | irange::set_range_from_nonzero_bits () | |||
2927 | { | |||
2928 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2928, __FUNCTION__), 0 : 0)); | |||
2929 | if (!m_nonzero_mask) | |||
2930 | return false; | |||
2931 | unsigned popcount = wi::popcount (wi::to_wide (m_nonzero_mask)); | |||
2932 | ||||
2933 | // If we have only one bit set in the mask, we can figure out the | |||
2934 | // range immediately. | |||
2935 | if (popcount == 1) | |||
2936 | { | |||
2937 | // Make sure we don't pessimize the range. | |||
2938 | if (!contains_p (m_nonzero_mask)) | |||
2939 | return false; | |||
2940 | ||||
2941 | bool has_zero = contains_p (build_zero_cst (type ())); | |||
2942 | tree nz = m_nonzero_mask; | |||
2943 | set (nz, nz); | |||
2944 | m_nonzero_mask = nz; | |||
2945 | if (has_zero) | |||
2946 | { | |||
2947 | int_range<2> zero; | |||
2948 | zero.set_zero (type ()); | |||
2949 | union_ (zero); | |||
2950 | } | |||
2951 | return true; | |||
2952 | } | |||
2953 | else if (popcount == 0) | |||
2954 | { | |||
2955 | set_zero (type ()); | |||
2956 | return true; | |||
2957 | } | |||
2958 | return false; | |||
2959 | } | |||
2960 | ||||
2961 | void | |||
2962 | irange::set_nonzero_bits (const wide_int_ref &bits) | |||
2963 | { | |||
2964 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2964, __FUNCTION__), 0 : 0)); | |||
2965 | unsigned prec = TYPE_PRECISION (type ())((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2965, __FUNCTION__))->type_common.precision); | |||
2966 | ||||
2967 | if (bits == -1) | |||
2968 | { | |||
2969 | m_nonzero_mask = NULLnullptr; | |||
2970 | normalize_kind (); | |||
2971 | if (flag_checkingglobal_options.x_flag_checking) | |||
2972 | verify_range (); | |||
2973 | return; | |||
2974 | } | |||
2975 | ||||
2976 | // Drop VARYINGs with a nonzero mask to a plain range. | |||
2977 | if (m_kind == VR_VARYING && bits != -1) | |||
2978 | m_kind = VR_RANGE; | |||
2979 | ||||
2980 | wide_int nz = wide_int::from (bits, prec, TYPE_SIGN (type ())((signop) ((tree_class_check ((type ()), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2980, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
2981 | m_nonzero_mask = wide_int_to_tree (type (), nz); | |||
2982 | if (set_range_from_nonzero_bits ()) | |||
2983 | return; | |||
2984 | ||||
2985 | normalize_kind (); | |||
2986 | if (flag_checkingglobal_options.x_flag_checking) | |||
2987 | verify_range (); | |||
2988 | } | |||
2989 | ||||
2990 | // Return the nonzero bitmask. This will return the nonzero bits plus | |||
2991 | // the nonzero bits inherent in the range. | |||
2992 | ||||
2993 | wide_int | |||
2994 | irange::get_nonzero_bits () const | |||
2995 | { | |||
2996 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 2996, __FUNCTION__), 0 : 0)); | |||
2997 | // The nonzero mask inherent in the range is calculated on-demand. | |||
2998 | // For example, [0,255] does not have a 0xff nonzero mask by default | |||
2999 | // (unless manually set). This saves us considerable time, because | |||
3000 | // setting it at creation incurs a large penalty for irange::set. | |||
3001 | // At the time of writing there was a 5% slowdown in VRP if we kept | |||
3002 | // the mask precisely up to date at all times. Instead, we default | |||
3003 | // to -1 and set it when explicitly requested. However, this | |||
3004 | // function will always return the correct mask. | |||
3005 | if (m_nonzero_mask) | |||
3006 | return wi::to_wide (m_nonzero_mask) & get_nonzero_bits_from_range (); | |||
3007 | else | |||
3008 | return get_nonzero_bits_from_range (); | |||
3009 | } | |||
3010 | ||||
3011 | // Convert tree mask to wide_int. Returns -1 for NULL masks. | |||
3012 | ||||
3013 | inline wide_int | |||
3014 | mask_to_wi (tree mask, tree type) | |||
3015 | { | |||
3016 | if (mask) | |||
3017 | return wi::to_wide (mask); | |||
3018 | else | |||
3019 | return wi::shwi (-1, TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3019, __FUNCTION__))->type_common.precision)); | |||
3020 | } | |||
3021 | ||||
3022 | // Intersect the nonzero bits in R into THIS and normalize the range. | |||
3023 | // Return TRUE if the intersection changed anything. | |||
3024 | ||||
3025 | bool | |||
3026 | irange::intersect_nonzero_bits (const irange &r) | |||
3027 | { | |||
3028 | gcc_checking_assert (!undefined_p () && !r.undefined_p ())((void)(!(!undefined_p () && !r.undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3028, __FUNCTION__), 0 : 0)); | |||
3029 | ||||
3030 | if (!m_nonzero_mask && !r.m_nonzero_mask) | |||
3031 | { | |||
3032 | normalize_kind (); | |||
3033 | if (flag_checkingglobal_options.x_flag_checking) | |||
3034 | verify_range (); | |||
3035 | return false; | |||
3036 | } | |||
3037 | ||||
3038 | bool changed = false; | |||
3039 | tree t = type (); | |||
3040 | if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t)) | |||
3041 | { | |||
3042 | wide_int nz = get_nonzero_bits () & r.get_nonzero_bits (); | |||
3043 | // If the nonzero bits did not change, return false. | |||
3044 | if (nz == get_nonzero_bits ()) | |||
3045 | return false; | |||
3046 | ||||
3047 | m_nonzero_mask = wide_int_to_tree (t, nz); | |||
3048 | if (set_range_from_nonzero_bits ()) | |||
3049 | return true; | |||
3050 | changed = true; | |||
3051 | } | |||
3052 | normalize_kind (); | |||
3053 | if (flag_checkingglobal_options.x_flag_checking) | |||
3054 | verify_range (); | |||
3055 | return changed; | |||
3056 | } | |||
3057 | ||||
3058 | // Union the nonzero bits in R into THIS and normalize the range. | |||
3059 | // Return TRUE if the union changed anything. | |||
3060 | ||||
3061 | bool | |||
3062 | irange::union_nonzero_bits (const irange &r) | |||
3063 | { | |||
3064 | gcc_checking_assert (!undefined_p () && !r.undefined_p ())((void)(!(!undefined_p () && !r.undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3064, __FUNCTION__), 0 : 0)); | |||
3065 | ||||
3066 | if (!m_nonzero_mask && !r.m_nonzero_mask) | |||
3067 | { | |||
3068 | normalize_kind (); | |||
3069 | if (flag_checkingglobal_options.x_flag_checking) | |||
3070 | verify_range (); | |||
3071 | return false; | |||
3072 | } | |||
3073 | ||||
3074 | bool changed = false; | |||
3075 | tree t = type (); | |||
3076 | if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t)) | |||
3077 | { | |||
3078 | wide_int nz = get_nonzero_bits () | r.get_nonzero_bits (); | |||
3079 | m_nonzero_mask = wide_int_to_tree (t, nz); | |||
3080 | // No need to call set_range_from_nonzero_bits, because we'll | |||
3081 | // never narrow the range. Besides, it would cause endless | |||
3082 | // recursion because of the union_ in | |||
3083 | // set_range_from_nonzero_bits. | |||
3084 | changed = true; | |||
3085 | } | |||
3086 | normalize_kind (); | |||
3087 | if (flag_checkingglobal_options.x_flag_checking) | |||
3088 | verify_range (); | |||
3089 | return changed; | |||
3090 | } | |||
3091 | ||||
3092 | void | |||
3093 | dump_value_range (FILE *file, const vrange *vr) | |||
3094 | { | |||
3095 | vr->dump (file); | |||
3096 | } | |||
3097 | ||||
3098 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
3099 | debug (const vrange *vr) | |||
3100 | { | |||
3101 | dump_value_range (stderrstderr, vr); | |||
3102 | fprintf (stderrstderr, "\n"); | |||
3103 | } | |||
3104 | ||||
3105 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
3106 | debug (const vrange &vr) | |||
3107 | { | |||
3108 | debug (&vr); | |||
3109 | } | |||
3110 | ||||
3111 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
3112 | debug (const value_range *vr) | |||
3113 | { | |||
3114 | dump_value_range (stderrstderr, vr); | |||
3115 | fprintf (stderrstderr, "\n"); | |||
3116 | } | |||
3117 | ||||
3118 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
3119 | debug (const value_range &vr) | |||
3120 | { | |||
3121 | dump_value_range (stderrstderr, &vr); | |||
3122 | fprintf (stderrstderr, "\n"); | |||
3123 | } | |||
3124 | ||||
3125 | /* Create two value-ranges in *VR0 and *VR1 from the anti-range *AR | |||
3126 | so that *VR0 U *VR1 == *AR. Returns true if that is possible, | |||
3127 | false otherwise. If *AR can be represented with a single range | |||
3128 | *VR1 will be VR_UNDEFINED. */ | |||
3129 | ||||
3130 | bool | |||
3131 | ranges_from_anti_range (const value_range *ar, | |||
3132 | value_range *vr0, value_range *vr1) | |||
3133 | { | |||
3134 | tree type = ar->type (); | |||
3135 | ||||
3136 | vr0->set_undefined (); | |||
3137 | vr1->set_undefined (); | |||
3138 | ||||
3139 | /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U | |||
3140 | [A+1, +INF]. Not sure if this helps in practice, though. */ | |||
3141 | ||||
3142 | if (ar->kind () != VR_ANTI_RANGE | |||
3143 | || TREE_CODE (ar->min ())((enum tree_code) (ar->min ())->base.code) != INTEGER_CST | |||
3144 | || TREE_CODE (ar->max ())((enum tree_code) (ar->max ())->base.code) != INTEGER_CST | |||
3145 | || !vrp_val_min (type) | |||
3146 | || !vrp_val_max (type)) | |||
3147 | return false; | |||
3148 | ||||
3149 | if (tree_int_cst_lt (vrp_val_min (type), ar->min ())) | |||
3150 | vr0->set (vrp_val_min (type), | |||
3151 | wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1)); | |||
3152 | if (tree_int_cst_lt (ar->max (), vrp_val_max (type))) | |||
3153 | vr1->set (wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1), | |||
3154 | vrp_val_max (type)); | |||
3155 | if (vr0->undefined_p ()) | |||
3156 | { | |||
3157 | *vr0 = *vr1; | |||
3158 | vr1->set_undefined (); | |||
3159 | } | |||
3160 | ||||
3161 | return !vr0->undefined_p (); | |||
3162 | } | |||
3163 | ||||
3164 | bool | |||
3165 | range_has_numeric_bounds_p (const irange *vr) | |||
3166 | { | |||
3167 | return (!vr->undefined_p () | |||
3168 | && TREE_CODE (vr->min ())((enum tree_code) (vr->min ())->base.code) == INTEGER_CST | |||
3169 | && TREE_CODE (vr->max ())((enum tree_code) (vr->max ())->base.code) == INTEGER_CST); | |||
3170 | } | |||
3171 | ||||
3172 | /* Return whether VAL is equal to the maximum value of its type. | |||
3173 | We can't do a simple equality comparison with TYPE_MAX_VALUE because | |||
3174 | C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE | |||
3175 | is not == to the integer constant with the same value in the type. */ | |||
3176 | ||||
3177 | bool | |||
3178 | vrp_val_is_max (const_tree val) | |||
3179 | { | |||
3180 | tree type_max = vrp_val_max (TREE_TYPE (val)((contains_struct_check ((val), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3180, __FUNCTION__))->typed.type)); | |||
3181 | return (val == type_max | |||
3182 | || (type_max != NULL_TREE(tree) nullptr | |||
3183 | && operand_equal_p (val, type_max, 0))); | |||
3184 | } | |||
3185 | ||||
3186 | /* Return whether VAL is equal to the minimum value of its type. */ | |||
3187 | ||||
3188 | bool | |||
3189 | vrp_val_is_min (const_tree val) | |||
3190 | { | |||
3191 | tree type_min = vrp_val_min (TREE_TYPE (val)((contains_struct_check ((val), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3191, __FUNCTION__))->typed.type)); | |||
3192 | return (val == type_min | |||
3193 | || (type_min != NULL_TREE(tree) nullptr | |||
3194 | && operand_equal_p (val, type_min, 0))); | |||
3195 | } | |||
3196 | ||||
3197 | /* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */ | |||
3198 | ||||
3199 | bool | |||
3200 | vrp_operand_equal_p (const_tree val1, const_tree val2) | |||
3201 | { | |||
3202 | if (val1 == val2) | |||
3203 | return true; | |||
3204 | if (!val1 || !val2 || !operand_equal_p (val1, val2, 0)) | |||
3205 | return false; | |||
3206 | return true; | |||
3207 | } | |||
3208 | ||||
3209 | // ?? These stubs are for ipa-prop.cc which use a value_range in a | |||
3210 | // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &) | |||
3211 | // instead of picking up the gt_ggc_mx (T *) version. | |||
3212 | void | |||
3213 | gt_pch_nx (int_range<1> *&x) | |||
3214 | { | |||
3215 | return gt_pch_nx ((irange *) x); | |||
3216 | } | |||
3217 | ||||
3218 | void | |||
3219 | gt_ggc_mx (int_range<1> *&x) | |||
3220 | { | |||
3221 | return gt_ggc_mx ((irange *) x); | |||
3222 | } | |||
3223 | ||||
3224 | #define DEFINE_INT_RANGE_INSTANCE(N)template int_range<N>::int_range(tree, tree, value_range_kind ); template int_range<N>::int_range(tree_node *, const wide_int &, const wide_int &, value_range_kind); template int_range <N>::int_range(tree); template int_range<N>::int_range (const irange &); template int_range<N>::int_range( const int_range &); template int_range<N>& int_range <N>::operator= (const int_range &); \ | |||
3225 | template int_range<N>::int_range(tree, tree, value_range_kind); \ | |||
3226 | template int_range<N>::int_range(tree_node *, \ | |||
3227 | const wide_int &, \ | |||
3228 | const wide_int &, \ | |||
3229 | value_range_kind); \ | |||
3230 | template int_range<N>::int_range(tree); \ | |||
3231 | template int_range<N>::int_range(const irange &); \ | |||
3232 | template int_range<N>::int_range(const int_range &); \ | |||
3233 | template int_range<N>& int_range<N>::operator= (const int_range &); | |||
3234 | ||||
3235 | DEFINE_INT_RANGE_INSTANCE(1)template int_range<1>::int_range(tree, tree, value_range_kind ); template int_range<1>::int_range(tree_node *, const wide_int &, const wide_int &, value_range_kind); template int_range <1>::int_range(tree); template int_range<1>::int_range (const irange &); template int_range<1>::int_range( const int_range &); template int_range<1>& int_range <1>::operator= (const int_range &); | |||
3236 | DEFINE_INT_RANGE_INSTANCE(2)template int_range<2>::int_range(tree, tree, value_range_kind ); template int_range<2>::int_range(tree_node *, const wide_int &, const wide_int &, value_range_kind); template int_range <2>::int_range(tree); template int_range<2>::int_range (const irange &); template int_range<2>::int_range( const int_range &); template int_range<2>& int_range <2>::operator= (const int_range &); | |||
3237 | DEFINE_INT_RANGE_INSTANCE(3)template int_range<3>::int_range(tree, tree, value_range_kind ); template int_range<3>::int_range(tree_node *, const wide_int &, const wide_int &, value_range_kind); template int_range <3>::int_range(tree); template int_range<3>::int_range (const irange &); template int_range<3>::int_range( const int_range &); template int_range<3>& int_range <3>::operator= (const int_range &); | |||
3238 | DEFINE_INT_RANGE_INSTANCE(255)template int_range<255>::int_range(tree, tree, value_range_kind ); template int_range<255>::int_range(tree_node *, const wide_int &, const wide_int &, value_range_kind); template int_range<255>::int_range(tree); template int_range< 255>::int_range(const irange &); template int_range< 255>::int_range(const int_range &); template int_range <255>& int_range<255>::operator= (const int_range &); | |||
3239 | ||||
3240 | #if CHECKING_P1 | |||
3241 | #include "selftest.h" | |||
3242 | ||||
3243 | namespace selftest | |||
3244 | { | |||
3245 | #define INT(N)build_int_cst (integer_types[itk_int], (N)) build_int_cst (integer_type_nodeinteger_types[itk_int], (N)) | |||
3246 | #define UINT(N)build_int_cstu (integer_types[itk_unsigned_int], (N)) build_int_cstu (unsigned_type_nodeinteger_types[itk_unsigned_int], (N)) | |||
3247 | #define UINT128(N)build_int_cstu (u128_type, (N)) build_int_cstu (u128_type, (N)) | |||
3248 | #define UCHAR(N)build_int_cstu (integer_types[itk_unsigned_char], (N)) build_int_cstu (unsigned_char_type_nodeinteger_types[itk_unsigned_char], (N)) | |||
3249 | #define SCHAR(N)build_int_cst (integer_types[itk_signed_char], (N)) build_int_cst (signed_char_type_nodeinteger_types[itk_signed_char], (N)) | |||
3250 | ||||
3251 | static int_range<3> | |||
3252 | build_range3 (int a, int b, int c, int d, int e, int f) | |||
3253 | { | |||
3254 | int_range<3> i1 (INT (a)build_int_cst (integer_types[itk_int], (a)), INT (b)build_int_cst (integer_types[itk_int], (b))); | |||
3255 | int_range<3> i2 (INT (c)build_int_cst (integer_types[itk_int], (c)), INT (d)build_int_cst (integer_types[itk_int], (d))); | |||
3256 | int_range<3> i3 (INT (e)build_int_cst (integer_types[itk_int], (e)), INT (f)build_int_cst (integer_types[itk_int], (f))); | |||
3257 | i1.union_ (i2); | |||
3258 | i1.union_ (i3); | |||
3259 | return i1; | |||
3260 | } | |||
3261 | ||||
3262 | static void | |||
3263 | range_tests_irange3 () | |||
3264 | { | |||
3265 | typedef int_range<3> int_range3; | |||
3266 | int_range3 r0, r1, r2; | |||
3267 | int_range3 i1, i2, i3; | |||
3268 | ||||
3269 | // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20]. | |||
3270 | r0 = int_range3 (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3271 | r1 = int_range3 (INT (5)build_int_cst (integer_types[itk_int], (5)), INT (8)build_int_cst (integer_types[itk_int], (8))); | |||
3272 | r0.union_ (r1); | |||
3273 | r1 = int_range3 (INT (1)build_int_cst (integer_types[itk_int], (1)), INT (3)build_int_cst (integer_types[itk_int], (3))); | |||
3274 | r0.union_ (r1); | |||
3275 | ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == build_range3 (1, 3, 5, 8, 10, 20))" ")"; bool actual_ = ((r0 == build_range3 (1, 3, 5, 8, 10, 20 ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3275, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3275, __FUNCTION__))), desc_); } while (0); | |||
3276 | ||||
3277 | // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20]. | |||
3278 | r1 = int_range3 (INT (-5)build_int_cst (integer_types[itk_int], (-5)), INT (0)build_int_cst (integer_types[itk_int], (0))); | |||
3279 | r0.union_ (r1); | |||
3280 | ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == build_range3 (-5, 3, 5, 8, 10, 20))" ")"; bool actual_ = ((r0 == build_range3 (-5, 3, 5, 8, 10, 20 ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3280, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3280, __FUNCTION__))), desc_); } while (0); | |||
3281 | ||||
3282 | // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60]. | |||
3283 | r1 = int_range3 (INT (50)build_int_cst (integer_types[itk_int], (50)), INT (60)build_int_cst (integer_types[itk_int], (60))); | |||
3284 | r0 = int_range3 (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3285 | r0.union_ (int_range3 (INT (30)build_int_cst (integer_types[itk_int], (30)), INT (40)build_int_cst (integer_types[itk_int], (40)))); | |||
3286 | r0.union_ (r1); | |||
3287 | ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == build_range3 (10, 20, 30, 40, 50, 60))" ")"; bool actual_ = ((r0 == build_range3 (10, 20, 30, 40, 50 , 60))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3287, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3287, __FUNCTION__))), desc_); } while (0); | |||
3288 | // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80]. | |||
3289 | r1 = int_range3 (INT (70)build_int_cst (integer_types[itk_int], (70)), INT (80)build_int_cst (integer_types[itk_int], (80))); | |||
3290 | r0.union_ (r1); | |||
3291 | ||||
3292 | r2 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3293 | r2.union_ (int_range3 (INT (70)build_int_cst (integer_types[itk_int], (70)), INT (80)build_int_cst (integer_types[itk_int], (80)))); | |||
3294 | ASSERT_TRUE (r0 == r2)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r2)" ")"; bool actual_ = ((r0 == r2)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3294, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3294, __FUNCTION__))), desc_); } while (0); | |||
3295 | ||||
3296 | // [10,20][30,40][50,60] U [6,35] => [6,40][50,60]. | |||
3297 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3298 | r1 = int_range3 (INT (6)build_int_cst (integer_types[itk_int], (6)), INT (35)build_int_cst (integer_types[itk_int], (35))); | |||
3299 | r0.union_ (r1); | |||
3300 | r1 = int_range3 (INT (6)build_int_cst (integer_types[itk_int], (6)), INT (40)build_int_cst (integer_types[itk_int], (40))); | |||
3301 | r1.union_ (int_range3 (INT (50)build_int_cst (integer_types[itk_int], (50)), INT (60)build_int_cst (integer_types[itk_int], (60)))); | |||
3302 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3302, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3302, __FUNCTION__))), desc_); } while (0); | |||
3303 | ||||
3304 | // [10,20][30,40][50,60] U [6,60] => [6,60]. | |||
3305 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3306 | r1 = int_range3 (INT (6)build_int_cst (integer_types[itk_int], (6)), INT (60)build_int_cst (integer_types[itk_int], (60))); | |||
3307 | r0.union_ (r1); | |||
3308 | ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range3 (build_int_cst (integer_types[itk_int], (6)), build_int_cst (integer_types[itk_int], (60))))" ")"; bool actual_ = ((r0 == int_range3 (build_int_cst (integer_types [itk_int], (6)), build_int_cst (integer_types[itk_int], (60)) ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3308, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3308, __FUNCTION__))), desc_); } while (0); | |||
3309 | ||||
3310 | // [10,20][30,40][50,60] U [6,70] => [6,70]. | |||
3311 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3312 | r1 = int_range3 (INT (6)build_int_cst (integer_types[itk_int], (6)), INT (70)build_int_cst (integer_types[itk_int], (70))); | |||
3313 | r0.union_ (r1); | |||
3314 | ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range3 (build_int_cst (integer_types[itk_int], (6)), build_int_cst (integer_types[itk_int], (70))))" ")"; bool actual_ = ((r0 == int_range3 (build_int_cst (integer_types [itk_int], (6)), build_int_cst (integer_types[itk_int], (70)) ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3314, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3314, __FUNCTION__))), desc_); } while (0); | |||
3315 | ||||
3316 | // [10,20][30,40][50,60] U [35,70] => [10,20][30,70]. | |||
3317 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3318 | r1 = int_range3 (INT (35)build_int_cst (integer_types[itk_int], (35)), INT (70)build_int_cst (integer_types[itk_int], (70))); | |||
3319 | r0.union_ (r1); | |||
3320 | r1 = int_range3 (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3321 | r1.union_ (int_range3 (INT (30)build_int_cst (integer_types[itk_int], (30)), INT (70)build_int_cst (integer_types[itk_int], (70)))); | |||
3322 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3322, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3322, __FUNCTION__))), desc_); } while (0); | |||
3323 | ||||
3324 | // [10,20][30,40][50,60] U [15,35] => [10,40][50,60]. | |||
3325 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3326 | r1 = int_range3 (INT (15)build_int_cst (integer_types[itk_int], (15)), INT (35)build_int_cst (integer_types[itk_int], (35))); | |||
3327 | r0.union_ (r1); | |||
3328 | r1 = int_range3 (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (40)build_int_cst (integer_types[itk_int], (40))); | |||
3329 | r1.union_ (int_range3 (INT (50)build_int_cst (integer_types[itk_int], (50)), INT (60)build_int_cst (integer_types[itk_int], (60)))); | |||
3330 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3330, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3330, __FUNCTION__))), desc_); } while (0); | |||
3331 | ||||
3332 | // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60]. | |||
3333 | r0 = build_range3 (10, 20, 30, 40, 50, 60); | |||
3334 | r1 = int_range3 (INT (35)build_int_cst (integer_types[itk_int], (35)), INT (35)build_int_cst (integer_types[itk_int], (35))); | |||
3335 | r0.union_ (r1); | |||
3336 | ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == build_range3 (10, 20, 30, 40, 50, 60))" ")"; bool actual_ = ((r0 == build_range3 (10, 20, 30, 40, 50 , 60))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3336, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3336, __FUNCTION__))), desc_); } while (0); | |||
3337 | } | |||
3338 | ||||
3339 | static void | |||
3340 | range_tests_int_range_max () | |||
3341 | { | |||
3342 | int_range_max big; | |||
3343 | unsigned int nrange; | |||
3344 | ||||
3345 | // Build a huge multi-range range. | |||
3346 | for (nrange = 0; nrange < 50; ++nrange) | |||
3347 | { | |||
3348 | int_range<1> tmp (INT (nrange*10)build_int_cst (integer_types[itk_int], (nrange*10)), INT (nrange*10 + 5)build_int_cst (integer_types[itk_int], (nrange*10 + 5))); | |||
3349 | big.union_ (tmp); | |||
3350 | } | |||
3351 | ASSERT_TRUE (big.num_pairs () == nrange)do { const char *desc_ = "ASSERT_TRUE (" "(big.num_pairs () == nrange)" ")"; bool actual_ = ((big.num_pairs () == nrange)); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3351, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3351, __FUNCTION__))), desc_); } while (0); | |||
3352 | ||||
3353 | // Verify that we can copy it without loosing precision. | |||
3354 | int_range_max copy (big); | |||
3355 | ASSERT_TRUE (copy.num_pairs () == nrange)do { const char *desc_ = "ASSERT_TRUE (" "(copy.num_pairs () == nrange)" ")"; bool actual_ = ((copy.num_pairs () == nrange)); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3355, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3355, __FUNCTION__))), desc_); } while (0); | |||
3356 | ||||
3357 | // Inverting it should produce one more sub-range. | |||
3358 | big.invert (); | |||
3359 | ASSERT_TRUE (big.num_pairs () == nrange + 1)do { const char *desc_ = "ASSERT_TRUE (" "(big.num_pairs () == nrange + 1)" ")"; bool actual_ = ((big.num_pairs () == nrange + 1)); if ( actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3359, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3359, __FUNCTION__))), desc_); } while (0); | |||
3360 | ||||
3361 | int_range<1> tmp (INT (5)build_int_cst (integer_types[itk_int], (5)), INT (37)build_int_cst (integer_types[itk_int], (37))); | |||
3362 | big.intersect (tmp); | |||
3363 | ASSERT_TRUE (big.num_pairs () == 4)do { const char *desc_ = "ASSERT_TRUE (" "(big.num_pairs () == 4)" ")"; bool actual_ = ((big.num_pairs () == 4)); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3363, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3363, __FUNCTION__))), desc_); } while (0); | |||
3364 | ||||
3365 | // Test that [10,10][20,20] does NOT contain 15. | |||
3366 | { | |||
3367 | int_range_max i1 (build_int_cst (integer_type_nodeinteger_types[itk_int], 10), | |||
3368 | build_int_cst (integer_type_nodeinteger_types[itk_int], 10)); | |||
3369 | int_range_max i2 (build_int_cst (integer_type_nodeinteger_types[itk_int], 20), | |||
3370 | build_int_cst (integer_type_nodeinteger_types[itk_int], 20)); | |||
3371 | i1.union_ (i2); | |||
3372 | ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15)))do { const char *desc_ = "ASSERT_FALSE (" "(i1.contains_p (build_int_cst (integer_types[itk_int], 15)))" ")"; bool actual_ = ((i1.contains_p (build_int_cst (integer_types [itk_int], 15)))); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3372, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3372, __FUNCTION__))), desc_); } while (0); | |||
3373 | } | |||
3374 | } | |||
3375 | ||||
3376 | static void | |||
3377 | range_tests_legacy () | |||
3378 | { | |||
3379 | // Test truncating copy to int_range<1>. | |||
3380 | int_range<3> big = build_range3 (10, 20, 30, 40, 50, 60); | |||
3381 | int_range<1> small = big; | |||
3382 | ASSERT_TRUE (small == int_range<1> (INT (10), INT (60)))do { const char *desc_ = "ASSERT_TRUE (" "(small == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types[itk_int], (60))))" ")"; bool actual_ = ((small == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types [itk_int], (60))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3382, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3382, __FUNCTION__))), desc_); } while (0); | |||
3383 | ||||
3384 | // Test truncating copy to int_range<2>. | |||
3385 | int_range<2> medium = big; | |||
3386 | ASSERT_TRUE (!medium.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(!medium.undefined_p ())" ")"; bool actual_ = ((!medium.undefined_p ())); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3386, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3386, __FUNCTION__))), desc_); } while (0); | |||
3387 | ||||
3388 | // Test that a truncating copy of [MIN,20][22,40][80,MAX] | |||
3389 | // ends up as a conservative anti-range of ~[21,21]. | |||
3390 | big = int_range<3> (vrp_val_min (integer_type_nodeinteger_types[itk_int]), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3391 | big.union_ (int_range<1> (INT (22)build_int_cst (integer_types[itk_int], (22)), INT (40)build_int_cst (integer_types[itk_int], (40)))); | |||
3392 | big.union_ (int_range<1> (INT (80)build_int_cst (integer_types[itk_int], (80)), vrp_val_max (integer_type_nodeinteger_types[itk_int]))); | |||
3393 | small = big; | |||
3394 | ASSERT_TRUE (small == int_range<1> (INT (21), INT (21), VR_ANTI_RANGE))do { const char *desc_ = "ASSERT_TRUE (" "(small == int_range<1> (build_int_cst (integer_types[itk_int], (21)), build_int_cst (integer_types[itk_int], (21)), VR_ANTI_RANGE))" ")"; bool actual_ = ((small == int_range<1> (build_int_cst (integer_types[itk_int], (21)), build_int_cst (integer_types [itk_int], (21)), VR_ANTI_RANGE))); if (actual_) ::selftest:: pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3394, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3394, __FUNCTION__))), desc_); } while (0); | |||
3395 | ||||
3396 | // Copying a legacy symbolic to an int_range should normalize the | |||
3397 | // symbolic at copy time. | |||
3398 | { | |||
3399 | tree ssa = make_ssa_name (integer_type_nodeinteger_types[itk_int]); | |||
3400 | value_range legacy_range (ssa, INT (25)build_int_cst (integer_types[itk_int], (25))); | |||
3401 | int_range<2> copy = legacy_range; | |||
3402 | ASSERT_TRUE (copy == int_range<2> (vrp_val_min (integer_type_node),do { const char *desc_ = "ASSERT_TRUE (" "(copy == int_range<2> (vrp_val_min (integer_types[itk_int]), build_int_cst (integer_types[itk_int], (25))))" ")"; bool actual_ = ((copy == int_range<2> (vrp_val_min (integer_types[itk_int]), build_int_cst (integer_types[itk_int ], (25))))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3403, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3403, __FUNCTION__))), desc_); } while (0) | |||
3403 | INT (25)))do { const char *desc_ = "ASSERT_TRUE (" "(copy == int_range<2> (vrp_val_min (integer_types[itk_int]), build_int_cst (integer_types[itk_int], (25))))" ")"; bool actual_ = ((copy == int_range<2> (vrp_val_min (integer_types[itk_int]), build_int_cst (integer_types[itk_int ], (25))))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3403, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3403, __FUNCTION__))), desc_); } while (0); | |||
3404 | ||||
3405 | // Test that copying ~[abc_23, abc_23] to a multi-range yields varying. | |||
3406 | legacy_range = value_range (ssa, ssa, VR_ANTI_RANGE); | |||
3407 | copy = legacy_range; | |||
3408 | ASSERT_TRUE (copy.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(copy.varying_p ())" ")"; bool actual_ = ((copy.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3408, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3408, __FUNCTION__))), desc_); } while (0); | |||
3409 | } | |||
3410 | ||||
3411 | // VARYING of different sizes should not be equal. | |||
3412 | tree big_type = build_nonstandard_integer_type (32, 1); | |||
3413 | tree small_type = build_nonstandard_integer_type (16, 1); | |||
3414 | int_range_max r0 (big_type); | |||
3415 | int_range_max r1 (small_type); | |||
3416 | ASSERT_TRUE (r0 != r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 != r1)" ")"; bool actual_ = ((r0 != r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3416, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3416, __FUNCTION__))), desc_); } while (0); | |||
3417 | value_range vr0 (big_type); | |||
3418 | int_range_max vr1 (small_type); | |||
3419 | ASSERT_TRUE (vr0 != vr1)do { const char *desc_ = "ASSERT_TRUE (" "(vr0 != vr1)" ")"; bool actual_ = ((vr0 != vr1)); if (actual_) ::selftest::pass (((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3419, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3419, __FUNCTION__))), desc_); } while (0); | |||
3420 | } | |||
3421 | ||||
3422 | // Simulate -fstrict-enums where the domain of a type is less than the | |||
3423 | // underlying type. | |||
3424 | ||||
3425 | static void | |||
3426 | range_tests_strict_enum () | |||
3427 | { | |||
3428 | // The enum can only hold [0, 3]. | |||
3429 | tree rtype = copy_node (unsigned_type_nodeinteger_types[itk_unsigned_int]); | |||
3430 | TYPE_MIN_VALUE (rtype)((tree_check5 ((rtype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3430, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval ) = build_int_cstu (rtype, 0); | |||
3431 | TYPE_MAX_VALUE (rtype)((tree_check5 ((rtype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3431, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ) = build_int_cstu (rtype, 3); | |||
3432 | ||||
3433 | // Test that even though vr1 covers the strict enum domain ([0, 3]), | |||
3434 | // it does not cover the domain of the underlying type. | |||
3435 | int_range<1> vr1 (build_int_cstu (rtype, 0), build_int_cstu (rtype, 1)); | |||
3436 | int_range<1> vr2 (build_int_cstu (rtype, 2), build_int_cstu (rtype, 3)); | |||
3437 | vr1.union_ (vr2); | |||
3438 | ASSERT_TRUE (vr1 == int_range<1> (build_int_cstu (rtype, 0),do { const char *desc_ = "ASSERT_TRUE (" "(vr1 == int_range<1> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3)))" ")"; bool actual_ = ((vr1 == int_range<1> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3)))); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3439, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3439, __FUNCTION__))), desc_); } while (0) | |||
3439 | build_int_cstu (rtype, 3)))do { const char *desc_ = "ASSERT_TRUE (" "(vr1 == int_range<1> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3)))" ")"; bool actual_ = ((vr1 == int_range<1> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3)))); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3439, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3439, __FUNCTION__))), desc_); } while (0); | |||
3440 | ASSERT_FALSE (vr1.varying_p ())do { const char *desc_ = "ASSERT_FALSE (" "(vr1.varying_p ())" ")"; bool actual_ = ((vr1.varying_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3440, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3440, __FUNCTION__))), desc_); } while (0); | |||
3441 | ||||
3442 | // Test that copying to a multi-range does not change things. | |||
3443 | int_range<2> ir1 (vr1); | |||
3444 | ASSERT_TRUE (ir1 == vr1)do { const char *desc_ = "ASSERT_TRUE (" "(ir1 == vr1)" ")"; bool actual_ = ((ir1 == vr1)); if (actual_) ::selftest::pass (((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3444, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3444, __FUNCTION__))), desc_); } while (0); | |||
3445 | ASSERT_FALSE (ir1.varying_p ())do { const char *desc_ = "ASSERT_FALSE (" "(ir1.varying_p ())" ")"; bool actual_ = ((ir1.varying_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3445, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3445, __FUNCTION__))), desc_); } while (0); | |||
3446 | ||||
3447 | // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3]. | |||
3448 | vr1 = int_range<1> (TYPE_MIN_VALUE (rtype)((tree_check5 ((rtype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3448, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval ), TYPE_MAX_VALUE (rtype)((tree_check5 ((rtype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3448, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval )); | |||
3449 | ir1 = vr1; | |||
3450 | ASSERT_TRUE (ir1 == vr1)do { const char *desc_ = "ASSERT_TRUE (" "(ir1 == vr1)" ")"; bool actual_ = ((ir1 == vr1)); if (actual_) ::selftest::pass (((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3450, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3450, __FUNCTION__))), desc_); } while (0); | |||
3451 | ASSERT_FALSE (ir1.varying_p ())do { const char *desc_ = "ASSERT_FALSE (" "(ir1.varying_p ())" ")"; bool actual_ = ((ir1.varying_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3451, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3451, __FUNCTION__))), desc_); } while (0); | |||
3452 | } | |||
3453 | ||||
3454 | static void | |||
3455 | range_tests_misc () | |||
3456 | { | |||
3457 | tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1); | |||
3458 | int_range<1> i1, i2, i3; | |||
3459 | int_range<1> r0, r1, rold; | |||
3460 | ||||
3461 | // Test 1-bit signed integer union. | |||
3462 | // [-1,-1] U [0,0] = VARYING. | |||
3463 | tree one_bit_type = build_nonstandard_integer_type (1, 0); | |||
3464 | tree one_bit_min = vrp_val_min (one_bit_type); | |||
3465 | tree one_bit_max = vrp_val_max (one_bit_type); | |||
3466 | { | |||
3467 | int_range<2> min (one_bit_min, one_bit_min); | |||
3468 | int_range<2> max (one_bit_max, one_bit_max); | |||
3469 | max.union_ (min); | |||
3470 | ASSERT_TRUE (max.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(max.varying_p ())" ")"; bool actual_ = ((max.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3470, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3470, __FUNCTION__))), desc_); } while (0); | |||
3471 | } | |||
3472 | // Test that we can set a range of true+false for a 1-bit signed int. | |||
3473 | r0 = range_true_and_false (one_bit_type); | |||
3474 | ||||
3475 | // Test inversion of 1-bit signed integers. | |||
3476 | { | |||
3477 | int_range<2> min (one_bit_min, one_bit_min); | |||
3478 | int_range<2> max (one_bit_max, one_bit_max); | |||
3479 | int_range<2> t; | |||
3480 | t = min; | |||
3481 | t.invert (); | |||
3482 | ASSERT_TRUE (t == max)do { const char *desc_ = "ASSERT_TRUE (" "(t == max)" ")"; bool actual_ = ((t == max)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3482, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3482, __FUNCTION__))), desc_); } while (0); | |||
3483 | t = max; | |||
3484 | t.invert (); | |||
3485 | ASSERT_TRUE (t == min)do { const char *desc_ = "ASSERT_TRUE (" "(t == min)" ")"; bool actual_ = ((t == min)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3485, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3485, __FUNCTION__))), desc_); } while (0); | |||
3486 | } | |||
3487 | ||||
3488 | // Test that NOT(255) is [0..254] in 8-bit land. | |||
3489 | int_range<1> not_255 (UCHAR (255)build_int_cstu (integer_types[itk_unsigned_char], (255)), UCHAR (255)build_int_cstu (integer_types[itk_unsigned_char], (255)), VR_ANTI_RANGE); | |||
3490 | ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)))do { const char *desc_ = "ASSERT_TRUE (" "(not_255 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_char], (0)), build_int_cstu (integer_types[itk_unsigned_char], (254))))" ")"; bool actual_ = ((not_255 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_char], (0)), build_int_cstu (integer_types [itk_unsigned_char], (254))))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3490, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3490, __FUNCTION__))), desc_); } while (0); | |||
3491 | ||||
3492 | // Test that NOT(0) is [1..255] in 8-bit land. | |||
3493 | int_range<1> not_zero = range_nonzero (unsigned_char_type_nodeinteger_types[itk_unsigned_char]); | |||
3494 | ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255)))do { const char *desc_ = "ASSERT_TRUE (" "(not_zero == int_range<1> (build_int_cstu (integer_types[itk_unsigned_char], (1)), build_int_cstu (integer_types[itk_unsigned_char], (255))))" ")"; bool actual_ = ((not_zero == int_range<1> (build_int_cstu (integer_types[itk_unsigned_char], (1)), build_int_cstu (integer_types [itk_unsigned_char], (255))))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3494, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3494, __FUNCTION__))), desc_); } while (0); | |||
3495 | ||||
3496 | // Check that [0,127][0x..ffffff80,0x..ffffff] | |||
3497 | // => ~[128, 0x..ffffff7f]. | |||
3498 | r0 = int_range<1> (UINT128 (0)build_int_cstu (u128_type, (0)), UINT128 (127)build_int_cstu (u128_type, (127))); | |||
3499 | tree high = build_minus_one_cst (u128_type); | |||
3500 | // low = -1 - 127 => 0x..ffffff80. | |||
3501 | tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127))fold_build2_loc (((location_t) 0), MINUS_EXPR, u128_type, high , build_int_cstu (u128_type, (127)) ); | |||
3502 | r1 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff] | |||
3503 | // r0 = [0,127][0x..ffffff80,0x..fffffff]. | |||
3504 | r0.union_ (r1); | |||
3505 | // r1 = [128, 0x..ffffff7f]. | |||
3506 | r1 = int_range<1> (UINT128(128)build_int_cstu (u128_type, (128)), | |||
3507 | fold_build2 (MINUS_EXPR, u128_type,fold_build2_loc (((location_t) 0), MINUS_EXPR, u128_type, build_minus_one_cst (u128_type), build_int_cstu (u128_type, (128)) ) | |||
3508 | build_minus_one_cst (u128_type),fold_build2_loc (((location_t) 0), MINUS_EXPR, u128_type, build_minus_one_cst (u128_type), build_int_cstu (u128_type, (128)) ) | |||
3509 | UINT128(128))fold_build2_loc (((location_t) 0), MINUS_EXPR, u128_type, build_minus_one_cst (u128_type), build_int_cstu (u128_type, (128)) )); | |||
3510 | r0.invert (); | |||
3511 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3511, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3511, __FUNCTION__))), desc_); } while (0); | |||
3512 | ||||
3513 | r0.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3514 | tree minint = wide_int_to_tree (integer_type_nodeinteger_types[itk_int], r0.lower_bound ()); | |||
3515 | tree maxint = wide_int_to_tree (integer_type_nodeinteger_types[itk_int], r0.upper_bound ()); | |||
3516 | ||||
3517 | r0.set_varying (short_integer_type_nodeinteger_types[itk_short]); | |||
3518 | ||||
3519 | r0.set_varying (unsigned_type_nodeinteger_types[itk_unsigned_int]); | |||
3520 | tree maxuint = wide_int_to_tree (unsigned_type_nodeinteger_types[itk_unsigned_int], r0.upper_bound ()); | |||
3521 | ||||
3522 | // Check that ~[0,5] => [6,MAX] for unsigned int. | |||
3523 | r0 = int_range<1> (UINT (0)build_int_cstu (integer_types[itk_unsigned_int], (0)), UINT (5)build_int_cstu (integer_types[itk_unsigned_int], (5))); | |||
3524 | r0.invert (); | |||
3525 | ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_int], (6)), maxuint))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_int], (6)), maxuint))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3525, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3525, __FUNCTION__))), desc_); } while (0); | |||
3526 | ||||
3527 | // Check that ~[10,MAX] => [0,9] for unsigned int. | |||
3528 | r0 = int_range<1> (UINT(10)build_int_cstu (integer_types[itk_unsigned_int], (10)), maxuint); | |||
3529 | r0.invert (); | |||
3530 | ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_int], (0)), build_int_cstu (integer_types[itk_unsigned_int], (9))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cstu (integer_types[itk_unsigned_int], (0)), build_int_cstu (integer_types [itk_unsigned_int], (9))))); if (actual_) ::selftest::pass (( (::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3530, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3530, __FUNCTION__))), desc_); } while (0); | |||
3531 | ||||
3532 | // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers. | |||
3533 | r0 = int_range<1> (UINT128 (0)build_int_cstu (u128_type, (0)), UINT128 (5)build_int_cstu (u128_type, (5)), VR_ANTI_RANGE); | |||
3534 | r1 = int_range<1> (UINT128(6)build_int_cstu (u128_type, (6)), build_minus_one_cst (u128_type)); | |||
3535 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3535, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3535, __FUNCTION__))), desc_); } while (0); | |||
3536 | ||||
3537 | // Check that [~5] is really [-MIN,4][6,MAX]. | |||
3538 | r0 = int_range<1> (INT (5)build_int_cst (integer_types[itk_int], (5)), INT (5)build_int_cst (integer_types[itk_int], (5)), VR_ANTI_RANGE); | |||
3539 | r1 = int_range<1> (minint, INT (4)build_int_cst (integer_types[itk_int], (4))); | |||
3540 | r1.union_ (int_range<1> (INT (6)build_int_cst (integer_types[itk_int], (6)), maxint)); | |||
3541 | ASSERT_FALSE (r1.undefined_p ())do { const char *desc_ = "ASSERT_FALSE (" "(r1.undefined_p ())" ")"; bool actual_ = ((r1.undefined_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3541, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3541, __FUNCTION__))), desc_); } while (0); | |||
3542 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3542, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3542, __FUNCTION__))), desc_); } while (0); | |||
3543 | ||||
3544 | r1 = int_range<1> (INT (5)build_int_cst (integer_types[itk_int], (5)), INT (5)build_int_cst (integer_types[itk_int], (5))); | |||
3545 | int_range<1> r2 (r1); | |||
3546 | ASSERT_TRUE (r1 == r2)do { const char *desc_ = "ASSERT_TRUE (" "(r1 == r2)" ")"; bool actual_ = ((r1 == r2)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3546, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3546, __FUNCTION__))), desc_); } while (0); | |||
3547 | ||||
3548 | r1 = int_range<1> (INT (5)build_int_cst (integer_types[itk_int], (5)), INT (10)build_int_cst (integer_types[itk_int], (10))); | |||
3549 | ||||
3550 | r1 = int_range<1> (integer_type_nodeinteger_types[itk_int], | |||
3551 | wi::to_wide (INT (5)build_int_cst (integer_types[itk_int], (5))), wi::to_wide (INT (10)build_int_cst (integer_types[itk_int], (10)))); | |||
3552 | ASSERT_TRUE (r1.contains_p (INT (7)))do { const char *desc_ = "ASSERT_TRUE (" "(r1.contains_p (build_int_cst (integer_types[itk_int], (7))))" ")"; bool actual_ = ((r1.contains_p (build_int_cst (integer_types [itk_int], (7))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3552, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3552, __FUNCTION__))), desc_); } while (0); | |||
3553 | ||||
3554 | r1 = int_range<1> (SCHAR (0)build_int_cst (integer_types[itk_signed_char], (0)), SCHAR (20)build_int_cst (integer_types[itk_signed_char], (20))); | |||
3555 | ASSERT_TRUE (r1.contains_p (SCHAR(15)))do { const char *desc_ = "ASSERT_TRUE (" "(r1.contains_p (build_int_cst (integer_types[itk_signed_char], (15))))" ")"; bool actual_ = ((r1.contains_p (build_int_cst (integer_types [itk_signed_char], (15))))); if (actual_) ::selftest::pass (( (::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3555, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3555, __FUNCTION__))), desc_); } while (0); | |||
3556 | ASSERT_FALSE (r1.contains_p (SCHAR(300)))do { const char *desc_ = "ASSERT_FALSE (" "(r1.contains_p (build_int_cst (integer_types[itk_signed_char], (300))))" ")"; bool actual_ = ((r1.contains_p (build_int_cst (integer_types [itk_signed_char], (300))))); if (actual_) ::selftest::fail ( ((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3556, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3556, __FUNCTION__))), desc_); } while (0); | |||
3557 | ||||
3558 | // NOT([10,20]) ==> [-MIN,9][21,MAX]. | |||
3559 | r0 = r1 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3560 | r2 = int_range<1> (minint, INT(9)build_int_cst (integer_types[itk_int], (9))); | |||
3561 | r2.union_ (int_range<1> (INT(21)build_int_cst (integer_types[itk_int], (21)), maxint)); | |||
3562 | ASSERT_FALSE (r2.undefined_p ())do { const char *desc_ = "ASSERT_FALSE (" "(r2.undefined_p ())" ")"; bool actual_ = ((r2.undefined_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3562, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3562, __FUNCTION__))), desc_); } while (0); | |||
3563 | r1.invert (); | |||
3564 | ASSERT_TRUE (r1 == r2)do { const char *desc_ = "ASSERT_TRUE (" "(r1 == r2)" ")"; bool actual_ = ((r1 == r2)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3564, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3564, __FUNCTION__))), desc_); } while (0); | |||
3565 | // Test that NOT(NOT(x)) == x. | |||
3566 | r2.invert (); | |||
3567 | ASSERT_TRUE (r0 == r2)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r2)" ")"; bool actual_ = ((r0 == r2)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3567, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3567, __FUNCTION__))), desc_); } while (0); | |||
3568 | ||||
3569 | // Test that booleans and their inverse work as expected. | |||
3570 | r0 = range_zero (boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]); | |||
3571 | ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node),do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_zero_cst (global_trees[TI_BOOLEAN_TYPE]), build_zero_cst (global_trees[TI_BOOLEAN_TYPE])))" ")"; bool actual_ = ((r0 == int_range<1> (build_zero_cst (global_trees[TI_BOOLEAN_TYPE]), build_zero_cst (global_trees [TI_BOOLEAN_TYPE])))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3572, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3572, __FUNCTION__))), desc_); } while (0) | |||
3572 | build_zero_cst (boolean_type_node)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_zero_cst (global_trees[TI_BOOLEAN_TYPE]), build_zero_cst (global_trees[TI_BOOLEAN_TYPE])))" ")"; bool actual_ = ((r0 == int_range<1> (build_zero_cst (global_trees[TI_BOOLEAN_TYPE]), build_zero_cst (global_trees [TI_BOOLEAN_TYPE])))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3572, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3572, __FUNCTION__))), desc_); } while (0); | |||
3573 | r0.invert (); | |||
3574 | ASSERT_TRUE (r0 == int_range<1> (build_one_cst (boolean_type_node),do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_one_cst (global_trees[TI_BOOLEAN_TYPE]), build_one_cst (global_trees[TI_BOOLEAN_TYPE])))" ")"; bool actual_ = ((r0 == int_range<1> (build_one_cst (global_trees[TI_BOOLEAN_TYPE]), build_one_cst (global_trees [TI_BOOLEAN_TYPE])))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3575, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3575, __FUNCTION__))), desc_); } while (0) | |||
3575 | build_one_cst (boolean_type_node)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_one_cst (global_trees[TI_BOOLEAN_TYPE]), build_one_cst (global_trees[TI_BOOLEAN_TYPE])))" ")"; bool actual_ = ((r0 == int_range<1> (build_one_cst (global_trees[TI_BOOLEAN_TYPE]), build_one_cst (global_trees [TI_BOOLEAN_TYPE])))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3575, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3575, __FUNCTION__))), desc_); } while (0); | |||
3576 | ||||
3577 | // Make sure NULL and non-NULL of pointer types work, and that | |||
3578 | // inverses of them are consistent. | |||
3579 | tree voidp = build_pointer_type (void_type_nodeglobal_trees[TI_VOID_TYPE]); | |||
3580 | r0 = range_zero (voidp); | |||
3581 | r1 = r0; | |||
3582 | r0.invert (); | |||
3583 | r0.invert (); | |||
3584 | ASSERT_TRUE (r0 == r1)do { const char *desc_ = "ASSERT_TRUE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3584, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3584, __FUNCTION__))), desc_); } while (0); | |||
3585 | ||||
3586 | // [10,20] U [15, 30] => [10, 30]. | |||
3587 | r0 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3588 | r1 = int_range<1> (INT (15)build_int_cst (integer_types[itk_int], (15)), INT (30)build_int_cst (integer_types[itk_int], (30))); | |||
3589 | r0.union_ (r1); | |||
3590 | ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types[itk_int], (30))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types [itk_int], (30))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3590, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3590, __FUNCTION__))), desc_); } while (0); | |||
3591 | ||||
3592 | // [15,40] U [] => [15,40]. | |||
3593 | r0 = int_range<1> (INT (15)build_int_cst (integer_types[itk_int], (15)), INT (40)build_int_cst (integer_types[itk_int], (40))); | |||
3594 | r1.set_undefined (); | |||
3595 | r0.union_ (r1); | |||
3596 | ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cst (integer_types[itk_int], (15)), build_int_cst (integer_types[itk_int], (40))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cst (integer_types[itk_int], (15)), build_int_cst (integer_types [itk_int], (40))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3596, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3596, __FUNCTION__))), desc_); } while (0); | |||
3597 | ||||
3598 | // [10,20] U [10,10] => [10,20]. | |||
3599 | r0 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3600 | r1 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (10)build_int_cst (integer_types[itk_int], (10))); | |||
3601 | r0.union_ (r1); | |||
3602 | ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types[itk_int], (20))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cst (integer_types[itk_int], (10)), build_int_cst (integer_types [itk_int], (20))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3602, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3602, __FUNCTION__))), desc_); } while (0); | |||
3603 | ||||
3604 | // [10,20] U [9,9] => [9,20]. | |||
3605 | r0 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3606 | r1 = int_range<1> (INT (9)build_int_cst (integer_types[itk_int], (9)), INT (9)build_int_cst (integer_types[itk_int], (9))); | |||
3607 | r0.union_ (r1); | |||
3608 | ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cst (integer_types[itk_int], (9)), build_int_cst (integer_types[itk_int], (20))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cst (integer_types[itk_int], (9)), build_int_cst (integer_types[ itk_int], (20))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3608, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3608, __FUNCTION__))), desc_); } while (0); | |||
3609 | ||||
3610 | // [10,20] ^ [15,30] => [15,20]. | |||
3611 | r0 = int_range<1> (INT (10)build_int_cst (integer_types[itk_int], (10)), INT (20)build_int_cst (integer_types[itk_int], (20))); | |||
3612 | r1 = int_range<1> (INT (15)build_int_cst (integer_types[itk_int], (15)), INT (30)build_int_cst (integer_types[itk_int], (30))); | |||
3613 | r0.intersect (r1); | |||
3614 | ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20)))do { const char *desc_ = "ASSERT_TRUE (" "(r0 == int_range<1> (build_int_cst (integer_types[itk_int], (15)), build_int_cst (integer_types[itk_int], (20))))" ")"; bool actual_ = ((r0 == int_range<1> (build_int_cst (integer_types[itk_int], (15)), build_int_cst (integer_types [itk_int], (20))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3614, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3614, __FUNCTION__))), desc_); } while (0); | |||
3615 | ||||
3616 | // Test the internal sanity of wide_int's wrt HWIs. | |||
3617 | ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),do { const char *desc_ = "ASSERT_TRUE (" "(wi::max_value (((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3617, __FUNCTION__))->type_common.precision), ((signop) ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3619, __FUNCTION__))->type_common.precision)))" ")"; bool actual_ = ((wi::max_value (((tree_class_check ((global_trees [TI_BOOLEAN_TYPE]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3617, __FUNCTION__))->type_common.precision), ((signop) ( (tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi ::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE] ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))->type_common.precision)))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); } while (0) | |||
3618 | TYPE_SIGN (boolean_type_node))do { const char *desc_ = "ASSERT_TRUE (" "(wi::max_value (((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3617, __FUNCTION__))->type_common.precision), ((signop) ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3619, __FUNCTION__))->type_common.precision)))" ")"; bool actual_ = ((wi::max_value (((tree_class_check ((global_trees [TI_BOOLEAN_TYPE]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3617, __FUNCTION__))->type_common.precision), ((signop) ( (tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi ::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE] ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))->type_common.precision)))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); } while (0) | |||
3619 | == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)))do { const char *desc_ = "ASSERT_TRUE (" "(wi::max_value (((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3617, __FUNCTION__))->type_common.precision), ((signop) ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type), \"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc\", 3619, __FUNCTION__))->type_common.precision)))" ")"; bool actual_ = ((wi::max_value (((tree_class_check ((global_trees [TI_BOOLEAN_TYPE]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3617, __FUNCTION__))->type_common.precision), ((signop) ( (tree_class_check ((global_trees[TI_BOOLEAN_TYPE]), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3618, __FUNCTION__))->base.u.bits.unsigned_flag))) == wi ::uhwi (1, ((tree_class_check ((global_trees[TI_BOOLEAN_TYPE] ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))->type_common.precision)))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3619, __FUNCTION__))), desc_); } while (0); | |||
3620 | ||||
3621 | // Test zero_p(). | |||
3622 | r0 = int_range<1> (INT (0)build_int_cst (integer_types[itk_int], (0)), INT (0)build_int_cst (integer_types[itk_int], (0))); | |||
3623 | ASSERT_TRUE (r0.zero_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.zero_p ())" ")" ; bool actual_ = ((r0.zero_p ())); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3623, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3623, __FUNCTION__))), desc_); } while (0); | |||
3624 | ||||
3625 | // Test nonzero_p(). | |||
3626 | r0 = int_range<1> (INT (0)build_int_cst (integer_types[itk_int], (0)), INT (0)build_int_cst (integer_types[itk_int], (0))); | |||
3627 | r0.invert (); | |||
3628 | ASSERT_TRUE (r0.nonzero_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.nonzero_p ())" ")" ; bool actual_ = ((r0.nonzero_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3628, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3628, __FUNCTION__))), desc_); } while (0); | |||
3629 | ||||
3630 | // test legacy interaction | |||
3631 | // r0 = ~[1,1] | |||
3632 | r0 = int_range<1> (UINT (1)build_int_cstu (integer_types[itk_unsigned_int], (1)), UINT (1)build_int_cstu (integer_types[itk_unsigned_int], (1)), VR_ANTI_RANGE); | |||
3633 | // r1 = ~[3,3] | |||
3634 | r1 = int_range<1> (UINT (3)build_int_cstu (integer_types[itk_unsigned_int], (3)), UINT (3)build_int_cstu (integer_types[itk_unsigned_int], (3)), VR_ANTI_RANGE); | |||
3635 | ||||
3636 | // vv = [0,0][2,2][4, MAX] | |||
3637 | int_range<3> vv = r0; | |||
3638 | vv.intersect (r1); | |||
3639 | ||||
3640 | ASSERT_TRUE (vv.contains_p (UINT (2)))do { const char *desc_ = "ASSERT_TRUE (" "(vv.contains_p (build_int_cstu (integer_types[itk_unsigned_int], (2))))" ")"; bool actual_ = ((vv.contains_p (build_int_cstu (integer_types [itk_unsigned_int], (2))))); if (actual_) ::selftest::pass (( (::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3640, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3640, __FUNCTION__))), desc_); } while (0); | |||
3641 | ASSERT_TRUE (vv.num_pairs () == 3)do { const char *desc_ = "ASSERT_TRUE (" "(vv.num_pairs () == 3)" ")"; bool actual_ = ((vv.num_pairs () == 3)); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3641, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3641, __FUNCTION__))), desc_); } while (0); | |||
3642 | ||||
3643 | // create r0 as legacy [1,1] | |||
3644 | r0 = int_range<1> (UINT (1)build_int_cstu (integer_types[itk_unsigned_int], (1)), UINT (1)build_int_cstu (integer_types[itk_unsigned_int], (1))); | |||
3645 | // And union it with [0,0][2,2][4,MAX] multi range | |||
3646 | r0.union_ (vv); | |||
3647 | // The result should be [0,2][4,MAX], or ~[3,3] but it must contain 2 | |||
3648 | ASSERT_TRUE (r0.contains_p (UINT (2)))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (build_int_cstu (integer_types[itk_unsigned_int], (2))))" ")"; bool actual_ = ((r0.contains_p (build_int_cstu (integer_types [itk_unsigned_int], (2))))); if (actual_) ::selftest::pass (( (::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3648, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3648, __FUNCTION__))), desc_); } while (0); | |||
3649 | } | |||
3650 | ||||
3651 | static void | |||
3652 | range_tests_nonzero_bits () | |||
3653 | { | |||
3654 | int_range<2> r0, r1; | |||
3655 | ||||
3656 | // Adding nonzero bits to a varying drops the varying. | |||
3657 | r0.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3658 | r0.set_nonzero_bits (255); | |||
3659 | ASSERT_TRUE (!r0.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(!r0.varying_p ())" ")"; bool actual_ = ((!r0.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3659, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3659, __FUNCTION__))), desc_); } while (0); | |||
3660 | // Dropping the nonzero bits brings us back to varying. | |||
3661 | r0.set_nonzero_bits (-1); | |||
3662 | ASSERT_TRUE (r0.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.varying_p ())" ")" ; bool actual_ = ((r0.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3662, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3662, __FUNCTION__))), desc_); } while (0); | |||
3663 | ||||
3664 | // Test contains_p with nonzero bits. | |||
3665 | r0.set_zero (integer_type_nodeinteger_types[itk_int]); | |||
3666 | ASSERT_TRUE (r0.contains_p (INT (0)))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (build_int_cst (integer_types[itk_int], (0))))" ")"; bool actual_ = ((r0.contains_p (build_int_cst (integer_types [itk_int], (0))))); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3666, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3666, __FUNCTION__))), desc_); } while (0); | |||
3667 | ASSERT_FALSE (r0.contains_p (INT (1)))do { const char *desc_ = "ASSERT_FALSE (" "(r0.contains_p (build_int_cst (integer_types[itk_int], (1))))" ")"; bool actual_ = ((r0.contains_p (build_int_cst (integer_types [itk_int], (1))))); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3667, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3667, __FUNCTION__))), desc_); } while (0); | |||
3668 | r0.set_nonzero_bits (0xfe); | |||
3669 | ASSERT_FALSE (r0.contains_p (INT (0x100)))do { const char *desc_ = "ASSERT_FALSE (" "(r0.contains_p (build_int_cst (integer_types[itk_int], (0x100))))" ")"; bool actual_ = ((r0.contains_p (build_int_cst (integer_types [itk_int], (0x100))))); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3669, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3669, __FUNCTION__))), desc_); } while (0); | |||
3670 | ASSERT_FALSE (r0.contains_p (INT (0x3)))do { const char *desc_ = "ASSERT_FALSE (" "(r0.contains_p (build_int_cst (integer_types[itk_int], (0x3))))" ")"; bool actual_ = ((r0.contains_p (build_int_cst (integer_types [itk_int], (0x3))))); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3670, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3670, __FUNCTION__))), desc_); } while (0); | |||
3671 | ||||
3672 | // Union of nonzero bits. | |||
3673 | r0.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3674 | r0.set_nonzero_bits (0xf0); | |||
3675 | r1.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3676 | r1.set_nonzero_bits (0xf); | |||
3677 | r0.union_ (r1); | |||
3678 | ASSERT_TRUE (r0.get_nonzero_bits () == 0xff)do { const char *desc_ = "ASSERT_TRUE (" "(r0.get_nonzero_bits () == 0xff)" ")"; bool actual_ = ((r0.get_nonzero_bits () == 0xff)); if ( actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3678, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3678, __FUNCTION__))), desc_); } while (0); | |||
3679 | ||||
3680 | // Intersect of nonzero bits. | |||
3681 | r0.set (INT (0)build_int_cst (integer_types[itk_int], (0)), INT (255)build_int_cst (integer_types[itk_int], (255))); | |||
3682 | r0.set_nonzero_bits (0xfe); | |||
3683 | r1.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3684 | r1.set_nonzero_bits (0xf0); | |||
3685 | r0.intersect (r1); | |||
3686 | ASSERT_TRUE (r0.get_nonzero_bits () == 0xf0)do { const char *desc_ = "ASSERT_TRUE (" "(r0.get_nonzero_bits () == 0xf0)" ")"; bool actual_ = ((r0.get_nonzero_bits () == 0xf0)); if ( actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3686, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3686, __FUNCTION__))), desc_); } while (0); | |||
3687 | ||||
3688 | // Intersect where the mask of nonzero bits is implicit from the range. | |||
3689 | r0.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3690 | r1.set (INT (0)build_int_cst (integer_types[itk_int], (0)), INT (255)build_int_cst (integer_types[itk_int], (255))); | |||
3691 | r0.intersect (r1); | |||
3692 | ASSERT_TRUE (r0.get_nonzero_bits () == 0xff)do { const char *desc_ = "ASSERT_TRUE (" "(r0.get_nonzero_bits () == 0xff)" ")"; bool actual_ = ((r0.get_nonzero_bits () == 0xff)); if ( actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3692, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3692, __FUNCTION__))), desc_); } while (0); | |||
3693 | ||||
3694 | // The union of a mask of 0xff..ffff00 with a mask of 0xff spans the | |||
3695 | // entire domain, and makes the range a varying. | |||
3696 | r0.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3697 | wide_int x = wi::shwi (0xff, TYPE_PRECISION (integer_type_node)((tree_class_check ((integer_types[itk_int]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3697, __FUNCTION__))->type_common.precision)); | |||
3698 | x = wi::bit_not (x); | |||
3699 | r0.set_nonzero_bits (x); // 0xff..ff00 | |||
3700 | r1.set_varying (integer_type_nodeinteger_types[itk_int]); | |||
3701 | r1.set_nonzero_bits (0xff); | |||
3702 | r0.union_ (r1); | |||
3703 | ASSERT_TRUE (r0.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.varying_p ())" ")" ; bool actual_ = ((r0.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3703, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3703, __FUNCTION__))), desc_); } while (0); | |||
3704 | ||||
3705 | // Test that setting a nonzero bit of 1 does not pessimize the range. | |||
3706 | r0.set_zero (integer_type_nodeinteger_types[itk_int]); | |||
3707 | r0.set_nonzero_bits (1); | |||
3708 | ASSERT_TRUE (r0.zero_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.zero_p ())" ")" ; bool actual_ = ((r0.zero_p ())); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3708, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3708, __FUNCTION__))), desc_); } while (0); | |||
3709 | } | |||
3710 | ||||
3711 | // Build an frange from string endpoints. | |||
3712 | ||||
3713 | static inline frange | |||
3714 | frange_float (const char *lb, const char *ub, tree type = float_type_nodeglobal_trees[TI_FLOAT_TYPE]) | |||
3715 | { | |||
3716 | REAL_VALUE_TYPEstruct real_value min, max; | |||
3717 | gcc_assert (real_from_string (&min, lb) == 0)((void)(!(real_from_string (&min, lb) == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3717, __FUNCTION__), 0 : 0)); | |||
3718 | gcc_assert (real_from_string (&max, ub) == 0)((void)(!(real_from_string (&max, ub) == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3718, __FUNCTION__), 0 : 0)); | |||
3719 | return frange (type, min, max); | |||
3720 | } | |||
3721 | ||||
3722 | static void | |||
3723 | range_tests_nan () | |||
3724 | { | |||
3725 | frange r0, r1; | |||
3726 | REAL_VALUE_TYPEstruct real_value q, r; | |||
3727 | bool signbit; | |||
3728 | ||||
3729 | // Equal ranges but with differing NAN bits are not equal. | |||
3730 | if (HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3731 | { | |||
3732 | r1 = frange_float ("10", "12"); | |||
3733 | r0 = r1; | |||
3734 | ASSERT_EQ (r0, r1)do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(r1)" ")" ; if (((r0)) == ((r1))) ::selftest::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3734, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3734, __FUNCTION__)))), desc_); } while (0); | |||
3735 | r0.clear_nan (); | |||
3736 | ASSERT_NE (r0, r1)do { const char *desc_ = "ASSERT_NE (" "r0" ", " "r1" ")"; if ((r0) != (r1)) ::selftest::pass ((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3736, __FUNCTION__)), desc_); else ::selftest::fail ((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3736, __FUNCTION__)), desc_); } while (0); | |||
3737 | r0.update_nan (); | |||
3738 | ASSERT_EQ (r0, r1)do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(r1)" ")" ; if (((r0)) == ((r1))) ::selftest::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3738, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3738, __FUNCTION__)))), desc_); } while (0); | |||
3739 | ||||
3740 | // [10, 20] NAN ^ [30, 40] NAN = NAN. | |||
3741 | r0 = frange_float ("10", "20"); | |||
3742 | r1 = frange_float ("30", "40"); | |||
3743 | r0.intersect (r1); | |||
3744 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3744, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3744, __FUNCTION__))), desc_); } while (0); | |||
3745 | ||||
3746 | // [3,5] U [5,10] NAN = ... NAN | |||
3747 | r0 = frange_float ("3", "5"); | |||
3748 | r0.clear_nan (); | |||
3749 | r1 = frange_float ("5", "10"); | |||
3750 | r0.union_ (r1); | |||
3751 | ASSERT_TRUE (r0.maybe_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.maybe_isnan ())" ")"; bool actual_ = ((r0.maybe_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3751, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3751, __FUNCTION__))), desc_); } while (0); | |||
3752 | } | |||
3753 | ||||
3754 | // NAN ranges are not equal to each other. | |||
3755 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3756 | r1 = r0; | |||
3757 | ASSERT_FALSE (r0 == r1)do { const char *desc_ = "ASSERT_FALSE (" "(r0 == r1)" ")"; bool actual_ = ((r0 == r1)); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3757, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3757, __FUNCTION__))), desc_); } while (0); | |||
3758 | ASSERT_FALSE (r0 == r0)do { const char *desc_ = "ASSERT_FALSE (" "(r0 == r0)" ")"; bool actual_ = ((r0 == r0)); if (actual_) ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3758, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3758, __FUNCTION__))), desc_); } while (0); | |||
3759 | ASSERT_TRUE (r0 != r0)do { const char *desc_ = "ASSERT_TRUE (" "(r0 != r0)" ")"; bool actual_ = ((r0 != r0)); if (actual_) ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3759, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3759, __FUNCTION__))), desc_); } while (0); | |||
3760 | ||||
3761 | // [5,6] U NAN = [5,6] NAN. | |||
3762 | r0 = frange_float ("5", "6"); | |||
3763 | r0.clear_nan (); | |||
3764 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3765 | r0.union_ (r1); | |||
3766 | real_from_string (&q, "5"); | |||
3767 | real_from_string (&r, "6"); | |||
3768 | ASSERT_TRUE (real_identical (&q, &r0.lower_bound ()))do { const char *desc_ = "ASSERT_TRUE (" "(real_identical (&q, &r0.lower_bound ()))" ")"; bool actual_ = ((real_identical (&q, &r0.lower_bound ()))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3768, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3768, __FUNCTION__))), desc_); } while (0); | |||
3769 | ASSERT_TRUE (real_identical (&r, &r0.upper_bound ()))do { const char *desc_ = "ASSERT_TRUE (" "(real_identical (&r, &r0.upper_bound ()))" ")"; bool actual_ = ((real_identical (&r, &r0.upper_bound ()))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3769, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3769, __FUNCTION__))), desc_); } while (0); | |||
3770 | ASSERT_TRUE (r0.maybe_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.maybe_isnan ())" ")"; bool actual_ = ((r0.maybe_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3770, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3770, __FUNCTION__))), desc_); } while (0); | |||
3771 | ||||
3772 | // NAN U NAN = NAN | |||
3773 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3774 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3775 | r0.union_ (r1); | |||
3776 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3776, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3776, __FUNCTION__))), desc_); } while (0); | |||
3777 | ||||
3778 | // [INF, INF] NAN ^ NAN = NAN | |||
3779 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3780 | r1 = frange_float ("+Inf", "+Inf"); | |||
3781 | if (!HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3782 | r1.update_nan (); | |||
3783 | r0.intersect (r1); | |||
3784 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3784, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3784, __FUNCTION__))), desc_); } while (0); | |||
3785 | ||||
3786 | // NAN ^ NAN = NAN | |||
3787 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3788 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3789 | r0.intersect (r1); | |||
3790 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3790, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3790, __FUNCTION__))), desc_); } while (0); | |||
3791 | ||||
3792 | // +NAN ^ -NAN = UNDEFINED | |||
3793 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE], false); | |||
3794 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE], true); | |||
3795 | r0.intersect (r1); | |||
3796 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3796, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3796, __FUNCTION__))), desc_); } while (0); | |||
3797 | ||||
3798 | // VARYING ^ NAN = NAN. | |||
3799 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3800 | r1.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3801 | r0.intersect (r1); | |||
3802 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3802, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3802, __FUNCTION__))), desc_); } while (0); | |||
3803 | ||||
3804 | // [3,4] ^ NAN = UNDEFINED. | |||
3805 | r0 = frange_float ("3", "4"); | |||
3806 | r0.clear_nan (); | |||
3807 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3808 | r0.intersect (r1); | |||
3809 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3809, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3809, __FUNCTION__))), desc_); } while (0); | |||
3810 | ||||
3811 | // [-3, 5] ^ NAN = UNDEFINED | |||
3812 | r0 = frange_float ("-3", "5"); | |||
3813 | r0.clear_nan (); | |||
3814 | r1.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3815 | r0.intersect (r1); | |||
3816 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3816, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3816, __FUNCTION__))), desc_); } while (0); | |||
3817 | ||||
3818 | // Setting the NAN bit to yes does not make us a known NAN. | |||
3819 | r0.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3820 | r0.update_nan (); | |||
3821 | ASSERT_FALSE (r0.known_isnan ())do { const char *desc_ = "ASSERT_FALSE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3821, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3821, __FUNCTION__))), desc_); } while (0); | |||
3822 | ||||
3823 | // NAN is in a VARYING. | |||
3824 | r0.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3825 | real_nan (&r, "", 1, TYPE_MODE (float_type_node)((((enum tree_code) ((tree_class_check ((global_trees[TI_FLOAT_TYPE ]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3825, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (global_trees[TI_FLOAT_TYPE]) : (global_trees[TI_FLOAT_TYPE] )->type_common.mode)); | |||
3826 | tree nan = build_real (float_type_nodeglobal_trees[TI_FLOAT_TYPE], r); | |||
3827 | ASSERT_TRUE (r0.contains_p (nan))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (nan))" ")"; bool actual_ = ((r0.contains_p (nan))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3827, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3827, __FUNCTION__))), desc_); } while (0); | |||
3828 | ||||
3829 | // -NAN is in a VARYING. | |||
3830 | r0.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3831 | q = real_value_negate (&r); | |||
3832 | tree neg_nan = build_real (float_type_nodeglobal_trees[TI_FLOAT_TYPE], q); | |||
3833 | ASSERT_TRUE (r0.contains_p (neg_nan))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (neg_nan))" ")"; bool actual_ = ((r0.contains_p (neg_nan))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3833, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3833, __FUNCTION__))), desc_); } while (0); | |||
3834 | ||||
3835 | // Clearing the NAN on a [] NAN is the empty set. | |||
3836 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3837 | r0.clear_nan (); | |||
3838 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3838, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3838, __FUNCTION__))), desc_); } while (0); | |||
3839 | ||||
3840 | // [10,20] NAN ^ [21,25] NAN = [NAN] | |||
3841 | r0 = frange_float ("10", "20"); | |||
3842 | r0.update_nan (); | |||
3843 | r1 = frange_float ("21", "25"); | |||
3844 | r1.update_nan (); | |||
3845 | r0.intersect (r1); | |||
3846 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3846, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3846, __FUNCTION__))), desc_); } while (0); | |||
3847 | ||||
3848 | // NAN U [5,6] should be [5,6] +-NAN. | |||
3849 | r0.set_nan (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3850 | r1 = frange_float ("5", "6"); | |||
3851 | r1.clear_nan (); | |||
3852 | r0.union_ (r1); | |||
3853 | real_from_string (&q, "5"); | |||
3854 | real_from_string (&r, "6"); | |||
3855 | ASSERT_TRUE (real_identical (&q, &r0.lower_bound ()))do { const char *desc_ = "ASSERT_TRUE (" "(real_identical (&q, &r0.lower_bound ()))" ")"; bool actual_ = ((real_identical (&q, &r0.lower_bound ()))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3855, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3855, __FUNCTION__))), desc_); } while (0); | |||
3856 | ASSERT_TRUE (real_identical (&r, &r0.upper_bound ()))do { const char *desc_ = "ASSERT_TRUE (" "(real_identical (&r, &r0.upper_bound ()))" ")"; bool actual_ = ((real_identical (&r, &r0.upper_bound ()))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3856, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3856, __FUNCTION__))), desc_); } while (0); | |||
3857 | ASSERT_TRUE (!r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(!r0.signbit_p (signbit))" ")"; bool actual_ = ((!r0.signbit_p (signbit))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3857, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3857, __FUNCTION__))), desc_); } while (0); | |||
3858 | ASSERT_TRUE (r0.maybe_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.maybe_isnan ())" ")"; bool actual_ = ((r0.maybe_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3858, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3858, __FUNCTION__))), desc_); } while (0); | |||
3859 | } | |||
3860 | ||||
3861 | static void | |||
3862 | range_tests_signed_zeros () | |||
3863 | { | |||
3864 | tree zero = build_zero_cst (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3865 | tree neg_zero = fold_build1 (NEGATE_EXPR, float_type_node, zero)fold_build1_loc (((location_t) 0), NEGATE_EXPR, global_trees[ TI_FLOAT_TYPE], zero ); | |||
3866 | frange r0, r1; | |||
3867 | bool signbit; | |||
3868 | ||||
3869 | // [0,0] contains [0,0] but not [-0,-0] and vice versa. | |||
3870 | r0 = frange (zero, zero); | |||
3871 | r1 = frange (neg_zero, neg_zero); | |||
3872 | ASSERT_TRUE (r0.contains_p (zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (zero))" ")"; bool actual_ = ((r0.contains_p (zero))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3872, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3872, __FUNCTION__))), desc_); } while (0); | |||
3873 | ASSERT_TRUE (!r0.contains_p (neg_zero))do { const char *desc_ = "ASSERT_TRUE (" "(!r0.contains_p (neg_zero))" ")"; bool actual_ = ((!r0.contains_p (neg_zero))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3873, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3873, __FUNCTION__))), desc_); } while (0); | |||
3874 | ASSERT_TRUE (r1.contains_p (neg_zero))do { const char *desc_ = "ASSERT_TRUE (" "(r1.contains_p (neg_zero))" ")"; bool actual_ = ((r1.contains_p (neg_zero))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3874, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3874, __FUNCTION__))), desc_); } while (0); | |||
3875 | ASSERT_TRUE (!r1.contains_p (zero))do { const char *desc_ = "ASSERT_TRUE (" "(!r1.contains_p (zero))" ")"; bool actual_ = ((!r1.contains_p (zero))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3875, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3875, __FUNCTION__))), desc_); } while (0); | |||
3876 | ||||
3877 | // Test contains_p() when we know the sign of the zero. | |||
3878 | r0 = frange (zero, zero); | |||
3879 | ASSERT_TRUE (r0.contains_p (zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (zero))" ")"; bool actual_ = ((r0.contains_p (zero))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3879, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3879, __FUNCTION__))), desc_); } while (0); | |||
3880 | ASSERT_FALSE (r0.contains_p (neg_zero))do { const char *desc_ = "ASSERT_FALSE (" "(r0.contains_p (neg_zero))" ")"; bool actual_ = ((r0.contains_p (neg_zero))); if (actual_ ) ::selftest::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3880, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3880, __FUNCTION__))), desc_); } while (0); | |||
3881 | r0 = frange (neg_zero, neg_zero); | |||
3882 | ASSERT_TRUE (r0.contains_p (neg_zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (neg_zero))" ")"; bool actual_ = ((r0.contains_p (neg_zero))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3882, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3882, __FUNCTION__))), desc_); } while (0); | |||
3883 | ASSERT_FALSE (r0.contains_p (zero))do { const char *desc_ = "ASSERT_FALSE (" "(r0.contains_p (zero))" ")"; bool actual_ = ((r0.contains_p (zero))); if (actual_) :: selftest::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3883, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3883, __FUNCTION__))), desc_); } while (0); | |||
3884 | ||||
3885 | r0 = frange (neg_zero, zero); | |||
3886 | ASSERT_TRUE (r0.contains_p (neg_zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (neg_zero))" ")"; bool actual_ = ((r0.contains_p (neg_zero))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3886, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3886, __FUNCTION__))), desc_); } while (0); | |||
3887 | ASSERT_TRUE (r0.contains_p (zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (zero))" ")"; bool actual_ = ((r0.contains_p (zero))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3887, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3887, __FUNCTION__))), desc_); } while (0); | |||
3888 | ||||
3889 | r0 = frange_float ("-3", "5"); | |||
3890 | ASSERT_TRUE (r0.contains_p (neg_zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (neg_zero))" ")"; bool actual_ = ((r0.contains_p (neg_zero))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3890, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3890, __FUNCTION__))), desc_); } while (0); | |||
3891 | ASSERT_TRUE (r0.contains_p (zero))do { const char *desc_ = "ASSERT_TRUE (" "(r0.contains_p (zero))" ")"; bool actual_ = ((r0.contains_p (zero))); if (actual_) :: selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3891, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3891, __FUNCTION__))), desc_); } while (0); | |||
3892 | ||||
3893 | // The intersection of zeros that differ in sign is a NAN (or | |||
3894 | // undefined if not honoring NANs). | |||
3895 | r0 = frange (neg_zero, neg_zero); | |||
3896 | r1 = frange (zero, zero); | |||
3897 | r0.intersect (r1); | |||
3898 | if (HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3899 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3899, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3899, __FUNCTION__))), desc_); } while (0); | |||
3900 | else | |||
3901 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3901, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3901, __FUNCTION__))), desc_); } while (0); | |||
3902 | ||||
3903 | // The union of zeros that differ in sign is a zero with unknown sign. | |||
3904 | r0 = frange (zero, zero); | |||
3905 | r1 = frange (neg_zero, neg_zero); | |||
3906 | r0.union_ (r1); | |||
3907 | ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(r0.zero_p () && !r0.signbit_p (signbit))" ")"; bool actual_ = ((r0.zero_p () && !r0.signbit_p ( signbit))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3907, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3907, __FUNCTION__))), desc_); } while (0); | |||
3908 | ||||
3909 | // [-0, +0] has an unknown sign. | |||
3910 | r0 = frange (neg_zero, zero); | |||
3911 | ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(r0.zero_p () && !r0.signbit_p (signbit))" ")"; bool actual_ = ((r0.zero_p () && !r0.signbit_p ( signbit))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3911, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3911, __FUNCTION__))), desc_); } while (0); | |||
3912 | ||||
3913 | // [-0, +0] ^ [0, 0] is [0, 0] | |||
3914 | r0 = frange (neg_zero, zero); | |||
3915 | r1 = frange (zero, zero); | |||
3916 | r0.intersect (r1); | |||
3917 | ASSERT_TRUE (r0.zero_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.zero_p ())" ")" ; bool actual_ = ((r0.zero_p ())); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3917, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3917, __FUNCTION__))), desc_); } while (0); | |||
3918 | ||||
3919 | r0 = frange_float ("+0", "5"); | |||
3920 | r0.clear_nan (); | |||
3921 | ASSERT_TRUE (r0.signbit_p (signbit) && !signbit)do { const char *desc_ = "ASSERT_TRUE (" "(r0.signbit_p (signbit) && !signbit)" ")"; bool actual_ = ((r0.signbit_p (signbit) && !signbit )); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3921, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3921, __FUNCTION__))), desc_); } while (0); | |||
3922 | ||||
3923 | r0 = frange_float ("-0", "5"); | |||
3924 | r0.clear_nan (); | |||
3925 | ASSERT_TRUE (!r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(!r0.signbit_p (signbit))" ")"; bool actual_ = ((!r0.signbit_p (signbit))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3925, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3925, __FUNCTION__))), desc_); } while (0); | |||
3926 | ||||
3927 | r0 = frange_float ("-0", "10"); | |||
3928 | r1 = frange_float ("0", "5"); | |||
3929 | r0.intersect (r1); | |||
3930 | ASSERT_TRUE (real_iszero (&r0.lower_bound (), false))do { const char *desc_ = "ASSERT_TRUE (" "(real_iszero (&r0.lower_bound (), false))" ")"; bool actual_ = ((real_iszero (&r0.lower_bound (), false ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3930, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3930, __FUNCTION__))), desc_); } while (0); | |||
3931 | ||||
3932 | r0 = frange_float ("-0", "5"); | |||
3933 | r1 = frange_float ("0", "5"); | |||
3934 | r0.union_ (r1); | |||
3935 | ASSERT_TRUE (real_iszero (&r0.lower_bound (), true))do { const char *desc_ = "ASSERT_TRUE (" "(real_iszero (&r0.lower_bound (), true))" ")"; bool actual_ = ((real_iszero (&r0.lower_bound (), true ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3935, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3935, __FUNCTION__))), desc_); } while (0); | |||
3936 | ||||
3937 | r0 = frange_float ("-5", "-0"); | |||
3938 | r0.update_nan (); | |||
3939 | r1 = frange_float ("0", "0"); | |||
3940 | r1.update_nan (); | |||
3941 | r0.intersect (r1); | |||
3942 | if (HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3943 | ASSERT_TRUE (r0.known_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.known_isnan ())" ")"; bool actual_ = ((r0.known_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3943, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3943, __FUNCTION__))), desc_); } while (0); | |||
3944 | else | |||
3945 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3945, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3945, __FUNCTION__))), desc_); } while (0); | |||
3946 | ||||
3947 | r0.set_nonnegative (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3948 | if (HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3949 | ASSERT_TRUE (r0.maybe_isnan ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.maybe_isnan ())" ")"; bool actual_ = ((r0.maybe_isnan ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3949, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3949, __FUNCTION__))), desc_); } while (0); | |||
3950 | ||||
3951 | // Numbers containing zero should have an unknown SIGNBIT. | |||
3952 | r0 = frange_float ("0", "10"); | |||
3953 | r0.clear_nan (); | |||
3954 | ASSERT_TRUE (r0.signbit_p (signbit) && !signbit)do { const char *desc_ = "ASSERT_TRUE (" "(r0.signbit_p (signbit) && !signbit)" ")"; bool actual_ = ((r0.signbit_p (signbit) && !signbit )); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3954, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3954, __FUNCTION__))), desc_); } while (0); | |||
3955 | } | |||
3956 | ||||
3957 | static void | |||
3958 | range_tests_signbit () | |||
3959 | { | |||
3960 | frange r0, r1; | |||
3961 | bool signbit; | |||
3962 | ||||
3963 | // Negative numbers should have the SIGNBIT set. | |||
3964 | r0 = frange_float ("-5", "-1"); | |||
3965 | r0.clear_nan (); | |||
3966 | ASSERT_TRUE (r0.signbit_p (signbit) && signbit)do { const char *desc_ = "ASSERT_TRUE (" "(r0.signbit_p (signbit) && signbit)" ")"; bool actual_ = ((r0.signbit_p (signbit) && signbit )); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3966, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3966, __FUNCTION__))), desc_); } while (0); | |||
3967 | // Positive numbers should have the SIGNBIT clear. | |||
3968 | r0 = frange_float ("1", "10"); | |||
3969 | r0.clear_nan (); | |||
3970 | ASSERT_TRUE (r0.signbit_p (signbit) && !signbit)do { const char *desc_ = "ASSERT_TRUE (" "(r0.signbit_p (signbit) && !signbit)" ")"; bool actual_ = ((r0.signbit_p (signbit) && !signbit )); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3970, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3970, __FUNCTION__))), desc_); } while (0); | |||
3971 | // Numbers spanning both positive and negative should have an | |||
3972 | // unknown SIGNBIT. | |||
3973 | r0 = frange_float ("-10", "10"); | |||
3974 | r0.clear_nan (); | |||
3975 | ASSERT_TRUE (!r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(!r0.signbit_p (signbit))" ")"; bool actual_ = ((!r0.signbit_p (signbit))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3975, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3975, __FUNCTION__))), desc_); } while (0); | |||
3976 | r0.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
3977 | ASSERT_TRUE (!r0.signbit_p (signbit))do { const char *desc_ = "ASSERT_TRUE (" "(!r0.signbit_p (signbit))" ")"; bool actual_ = ((!r0.signbit_p (signbit))); if (actual_ ) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3977, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3977, __FUNCTION__))), desc_); } while (0); | |||
3978 | } | |||
3979 | ||||
3980 | static void | |||
3981 | range_tests_floats () | |||
3982 | { | |||
3983 | frange r0, r1; | |||
3984 | ||||
3985 | if (HONOR_NANS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3986 | range_tests_nan (); | |||
3987 | range_tests_signbit (); | |||
3988 | ||||
3989 | if (HONOR_SIGNED_ZEROS (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
3990 | range_tests_signed_zeros (); | |||
3991 | ||||
3992 | // A range of [-INF,+INF] is actually VARYING if no other properties | |||
3993 | // are set. | |||
3994 | r0 = frange_float ("-Inf", "+Inf"); | |||
3995 | ASSERT_TRUE (r0.varying_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.varying_p ())" ")" ; bool actual_ = ((r0.varying_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3995, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 3995, __FUNCTION__))), desc_); } while (0); | |||
3996 | // ...unless it has some special property... | |||
3997 | if (HONOR_NANS (r0.type ())) | |||
3998 | { | |||
3999 | r0.clear_nan (); | |||
4000 | ASSERT_FALSE (r0.varying_p ())do { const char *desc_ = "ASSERT_FALSE (" "(r0.varying_p ())" ")"; bool actual_ = ((r0.varying_p ())); if (actual_) ::selftest ::fail (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4000, __FUNCTION__))), desc_); else ::selftest::pass (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4000, __FUNCTION__))), desc_); } while (0); | |||
4001 | } | |||
4002 | ||||
4003 | // For most architectures, where float and double are different | |||
4004 | // sizes, having the same endpoints does not necessarily mean the | |||
4005 | // ranges are equal. | |||
4006 | if (!types_compatible_p (float_type_nodeglobal_trees[TI_FLOAT_TYPE], double_type_nodeglobal_trees[TI_DOUBLE_TYPE])) | |||
4007 | { | |||
4008 | r0 = frange_float ("3.0", "3.0", float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
4009 | r1 = frange_float ("3.0", "3.0", double_type_nodeglobal_trees[TI_DOUBLE_TYPE]); | |||
4010 | ASSERT_NE (r0, r1)do { const char *desc_ = "ASSERT_NE (" "r0" ", " "r1" ")"; if ((r0) != (r1)) ::selftest::pass ((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4010, __FUNCTION__)), desc_); else ::selftest::fail ((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4010, __FUNCTION__)), desc_); } while (0); | |||
4011 | } | |||
4012 | ||||
4013 | // [3,5] U [10,12] = [3,12]. | |||
4014 | r0 = frange_float ("3", "5"); | |||
4015 | r1 = frange_float ("10", "12"); | |||
4016 | r0.union_ (r1); | |||
4017 | ASSERT_EQ (r0, frange_float ("3", "12"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"3\", \"12\"))" ")"; if (((r0)) == ((frange_float ("3", "12")))) ::selftest:: pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4017, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4017, __FUNCTION__)))), desc_); } while (0); | |||
4018 | ||||
4019 | // [5,10] U [4,8] = [4,10] | |||
4020 | r0 = frange_float ("5", "10"); | |||
4021 | r1 = frange_float ("4", "8"); | |||
4022 | r0.union_ (r1); | |||
4023 | ASSERT_EQ (r0, frange_float ("4", "10"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"4\", \"10\"))" ")"; if (((r0)) == ((frange_float ("4", "10")))) ::selftest:: pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4023, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4023, __FUNCTION__)))), desc_); } while (0); | |||
4024 | ||||
4025 | // [3,5] U [4,10] = [3,10] | |||
4026 | r0 = frange_float ("3", "5"); | |||
4027 | r1 = frange_float ("4", "10"); | |||
4028 | r0.union_ (r1); | |||
4029 | ASSERT_EQ (r0, frange_float ("3", "10"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"3\", \"10\"))" ")"; if (((r0)) == ((frange_float ("3", "10")))) ::selftest:: pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4029, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4029, __FUNCTION__)))), desc_); } while (0); | |||
4030 | ||||
4031 | // [4,10] U [5,11] = [4,11] | |||
4032 | r0 = frange_float ("4", "10"); | |||
4033 | r1 = frange_float ("5", "11"); | |||
4034 | r0.union_ (r1); | |||
4035 | ASSERT_EQ (r0, frange_float ("4", "11"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"4\", \"11\"))" ")"; if (((r0)) == ((frange_float ("4", "11")))) ::selftest:: pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4035, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4035, __FUNCTION__)))), desc_); } while (0); | |||
4036 | ||||
4037 | // [3,12] ^ [10,12] = [10,12]. | |||
4038 | r0 = frange_float ("3", "12"); | |||
4039 | r1 = frange_float ("10", "12"); | |||
4040 | r0.intersect (r1); | |||
4041 | ASSERT_EQ (r0, frange_float ("10", "12"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"10\", \"12\"))" ")"; if (((r0)) == ((frange_float ("10", "12")))) ::selftest ::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4041, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4041, __FUNCTION__)))), desc_); } while (0); | |||
4042 | ||||
4043 | // [10,12] ^ [11,11] = [11,11] | |||
4044 | r0 = frange_float ("10", "12"); | |||
4045 | r1 = frange_float ("11", "11"); | |||
4046 | r0.intersect (r1); | |||
4047 | ASSERT_EQ (r0, frange_float ("11", "11"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"11\", \"11\"))" ")"; if (((r0)) == ((frange_float ("11", "11")))) ::selftest ::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4047, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4047, __FUNCTION__)))), desc_); } while (0); | |||
4048 | ||||
4049 | // [10,20] ^ [5,15] = [10,15] | |||
4050 | r0 = frange_float ("10", "20"); | |||
4051 | r1 = frange_float ("5", "15"); | |||
4052 | r0.intersect (r1); | |||
4053 | ASSERT_EQ (r0, frange_float ("10", "15"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"10\", \"15\"))" ")"; if (((r0)) == ((frange_float ("10", "15")))) ::selftest ::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4053, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4053, __FUNCTION__)))), desc_); } while (0); | |||
4054 | ||||
4055 | // [10,20] ^ [15,25] = [15,20] | |||
4056 | r0 = frange_float ("10", "20"); | |||
4057 | r1 = frange_float ("15", "25"); | |||
4058 | r0.intersect (r1); | |||
4059 | ASSERT_EQ (r0, frange_float ("15", "20"))do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(frange_float (\"15\", \"20\"))" ")"; if (((r0)) == ((frange_float ("15", "20")))) ::selftest ::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4059, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4059, __FUNCTION__)))), desc_); } while (0); | |||
4060 | ||||
4061 | // [10,20] ^ [21,25] = [] | |||
4062 | r0 = frange_float ("10", "20"); | |||
4063 | r0.clear_nan (); | |||
4064 | r1 = frange_float ("21", "25"); | |||
4065 | r1.clear_nan (); | |||
4066 | r0.intersect (r1); | |||
4067 | ASSERT_TRUE (r0.undefined_p ())do { const char *desc_ = "ASSERT_TRUE (" "(r0.undefined_p ())" ")"; bool actual_ = ((r0.undefined_p ())); if (actual_) ::selftest ::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4067, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4067, __FUNCTION__))), desc_); } while (0); | |||
4068 | ||||
4069 | if (HONOR_INFINITIES (float_type_nodeglobal_trees[TI_FLOAT_TYPE])) | |||
4070 | { | |||
4071 | // Make sure [-Inf, -Inf] doesn't get normalized. | |||
4072 | r0 = frange_float ("-Inf", "-Inf"); | |||
4073 | ASSERT_TRUE (real_isinf (&r0.lower_bound (), true))do { const char *desc_ = "ASSERT_TRUE (" "(real_isinf (&r0.lower_bound (), true))" ")"; bool actual_ = ((real_isinf (&r0.lower_bound (), true ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4073, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4073, __FUNCTION__))), desc_); } while (0); | |||
4074 | ASSERT_TRUE (real_isinf (&r0.upper_bound (), true))do { const char *desc_ = "ASSERT_TRUE (" "(real_isinf (&r0.upper_bound (), true))" ")"; bool actual_ = ((real_isinf (&r0.upper_bound (), true ))); if (actual_) ::selftest::pass (((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4074, __FUNCTION__))), desc_); else ::selftest::fail (((::selftest ::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4074, __FUNCTION__))), desc_); } while (0); | |||
4075 | } | |||
4076 | ||||
4077 | // Test that reading back a global range yields the same result as | |||
4078 | // what we wrote into it. | |||
4079 | tree ssa = make_temp_ssa_name (float_type_nodeglobal_trees[TI_FLOAT_TYPE], NULLnullptr, "blah"); | |||
4080 | r0.set_varying (float_type_nodeglobal_trees[TI_FLOAT_TYPE]); | |||
4081 | r0.clear_nan (); | |||
4082 | set_range_info (ssa, r0); | |||
4083 | get_global_range_query ()->range_of_expr (r1, ssa); | |||
4084 | ASSERT_EQ (r0, r1)do { const char *desc_ = "ASSERT_EQ (" "(r0)" ", " "(r1)" ")" ; if (((r0)) == ((r1))) ::selftest::pass ((((::selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4084, __FUNCTION__)))), desc_); else ::selftest::fail ((((:: selftest::location ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.cc" , 4084, __FUNCTION__)))), desc_); } while (0); | |||
4085 | } | |||
4086 | ||||
4087 | // Run floating range tests for various combinations of NAN and INF | |||
4088 | // support. | |||
4089 | ||||
4090 | static void | |||
4091 | range_tests_floats_various () | |||
4092 | { | |||
4093 | int save_finite_math_only = flag_finite_math_onlyglobal_options.x_flag_finite_math_only; | |||
4094 | ||||
4095 | // Test -ffinite-math-only. | |||
4096 | flag_finite_math_onlyglobal_options.x_flag_finite_math_only = 1; | |||
4097 | range_tests_floats (); | |||
4098 | // Test -fno-finite-math-only. | |||
4099 | flag_finite_math_onlyglobal_options.x_flag_finite_math_only = 0; | |||
4100 | range_tests_floats (); | |||
4101 | ||||
4102 | flag_finite_math_onlyglobal_options.x_flag_finite_math_only = save_finite_math_only; | |||
4103 | } | |||
4104 | ||||
4105 | void | |||
4106 | range_tests () | |||
4107 | { | |||
4108 | range_tests_legacy (); | |||
4109 | range_tests_irange3 (); | |||
| ||||
4110 | range_tests_int_range_max (); | |||
4111 | range_tests_strict_enum (); | |||
4112 | range_tests_nonzero_bits (); | |||
4113 | range_tests_floats_various (); | |||
4114 | range_tests_misc (); | |||
4115 | } | |||
4116 | ||||
4117 | } // namespace selftest | |||
4118 | ||||
4119 | #endif // CHECKING_P |
1 | /* Support routines for value ranges. | |||
2 | Copyright (C) 2019-2023 Free Software Foundation, Inc. | |||
3 | Contributed by Aldy Hernandez <aldyh@redhat.com> and | |||
4 | Andrew Macleod <amacleod@redhat.com>. | |||
5 | ||||
6 | This file is part of GCC. | |||
7 | ||||
8 | GCC is free software; you can redistribute it and/or modify | |||
9 | it under the terms of the GNU General Public License as published by | |||
10 | the Free Software Foundation; either version 3, or (at your option) | |||
11 | any later version. | |||
12 | ||||
13 | GCC is distributed in the hope that it will be useful, | |||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
16 | GNU General Public License for more details. | |||
17 | ||||
18 | You should have received a copy of the GNU General Public License | |||
19 | along with GCC; see the file COPYING3. If not see | |||
20 | <http://www.gnu.org/licenses/>. */ | |||
21 | ||||
22 | #ifndef GCC_VALUE_RANGE_H | |||
23 | #define GCC_VALUE_RANGE_H | |||
24 | ||||
25 | class irange; | |||
26 | ||||
27 | // Types of value ranges. | |||
28 | enum value_range_kind | |||
29 | { | |||
30 | /* Empty range. */ | |||
31 | VR_UNDEFINED, | |||
32 | /* Range spans the entire domain. */ | |||
33 | VR_VARYING, | |||
34 | /* Range is [MIN, MAX]. */ | |||
35 | VR_RANGE, | |||
36 | /* Range is ~[MIN, MAX]. */ | |||
37 | VR_ANTI_RANGE, | |||
38 | /* Range is a NAN. */ | |||
39 | VR_NAN, | |||
40 | /* Range is a nice guy. */ | |||
41 | VR_LAST | |||
42 | }; | |||
43 | ||||
44 | // Discriminator between different vrange types. | |||
45 | ||||
46 | enum value_range_discriminator | |||
47 | { | |||
48 | // Range holds an integer or pointer. | |||
49 | VR_IRANGE, | |||
50 | // Floating point range. | |||
51 | VR_FRANGE, | |||
52 | // Range holds an unsupported type. | |||
53 | VR_UNKNOWN | |||
54 | }; | |||
55 | ||||
56 | // Abstract class for ranges of any of the supported types. | |||
57 | // | |||
58 | // To query what types ranger and the entire ecosystem can support, | |||
59 | // use Value_Range::supports_type_p(tree type). This is a static | |||
60 | // method available independently of any vrange object. | |||
61 | // | |||
62 | // To query what a given vrange variant can support, use: | |||
63 | // irange::supports_p () | |||
64 | // frange::supports_p () | |||
65 | // etc | |||
66 | // | |||
67 | // To query what a range object can support, use: | |||
68 | // void foo (vrange &v, irange &i, frange &f) | |||
69 | // { | |||
70 | // if (v.supports_type_p (type)) ... | |||
71 | // if (i.supports_type_p (type)) ... | |||
72 | // if (f.supports_type_p (type)) ... | |||
73 | // } | |||
74 | ||||
75 | class vrange | |||
76 | { | |||
77 | template <typename T> friend bool is_a (vrange &); | |||
78 | friend class Value_Range; | |||
79 | public: | |||
80 | virtual void accept (const class vrange_visitor &v) const = 0; | |||
81 | virtual void set (tree, tree, value_range_kind = VR_RANGE); | |||
82 | virtual tree type () const; | |||
83 | virtual bool supports_type_p (const_tree type) const; | |||
84 | virtual void set_varying (tree type); | |||
85 | virtual void set_undefined (); | |||
86 | virtual bool union_ (const vrange &); | |||
87 | virtual bool intersect (const vrange &); | |||
88 | virtual bool singleton_p (tree *result = NULLnullptr) const; | |||
89 | virtual bool contains_p (tree cst) const; | |||
90 | virtual bool zero_p () const; | |||
91 | virtual bool nonzero_p () const; | |||
92 | virtual void set_nonzero (tree type); | |||
93 | virtual void set_zero (tree type); | |||
94 | virtual void set_nonnegative (tree type); | |||
95 | virtual bool fits_p (const vrange &r) const; | |||
96 | ||||
97 | bool varying_p () const; | |||
98 | bool undefined_p () const; | |||
99 | vrange& operator= (const vrange &); | |||
100 | bool operator== (const vrange &) const; | |||
101 | bool operator!= (const vrange &r) const { return !(*this == r); } | |||
102 | void dump (FILE *) const; | |||
103 | ||||
104 | enum value_range_kind kind () const; // DEPRECATED | |||
105 | ||||
106 | protected: | |||
107 | ENUM_BITFIELD(value_range_kind)enum value_range_kind m_kind : 8; | |||
108 | ENUM_BITFIELD(value_range_discriminator)enum value_range_discriminator m_discriminator : 4; | |||
109 | }; | |||
110 | ||||
111 | // An integer range without any storage. | |||
112 | ||||
113 | class GTY((user)) irange : public vrange | |||
114 | { | |||
115 | friend class vrange_allocator; | |||
116 | friend class irange_storage_slot; // For legacy_mode_p checks. | |||
117 | public: | |||
118 | // In-place setters. | |||
119 | virtual void set (tree, tree, value_range_kind = VR_RANGE) override; | |||
120 | void set (tree type, const wide_int_ref &, const wide_int_ref &, | |||
121 | value_range_kind = VR_RANGE); | |||
122 | virtual void set_nonzero (tree type) override; | |||
123 | virtual void set_zero (tree type) override; | |||
124 | virtual void set_nonnegative (tree type) override; | |||
125 | virtual void set_varying (tree type) override; | |||
126 | virtual void set_undefined () override; | |||
127 | ||||
128 | // Range types. | |||
129 | static bool supports_p (const_tree type); | |||
130 | virtual bool supports_type_p (const_tree type) const override; | |||
131 | virtual tree type () const override; | |||
132 | ||||
133 | // Iteration over sub-ranges. | |||
134 | unsigned num_pairs () const; | |||
135 | wide_int lower_bound (unsigned = 0) const; | |||
136 | wide_int upper_bound (unsigned) const; | |||
137 | wide_int upper_bound () const; | |||
138 | ||||
139 | // Predicates. | |||
140 | virtual bool zero_p () const override; | |||
141 | virtual bool nonzero_p () const override; | |||
142 | virtual bool singleton_p (tree *result = NULLnullptr) const override; | |||
143 | virtual bool contains_p (tree cst) const override; | |||
144 | ||||
145 | // In-place operators. | |||
146 | virtual bool union_ (const vrange &) override; | |||
147 | virtual bool intersect (const vrange &) override; | |||
148 | void invert (); | |||
149 | ||||
150 | // Operator overloads. | |||
151 | irange& operator= (const irange &); | |||
152 | bool operator== (const irange &) const; | |||
153 | bool operator!= (const irange &r) const { return !(*this == r); } | |||
154 | ||||
155 | // Misc methods. | |||
156 | virtual bool fits_p (const vrange &r) const override; | |||
157 | virtual void accept (const vrange_visitor &v) const override; | |||
158 | ||||
159 | // Nonzero masks. | |||
160 | wide_int get_nonzero_bits () const; | |||
161 | void set_nonzero_bits (const wide_int_ref &bits); | |||
162 | ||||
163 | // Deprecated legacy public methods. | |||
164 | tree min () const; // DEPRECATED | |||
165 | tree max () const; // DEPRECATED | |||
166 | bool symbolic_p () const; // DEPRECATED | |||
167 | bool constant_p () const; // DEPRECATED | |||
168 | void normalize_symbolics (); // DEPRECATED | |||
169 | void normalize_addresses (); // DEPRECATED | |||
170 | bool may_contain_p (tree) const; // DEPRECATED | |||
171 | bool legacy_verbose_union_ (const class irange *); // DEPRECATED | |||
172 | bool legacy_verbose_intersect (const irange *); // DEPRECATED | |||
173 | ||||
174 | protected: | |||
175 | irange (tree *, unsigned); | |||
176 | // potential promotion to public? | |||
177 | tree tree_lower_bound (unsigned = 0) const; | |||
178 | tree tree_upper_bound (unsigned) const; | |||
179 | tree tree_upper_bound () const; | |||
180 | ||||
181 | // In-place operators. | |||
182 | bool irange_union (const irange &); | |||
183 | bool irange_intersect (const irange &); | |||
184 | void irange_set (tree, tree); | |||
185 | void irange_set_anti_range (tree, tree); | |||
186 | bool irange_contains_p (const irange &) const; | |||
187 | bool irange_single_pair_union (const irange &r); | |||
188 | ||||
189 | void normalize_kind (); | |||
190 | ||||
191 | bool legacy_mode_p () const; | |||
192 | bool legacy_equal_p (const irange &) const; | |||
193 | void legacy_union (irange *, const irange *); | |||
194 | void legacy_intersect (irange *, const irange *); | |||
195 | void verify_range (); | |||
196 | wide_int legacy_lower_bound (unsigned = 0) const; | |||
197 | wide_int legacy_upper_bound (unsigned) const; | |||
198 | int value_inside_range (tree) const; | |||
199 | bool maybe_anti_range () const; | |||
200 | void copy_to_legacy (const irange &); | |||
201 | void copy_legacy_to_multi_range (const irange &); | |||
202 | ||||
203 | private: | |||
204 | friend void gt_ggc_mx (irange *); | |||
205 | friend void gt_pch_nx (irange *); | |||
206 | friend void gt_pch_nx (irange *, gt_pointer_operator, void *); | |||
207 | ||||
208 | void irange_set_1bit_anti_range (tree, tree); | |||
209 | bool varying_compatible_p () const; | |||
210 | bool intersect_nonzero_bits (const irange &r); | |||
211 | bool union_nonzero_bits (const irange &r); | |||
212 | wide_int get_nonzero_bits_from_range () const; | |||
213 | bool set_range_from_nonzero_bits (); | |||
214 | ||||
215 | bool intersect (const wide_int& lb, const wide_int& ub); | |||
216 | unsigned char m_num_ranges; | |||
217 | unsigned char m_max_ranges; | |||
218 | tree m_nonzero_mask; | |||
219 | tree *m_base; | |||
220 | }; | |||
221 | ||||
222 | // Here we describe an irange with N pairs of ranges. The storage for | |||
223 | // the pairs is embedded in the class as an array. | |||
224 | ||||
225 | template<unsigned N> | |||
226 | class GTY((user)) int_range : public irange | |||
227 | { | |||
228 | public: | |||
229 | int_range (); | |||
230 | int_range (tree, tree, value_range_kind = VR_RANGE); | |||
231 | int_range (tree type, const wide_int &, const wide_int &, | |||
232 | value_range_kind = VR_RANGE); | |||
233 | int_range (tree type); | |||
234 | int_range (const int_range &); | |||
235 | int_range (const irange &); | |||
236 | virtual ~int_range () = default; | |||
237 | int_range& operator= (const int_range &); | |||
238 | private: | |||
239 | template <unsigned X> friend void gt_ggc_mx (int_range<X> *); | |||
240 | template <unsigned X> friend void gt_pch_nx (int_range<X> *); | |||
241 | template <unsigned X> friend void gt_pch_nx (int_range<X> *, | |||
242 | gt_pointer_operator, void *); | |||
243 | ||||
244 | // ?? These stubs are for ipa-prop.cc which use a value_range in a | |||
245 | // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &) | |||
246 | // instead of picking up the gt_ggc_mx (T *) version. | |||
247 | friend void gt_ggc_mx (int_range<1> *&); | |||
248 | friend void gt_pch_nx (int_range<1> *&); | |||
249 | ||||
250 | tree m_ranges[N*2]; | |||
251 | }; | |||
252 | ||||
253 | // Unsupported temporaries may be created by ranger before it's known | |||
254 | // they're unsupported, or by vr_values::get_value_range. | |||
255 | ||||
256 | class unsupported_range : public vrange | |||
257 | { | |||
258 | public: | |||
259 | unsupported_range () | |||
260 | { | |||
261 | m_discriminator = VR_UNKNOWN; | |||
262 | set_undefined (); | |||
263 | } | |||
264 | virtual void set_undefined () final override | |||
265 | { | |||
266 | m_kind = VR_UNDEFINED; | |||
267 | } | |||
268 | virtual void accept (const vrange_visitor &v) const override; | |||
269 | }; | |||
270 | ||||
271 | // The NAN state as an opaque object. The default constructor is +-NAN. | |||
272 | ||||
273 | class nan_state | |||
274 | { | |||
275 | public: | |||
276 | nan_state (); | |||
277 | nan_state (bool pos_nan, bool neg_nan); | |||
278 | bool neg_p () const; | |||
279 | bool pos_p () const; | |||
280 | private: | |||
281 | bool m_pos_nan; | |||
282 | bool m_neg_nan; | |||
283 | }; | |||
284 | ||||
285 | // Default constructor initializing the object to +-NAN. | |||
286 | ||||
287 | inline | |||
288 | nan_state::nan_state () | |||
289 | { | |||
290 | m_pos_nan = true; | |||
291 | m_neg_nan = true; | |||
292 | } | |||
293 | ||||
294 | // Constructor initializing the object to +NAN if POS_NAN is set, -NAN | |||
295 | // if NEG_NAN is set, or +-NAN if both are set. Otherwise POS_NAN and | |||
296 | // NEG_NAN are clear, and the object cannot be a NAN. | |||
297 | ||||
298 | inline | |||
299 | nan_state::nan_state (bool pos_nan, bool neg_nan) | |||
300 | { | |||
301 | m_pos_nan = pos_nan; | |||
302 | m_neg_nan = neg_nan; | |||
303 | } | |||
304 | ||||
305 | // Return if +NAN is possible. | |||
306 | ||||
307 | inline bool | |||
308 | nan_state::pos_p () const | |||
309 | { | |||
310 | return m_pos_nan; | |||
311 | } | |||
312 | ||||
313 | // Return if -NAN is possible. | |||
314 | ||||
315 | inline bool | |||
316 | nan_state::neg_p () const | |||
317 | { | |||
318 | return m_neg_nan; | |||
319 | } | |||
320 | ||||
321 | // A floating point range. | |||
322 | // | |||
323 | // The representation is a type with a couple of endpoints, unioned | |||
324 | // with the set of { -NAN, +Nan }. | |||
325 | ||||
326 | class frange : public vrange | |||
327 | { | |||
328 | friend class frange_storage_slot; | |||
329 | friend class vrange_printer; | |||
330 | public: | |||
331 | frange (); | |||
332 | frange (const frange &); | |||
333 | frange (tree, tree, value_range_kind = VR_RANGE); | |||
334 | frange (tree type); | |||
335 | frange (tree type, const REAL_VALUE_TYPEstruct real_value &min, const REAL_VALUE_TYPEstruct real_value &max, | |||
336 | value_range_kind = VR_RANGE); | |||
337 | static bool supports_p (const_tree type) | |||
338 | { | |||
339 | // ?? Decimal floats can have multiple representations for the | |||
340 | // same number. Supporting them may be as simple as just | |||
341 | // disabling them in singleton_p. No clue. | |||
342 | return SCALAR_FLOAT_TYPE_P (type)(((enum tree_code) (type)->base.code) == REAL_TYPE) && !DECIMAL_FLOAT_TYPE_P (type)((((enum tree_code) (type)->base.code) == REAL_TYPE) && (((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 342, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode)]) == MODE_DECIMAL_FLOAT )); | |||
343 | } | |||
344 | virtual tree type () const override; | |||
345 | virtual void set (tree, tree, value_range_kind = VR_RANGE) override; | |||
346 | void set (tree type, const REAL_VALUE_TYPEstruct real_value &, const REAL_VALUE_TYPEstruct real_value &, | |||
347 | value_range_kind = VR_RANGE); | |||
348 | void set (tree type, const REAL_VALUE_TYPEstruct real_value &, const REAL_VALUE_TYPEstruct real_value &, | |||
349 | const nan_state &, value_range_kind = VR_RANGE); | |||
350 | void set_nan (tree type); | |||
351 | void set_nan (tree type, bool sign); | |||
352 | virtual void set_varying (tree type) override; | |||
353 | virtual void set_undefined () override; | |||
354 | virtual bool union_ (const vrange &) override; | |||
355 | virtual bool intersect (const vrange &) override; | |||
356 | virtual bool contains_p (tree) const override; | |||
357 | virtual bool singleton_p (tree *result = NULLnullptr) const override; | |||
358 | virtual bool supports_type_p (const_tree type) const override; | |||
359 | virtual void accept (const vrange_visitor &v) const override; | |||
360 | virtual bool zero_p () const override; | |||
361 | virtual bool nonzero_p () const override; | |||
362 | virtual void set_nonzero (tree type) override; | |||
363 | virtual void set_zero (tree type) override; | |||
364 | virtual void set_nonnegative (tree type) override; | |||
365 | frange& operator= (const frange &); | |||
366 | bool operator== (const frange &) const; | |||
367 | bool operator!= (const frange &r) const { return !(*this == r); } | |||
368 | const REAL_VALUE_TYPEstruct real_value &lower_bound () const; | |||
369 | const REAL_VALUE_TYPEstruct real_value &upper_bound () const; | |||
370 | nan_state get_nan_state () const; | |||
371 | void update_nan (); | |||
372 | void update_nan (bool sign); | |||
373 | void update_nan (tree) = delete; // Disallow silent conversion to bool. | |||
374 | void update_nan (const nan_state &); | |||
375 | void clear_nan (); | |||
376 | ||||
377 | // fpclassify like API | |||
378 | bool known_isfinite () const; | |||
379 | bool known_isnan () const; | |||
380 | bool known_isinf () const; | |||
381 | bool maybe_isnan () const; | |||
382 | bool maybe_isnan (bool sign) const; | |||
383 | bool maybe_isinf () const; | |||
384 | bool signbit_p (bool &signbit) const; | |||
385 | bool nan_signbit_p (bool &signbit) const; | |||
386 | private: | |||
387 | void verify_range (); | |||
388 | bool normalize_kind (); | |||
389 | bool union_nans (const frange &); | |||
390 | bool intersect_nans (const frange &); | |||
391 | bool combine_zeros (const frange &, bool union_p); | |||
392 | void flush_denormals_to_zero (); | |||
393 | ||||
394 | tree m_type; | |||
395 | REAL_VALUE_TYPEstruct real_value m_min; | |||
396 | REAL_VALUE_TYPEstruct real_value m_max; | |||
397 | bool m_pos_nan; | |||
398 | bool m_neg_nan; | |||
399 | }; | |||
400 | ||||
401 | inline const REAL_VALUE_TYPEstruct real_value & | |||
402 | frange::lower_bound () const | |||
403 | { | |||
404 | gcc_checking_assert (!undefined_p () && !known_isnan ())((void)(!(!undefined_p () && !known_isnan ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 404, __FUNCTION__), 0 : 0)); | |||
405 | return m_min; | |||
406 | } | |||
407 | ||||
408 | inline const REAL_VALUE_TYPEstruct real_value & | |||
409 | frange::upper_bound () const | |||
410 | { | |||
411 | gcc_checking_assert (!undefined_p () && !known_isnan ())((void)(!(!undefined_p () && !known_isnan ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 411, __FUNCTION__), 0 : 0)); | |||
412 | return m_max; | |||
413 | } | |||
414 | ||||
415 | // Return the NAN state. | |||
416 | ||||
417 | inline nan_state | |||
418 | frange::get_nan_state () const | |||
419 | { | |||
420 | return nan_state (m_pos_nan, m_neg_nan); | |||
421 | } | |||
422 | ||||
423 | // is_a<> and as_a<> implementation for vrange. | |||
424 | ||||
425 | // Anything we haven't specialized is a hard fail. | |||
426 | template <typename T> | |||
427 | inline bool | |||
428 | is_a (vrange &) | |||
429 | { | |||
430 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 430, __FUNCTION__)); | |||
431 | return false; | |||
432 | } | |||
433 | ||||
434 | template <typename T> | |||
435 | inline bool | |||
436 | is_a (const vrange &v) | |||
437 | { | |||
438 | // Reuse is_a <vrange> to implement the const version. | |||
439 | const T &derived = static_cast<const T &> (v); | |||
440 | return is_a <T> (const_cast<T &> (derived)); | |||
441 | } | |||
442 | ||||
443 | template <typename T> | |||
444 | inline T & | |||
445 | as_a (vrange &v) | |||
446 | { | |||
447 | gcc_checking_assert (is_a <T> (v))((void)(!(is_a <T> (v)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 447, __FUNCTION__), 0 : 0)); | |||
448 | return static_cast <T &> (v); | |||
449 | } | |||
450 | ||||
451 | template <typename T> | |||
452 | inline const T & | |||
453 | as_a (const vrange &v) | |||
454 | { | |||
455 | gcc_checking_assert (is_a <T> (v))((void)(!(is_a <T> (v)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 455, __FUNCTION__), 0 : 0)); | |||
456 | return static_cast <const T &> (v); | |||
457 | } | |||
458 | ||||
459 | // Specializations for the different range types. | |||
460 | ||||
461 | template <> | |||
462 | inline bool | |||
463 | is_a <irange> (vrange &v) | |||
464 | { | |||
465 | return v.m_discriminator == VR_IRANGE; | |||
466 | } | |||
467 | ||||
468 | template <> | |||
469 | inline bool | |||
470 | is_a <frange> (vrange &v) | |||
471 | { | |||
472 | return v.m_discriminator == VR_FRANGE; | |||
473 | } | |||
474 | ||||
475 | class vrange_visitor | |||
476 | { | |||
477 | public: | |||
478 | virtual void visit (const irange &) const { } | |||
479 | virtual void visit (const frange &) const { } | |||
480 | virtual void visit (const unsupported_range &) const { } | |||
481 | }; | |||
482 | ||||
483 | // This is a special int_range<1> with only one pair, plus | |||
484 | // VR_ANTI_RANGE magic to describe slightly more than can be described | |||
485 | // in one pair. It is described in the code as a "legacy range" (as | |||
486 | // opposed to multi-ranges which have multiple sub-ranges). It is | |||
487 | // provided for backward compatibility with code that has not been | |||
488 | // converted to multi-range irange's. | |||
489 | // | |||
490 | // There are copy operators to seamlessly copy to/fro multi-ranges. | |||
491 | typedef int_range<1> value_range; | |||
492 | ||||
493 | // This is an "infinite" precision irange for use in temporary | |||
494 | // calculations. | |||
495 | typedef int_range<255> int_range_max; | |||
496 | ||||
497 | // This is an "infinite" precision range object for use in temporary | |||
498 | // calculations for any of the handled types. The object can be | |||
499 | // transparently used as a vrange. | |||
500 | ||||
501 | class Value_Range | |||
502 | { | |||
503 | public: | |||
504 | Value_Range (); | |||
505 | Value_Range (const vrange &r); | |||
506 | Value_Range (tree type); | |||
507 | Value_Range (const Value_Range &); | |||
508 | void set_type (tree type); | |||
509 | vrange& operator= (const vrange &); | |||
510 | bool operator== (const Value_Range &r) const; | |||
511 | bool operator!= (const Value_Range &r) const; | |||
512 | operator vrange &(); | |||
513 | operator const vrange &() const; | |||
514 | void dump (FILE *) const; | |||
515 | static bool supports_type_p (const_tree type); | |||
516 | ||||
517 | // Convenience methods for vrange compatibility. | |||
518 | void set (tree min, tree max, value_range_kind kind = VR_RANGE) | |||
519 | { return m_vrange->set (min, max, kind); } | |||
520 | tree type () { return m_vrange->type (); } | |||
521 | enum value_range_kind kind () { return m_vrange->kind (); } | |||
522 | bool varying_p () const { return m_vrange->varying_p (); } | |||
523 | bool undefined_p () const { return m_vrange->undefined_p (); } | |||
524 | void set_varying (tree type) { m_vrange->set_varying (type); } | |||
525 | void set_undefined () { m_vrange->set_undefined (); } | |||
526 | bool union_ (const vrange &r) { return m_vrange->union_ (r); } | |||
527 | bool intersect (const vrange &r) { return m_vrange->intersect (r); } | |||
528 | bool singleton_p (tree *result = NULLnullptr) const | |||
529 | { return m_vrange->singleton_p (result); } | |||
530 | bool zero_p () const { return m_vrange->zero_p (); } | |||
531 | wide_int lower_bound () const; // For irange/prange comparability. | |||
532 | wide_int upper_bound () const; // For irange/prange comparability. | |||
533 | void accept (const vrange_visitor &v) const { m_vrange->accept (v); } | |||
534 | private: | |||
535 | void init (tree type); | |||
536 | unsupported_range m_unsupported; | |||
537 | vrange *m_vrange; | |||
538 | int_range_max m_irange; | |||
539 | frange m_frange; | |||
540 | }; | |||
541 | ||||
542 | inline | |||
543 | Value_Range::Value_Range () | |||
544 | { | |||
545 | m_vrange = &m_unsupported; | |||
546 | } | |||
547 | ||||
548 | // Copy constructor from a vrange. | |||
549 | ||||
550 | inline | |||
551 | Value_Range::Value_Range (const vrange &r) | |||
552 | { | |||
553 | *this = r; | |||
554 | } | |||
555 | ||||
556 | // Copy constructor from a TYPE. The range of the temporary is set to | |||
557 | // UNDEFINED. | |||
558 | ||||
559 | inline | |||
560 | Value_Range::Value_Range (tree type) | |||
561 | { | |||
562 | init (type); | |||
563 | } | |||
564 | ||||
565 | inline | |||
566 | Value_Range::Value_Range (const Value_Range &r) | |||
567 | { | |||
568 | m_vrange = r.m_vrange; | |||
569 | } | |||
570 | ||||
571 | // Initialize object so it is possible to store temporaries of TYPE | |||
572 | // into it. | |||
573 | ||||
574 | inline void | |||
575 | Value_Range::init (tree type) | |||
576 | { | |||
577 | gcc_checking_assert (TYPE_P (type))((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (type)->base.code))] == tcc_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 577, __FUNCTION__), 0 : 0)); | |||
578 | ||||
579 | if (irange::supports_p (type)) | |||
580 | m_vrange = &m_irange; | |||
581 | else if (frange::supports_p (type)) | |||
582 | m_vrange = &m_frange; | |||
583 | else | |||
584 | m_vrange = &m_unsupported; | |||
585 | } | |||
586 | ||||
587 | // Set the temporary to allow storing temporaries of TYPE. The range | |||
588 | // of the temporary is set to UNDEFINED. | |||
589 | ||||
590 | inline void | |||
591 | Value_Range::set_type (tree type) | |||
592 | { | |||
593 | init (type); | |||
594 | m_vrange->set_undefined (); | |||
595 | } | |||
596 | ||||
597 | // Assignment operator for temporaries. Copying incompatible types is | |||
598 | // allowed. | |||
599 | ||||
600 | inline vrange & | |||
601 | Value_Range::operator= (const vrange &r) | |||
602 | { | |||
603 | if (is_a <irange> (r)) | |||
604 | { | |||
605 | m_irange = as_a <irange> (r); | |||
606 | m_vrange = &m_irange; | |||
607 | } | |||
608 | else if (is_a <frange> (r)) | |||
609 | { | |||
610 | m_frange = as_a <frange> (r); | |||
611 | m_vrange = &m_frange; | |||
612 | } | |||
613 | else | |||
614 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 614, __FUNCTION__)); | |||
615 | ||||
616 | return *m_vrange; | |||
617 | } | |||
618 | ||||
619 | inline bool | |||
620 | Value_Range::operator== (const Value_Range &r) const | |||
621 | { | |||
622 | return *m_vrange == *r.m_vrange; | |||
623 | } | |||
624 | ||||
625 | inline bool | |||
626 | Value_Range::operator!= (const Value_Range &r) const | |||
627 | { | |||
628 | return *m_vrange != *r.m_vrange; | |||
629 | } | |||
630 | ||||
631 | inline | |||
632 | Value_Range::operator vrange &() | |||
633 | { | |||
634 | return *m_vrange; | |||
635 | } | |||
636 | ||||
637 | inline | |||
638 | Value_Range::operator const vrange &() const | |||
639 | { | |||
640 | return *m_vrange; | |||
641 | } | |||
642 | ||||
643 | // Return TRUE if TYPE is supported by the vrange infrastructure. | |||
644 | ||||
645 | inline bool | |||
646 | Value_Range::supports_type_p (const_tree type) | |||
647 | { | |||
648 | return irange::supports_p (type) || frange::supports_p (type); | |||
649 | } | |||
650 | ||||
651 | // Returns true for an old-school value_range as described above. | |||
652 | inline bool | |||
653 | irange::legacy_mode_p () const | |||
654 | { | |||
655 | return m_max_ranges == 1; | |||
656 | } | |||
657 | ||||
658 | extern bool range_has_numeric_bounds_p (const irange *); | |||
659 | extern bool ranges_from_anti_range (const value_range *, | |||
660 | value_range *, value_range *); | |||
661 | extern void dump_value_range (FILE *, const vrange *); | |||
662 | extern bool vrp_val_is_min (const_tree); | |||
663 | extern bool vrp_val_is_max (const_tree); | |||
664 | extern bool vrp_operand_equal_p (const_tree, const_tree); | |||
665 | inline REAL_VALUE_TYPEstruct real_value frange_val_min (const_tree type); | |||
666 | inline REAL_VALUE_TYPEstruct real_value frange_val_max (const_tree type); | |||
667 | ||||
668 | inline value_range_kind | |||
669 | vrange::kind () const | |||
670 | { | |||
671 | return m_kind; | |||
672 | } | |||
673 | ||||
674 | // Number of sub-ranges in a range. | |||
675 | ||||
676 | inline unsigned | |||
677 | irange::num_pairs () const | |||
678 | { | |||
679 | if (m_kind == VR_ANTI_RANGE) | |||
680 | return constant_p () ? 2 : 1; | |||
681 | else | |||
682 | return m_num_ranges; | |||
683 | } | |||
684 | ||||
685 | inline tree | |||
686 | irange::type () const | |||
687 | { | |||
688 | gcc_checking_assert (m_num_ranges > 0)((void)(!(m_num_ranges > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 688, __FUNCTION__), 0 : 0)); | |||
689 | return TREE_TYPE (m_base[0])((contains_struct_check ((m_base[0]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 689, __FUNCTION__))->typed.type); | |||
| ||||
690 | } | |||
691 | ||||
692 | // Return the lower bound of a sub-range expressed as a tree. PAIR is | |||
693 | // the sub-range in question. | |||
694 | ||||
695 | inline tree | |||
696 | irange::tree_lower_bound (unsigned pair) const | |||
697 | { | |||
698 | return m_base[pair * 2]; | |||
699 | } | |||
700 | ||||
701 | // Return the upper bound of a sub-range expressed as a tree. PAIR is | |||
702 | // the sub-range in question. | |||
703 | ||||
704 | inline tree | |||
705 | irange::tree_upper_bound (unsigned pair) const | |||
706 | { | |||
707 | return m_base[pair * 2 + 1]; | |||
708 | } | |||
709 | ||||
710 | // Return the highest bound of a range expressed as a tree. | |||
711 | ||||
712 | inline tree | |||
713 | irange::tree_upper_bound () const | |||
714 | { | |||
715 | gcc_checking_assert (m_num_ranges)((void)(!(m_num_ranges) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 715, __FUNCTION__), 0 : 0)); | |||
716 | return tree_upper_bound (m_num_ranges - 1); | |||
717 | } | |||
718 | ||||
719 | inline tree | |||
720 | irange::min () const | |||
721 | { | |||
722 | return tree_lower_bound (0); | |||
723 | } | |||
724 | ||||
725 | inline tree | |||
726 | irange::max () const | |||
727 | { | |||
728 | if (m_num_ranges) | |||
729 | return tree_upper_bound (); | |||
730 | else | |||
731 | return NULLnullptr; | |||
732 | } | |||
733 | ||||
734 | inline bool | |||
735 | irange::varying_compatible_p () const | |||
736 | { | |||
737 | if (m_num_ranges != 1) | |||
738 | return false; | |||
739 | ||||
740 | tree l = m_base[0]; | |||
741 | tree u = m_base[1]; | |||
742 | tree t = TREE_TYPE (l)((contains_struct_check ((l), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 742, __FUNCTION__))->typed.type); | |||
743 | ||||
744 | if (m_kind == VR_VARYING && t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
745 | return true; | |||
746 | ||||
747 | unsigned prec = TYPE_PRECISION (t)((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 747, __FUNCTION__))->type_common.precision); | |||
748 | signop sign = TYPE_SIGN (t)((signop) ((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 748, __FUNCTION__))->base.u.bits.unsigned_flag)); | |||
749 | if (INTEGRAL_TYPE_P (t)(((enum tree_code) (t)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (t)->base.code) == BOOLEAN_TYPE || ((enum tree_code ) (t)->base.code) == INTEGER_TYPE)) | |||
750 | return (wi::to_wide (l) == wi::min_value (prec, sign) | |||
751 | && wi::to_wide (u) == wi::max_value (prec, sign) | |||
752 | && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1)); | |||
753 | if (POINTER_TYPE_P (t)(((enum tree_code) (t)->base.code) == POINTER_TYPE || ((enum tree_code) (t)->base.code) == REFERENCE_TYPE)) | |||
754 | return (wi::to_wide (l) == 0 | |||
755 | && wi::to_wide (u) == wi::max_value (prec, sign) | |||
756 | && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1)); | |||
757 | return true; | |||
758 | } | |||
759 | ||||
760 | inline void | |||
761 | irange::set (tree type, const wide_int_ref &min, const wide_int_ref &max, | |||
762 | value_range_kind kind) | |||
763 | { | |||
764 | set (wide_int_to_tree (type, min), wide_int_to_tree (type, max), kind); | |||
765 | } | |||
766 | ||||
767 | inline bool | |||
768 | vrange::varying_p () const | |||
769 | { | |||
770 | return m_kind == VR_VARYING; | |||
771 | } | |||
772 | ||||
773 | inline bool | |||
774 | vrange::undefined_p () const | |||
775 | { | |||
776 | return m_kind == VR_UNDEFINED; | |||
777 | } | |||
778 | ||||
779 | inline bool | |||
780 | irange::zero_p () const | |||
781 | { | |||
782 | return (m_kind == VR_RANGE && m_num_ranges == 1 | |||
783 | && integer_zerop (tree_lower_bound (0)) | |||
784 | && integer_zerop (tree_upper_bound (0))); | |||
785 | } | |||
786 | ||||
787 | inline bool | |||
788 | irange::nonzero_p () const | |||
789 | { | |||
790 | if (undefined_p ()) | |||
791 | return false; | |||
792 | ||||
793 | tree zero = build_zero_cst (type ()); | |||
794 | return *this == int_range<1> (zero, zero, VR_ANTI_RANGE); | |||
795 | } | |||
796 | ||||
797 | inline bool | |||
798 | irange::supports_p (const_tree type) | |||
799 | { | |||
800 | return INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (type)->base.code) == INTEGER_TYPE) || POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE); | |||
801 | } | |||
802 | ||||
803 | inline bool | |||
804 | range_includes_zero_p (const irange *vr) | |||
805 | { | |||
806 | if (vr->undefined_p ()) | |||
807 | return false; | |||
808 | ||||
809 | if (vr->varying_p ()) | |||
810 | return true; | |||
811 | ||||
812 | return vr->may_contain_p (build_zero_cst (vr->type ())); | |||
813 | } | |||
814 | ||||
815 | inline void | |||
816 | gt_ggc_mx (irange *x) | |||
817 | { | |||
818 | for (unsigned i = 0; i < x->m_num_ranges; ++i) | |||
819 | { | |||
820 | gt_ggc_mx (x->m_base[i * 2]); | |||
821 | gt_ggc_mx (x->m_base[i * 2 + 1]); | |||
822 | } | |||
823 | if (x->m_nonzero_mask) | |||
824 | gt_ggc_mx (x->m_nonzero_mask); | |||
825 | } | |||
826 | ||||
827 | inline void | |||
828 | gt_pch_nx (irange *x) | |||
829 | { | |||
830 | for (unsigned i = 0; i < x->m_num_ranges; ++i) | |||
831 | { | |||
832 | gt_pch_nx (x->m_base[i * 2]); | |||
833 | gt_pch_nx (x->m_base[i * 2 + 1]); | |||
834 | } | |||
835 | if (x->m_nonzero_mask) | |||
836 | gt_pch_nx (x->m_nonzero_mask); | |||
837 | } | |||
838 | ||||
839 | inline void | |||
840 | gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie) | |||
841 | { | |||
842 | for (unsigned i = 0; i < x->m_num_ranges; ++i) | |||
843 | { | |||
844 | op (&x->m_base[i * 2], NULLnullptr, cookie); | |||
845 | op (&x->m_base[i * 2 + 1], NULLnullptr, cookie); | |||
846 | } | |||
847 | if (x->m_nonzero_mask) | |||
848 | op (&x->m_nonzero_mask, NULLnullptr, cookie); | |||
849 | } | |||
850 | ||||
851 | template<unsigned N> | |||
852 | inline void | |||
853 | gt_ggc_mx (int_range<N> *x) | |||
854 | { | |||
855 | gt_ggc_mx ((irange *) x); | |||
856 | } | |||
857 | ||||
858 | template<unsigned N> | |||
859 | inline void | |||
860 | gt_pch_nx (int_range<N> *x) | |||
861 | { | |||
862 | gt_pch_nx ((irange *) x); | |||
863 | } | |||
864 | ||||
865 | template<unsigned N> | |||
866 | inline void | |||
867 | gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie) | |||
868 | { | |||
869 | gt_pch_nx ((irange *) x, op, cookie); | |||
870 | } | |||
871 | ||||
872 | // Constructors for irange | |||
873 | ||||
874 | inline | |||
875 | irange::irange (tree *base, unsigned nranges) | |||
876 | { | |||
877 | m_discriminator = VR_IRANGE; | |||
878 | m_base = base; | |||
879 | m_max_ranges = nranges; | |||
880 | set_undefined (); | |||
881 | } | |||
882 | ||||
883 | // Constructors for int_range<>. | |||
884 | ||||
885 | template<unsigned N> | |||
886 | inline | |||
887 | int_range<N>::int_range () | |||
888 | : irange (m_ranges, N) | |||
889 | { | |||
890 | } | |||
891 | ||||
892 | template<unsigned N> | |||
893 | int_range<N>::int_range (const int_range &other) | |||
894 | : irange (m_ranges, N) | |||
895 | { | |||
896 | irange::operator= (other); | |||
897 | } | |||
898 | ||||
899 | template<unsigned N> | |||
900 | int_range<N>::int_range (tree min, tree max, value_range_kind kind) | |||
901 | : irange (m_ranges, N) | |||
902 | { | |||
903 | irange::set (min, max, kind); | |||
904 | } | |||
905 | ||||
906 | template<unsigned N> | |||
907 | int_range<N>::int_range (tree type) | |||
908 | : irange (m_ranges, N) | |||
909 | { | |||
910 | set_varying (type); | |||
911 | } | |||
912 | ||||
913 | template<unsigned N> | |||
914 | int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax, | |||
915 | value_range_kind kind) | |||
916 | : irange (m_ranges, N) | |||
917 | { | |||
918 | tree min = wide_int_to_tree (type, wmin); | |||
919 | tree max = wide_int_to_tree (type, wmax); | |||
920 | set (min, max, kind); | |||
921 | } | |||
922 | ||||
923 | template<unsigned N> | |||
924 | int_range<N>::int_range (const irange &other) | |||
925 | : irange (m_ranges, N) | |||
926 | { | |||
927 | irange::operator= (other); | |||
928 | } | |||
929 | ||||
930 | template<unsigned N> | |||
931 | int_range<N>& | |||
932 | int_range<N>::operator= (const int_range &src) | |||
933 | { | |||
934 | irange::operator= (src); | |||
935 | return *this; | |||
936 | } | |||
937 | ||||
938 | inline void | |||
939 | irange::set_undefined () | |||
940 | { | |||
941 | m_kind = VR_UNDEFINED; | |||
942 | m_num_ranges = 0; | |||
943 | m_nonzero_mask = NULLnullptr; | |||
944 | } | |||
945 | ||||
946 | inline void | |||
947 | irange::set_varying (tree type) | |||
948 | { | |||
949 | m_kind = VR_VARYING; | |||
950 | m_num_ranges = 1; | |||
951 | m_nonzero_mask = NULLnullptr; | |||
952 | ||||
953 | if (INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (type)->base.code) == INTEGER_TYPE)) | |||
954 | { | |||
955 | // Strict enum's require varying to be not TYPE_MIN/MAX, but rather | |||
956 | // min_value and max_value. | |||
957 | wide_int min = wi::min_value (TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 957, __FUNCTION__))->type_common.precision), TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 957, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
958 | wide_int max = wi::max_value (TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 958, __FUNCTION__))->type_common.precision), TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 958, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
959 | if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 959, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ))) | |||
960 | && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 960, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval )))) | |||
961 | { | |||
962 | m_base[0] = TYPE_MIN_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 962, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval ); | |||
963 | m_base[1] = TYPE_MAX_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 963, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ); | |||
964 | } | |||
965 | else | |||
966 | { | |||
967 | m_base[0] = wide_int_to_tree (type, min); | |||
968 | m_base[1] = wide_int_to_tree (type, max); | |||
969 | } | |||
970 | } | |||
971 | else if (POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE)) | |||
972 | { | |||
973 | m_base[0] = build_int_cst (type, 0); | |||
974 | m_base[1] = build_int_cst (type, -1); | |||
975 | } | |||
976 | else | |||
977 | m_base[0] = m_base[1] = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
978 | } | |||
979 | ||||
980 | // Return the lower bound of a sub-range. PAIR is the sub-range in | |||
981 | // question. | |||
982 | ||||
983 | inline wide_int | |||
984 | irange::lower_bound (unsigned pair) const | |||
985 | { | |||
986 | if (legacy_mode_p ()) | |||
987 | return legacy_lower_bound (pair); | |||
988 | gcc_checking_assert (m_num_ranges > 0)((void)(!(m_num_ranges > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 988, __FUNCTION__), 0 : 0)); | |||
989 | gcc_checking_assert (pair + 1 <= num_pairs ())((void)(!(pair + 1 <= num_pairs ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 989, __FUNCTION__), 0 : 0)); | |||
990 | return wi::to_wide (tree_lower_bound (pair)); | |||
991 | } | |||
992 | ||||
993 | // Return the upper bound of a sub-range. PAIR is the sub-range in | |||
994 | // question. | |||
995 | ||||
996 | inline wide_int | |||
997 | irange::upper_bound (unsigned pair) const | |||
998 | { | |||
999 | if (legacy_mode_p ()) | |||
1000 | return legacy_upper_bound (pair); | |||
1001 | gcc_checking_assert (m_num_ranges > 0)((void)(!(m_num_ranges > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1001, __FUNCTION__), 0 : 0)); | |||
1002 | gcc_checking_assert (pair + 1 <= num_pairs ())((void)(!(pair + 1 <= num_pairs ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1002, __FUNCTION__), 0 : 0)); | |||
1003 | return wi::to_wide (tree_upper_bound (pair)); | |||
1004 | } | |||
1005 | ||||
1006 | // Return the highest bound of a range. | |||
1007 | ||||
1008 | inline wide_int | |||
1009 | irange::upper_bound () const | |||
1010 | { | |||
1011 | unsigned pairs = num_pairs (); | |||
1012 | gcc_checking_assert (pairs > 0)((void)(!(pairs > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1012, __FUNCTION__), 0 : 0)); | |||
1013 | return upper_bound (pairs - 1); | |||
1014 | } | |||
1015 | ||||
1016 | inline bool | |||
1017 | irange::union_ (const vrange &r) | |||
1018 | { | |||
1019 | dump_flags_t m_flags = dump_flags; | |||
1020 | dump_flags &= ~TDF_DETAILS; | |||
1021 | bool ret = irange::legacy_verbose_union_ (&as_a <irange> (r)); | |||
1022 | dump_flags = m_flags; | |||
1023 | return ret; | |||
1024 | } | |||
1025 | ||||
1026 | inline bool | |||
1027 | irange::intersect (const vrange &r) | |||
1028 | { | |||
1029 | dump_flags_t m_flags = dump_flags; | |||
1030 | dump_flags &= ~TDF_DETAILS; | |||
1031 | bool ret = irange::legacy_verbose_intersect (&as_a <irange> (r)); | |||
1032 | dump_flags = m_flags; | |||
1033 | return ret; | |||
1034 | } | |||
1035 | ||||
1036 | // Set value range VR to a nonzero range of type TYPE. | |||
1037 | ||||
1038 | inline void | |||
1039 | irange::set_nonzero (tree type) | |||
1040 | { | |||
1041 | tree zero = build_int_cst (type, 0); | |||
1042 | if (legacy_mode_p ()) | |||
1043 | set (zero, zero, VR_ANTI_RANGE); | |||
1044 | else | |||
1045 | irange_set_anti_range (zero, zero); | |||
1046 | } | |||
1047 | ||||
1048 | // Set value range VR to a ZERO range of type TYPE. | |||
1049 | ||||
1050 | inline void | |||
1051 | irange::set_zero (tree type) | |||
1052 | { | |||
1053 | tree z = build_int_cst (type, 0); | |||
1054 | if (legacy_mode_p ()) | |||
1055 | set (z, z); | |||
1056 | else | |||
1057 | irange_set (z, z); | |||
1058 | } | |||
1059 | ||||
1060 | // Normalize a range to VARYING or UNDEFINED if possible. | |||
1061 | ||||
1062 | inline void | |||
1063 | irange::normalize_kind () | |||
1064 | { | |||
1065 | if (m_num_ranges == 0) | |||
1066 | set_undefined (); | |||
1067 | else if (varying_compatible_p ()) | |||
1068 | { | |||
1069 | if (m_kind == VR_RANGE) | |||
1070 | m_kind = VR_VARYING; | |||
1071 | else if (m_kind == VR_ANTI_RANGE) | |||
1072 | set_undefined (); | |||
1073 | } | |||
1074 | } | |||
1075 | ||||
1076 | // Return the maximum value for TYPE. | |||
1077 | ||||
1078 | inline tree | |||
1079 | vrp_val_max (const_tree type) | |||
1080 | { | |||
1081 | if (INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (type)->base.code) == INTEGER_TYPE)) | |||
1082 | return TYPE_MAX_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1082, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ); | |||
1083 | if (POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE)) | |||
1084 | { | |||
1085 | wide_int max = wi::max_value (TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1085, __FUNCTION__))->type_common.precision), TYPE_SIGN (type)((signop) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1085, __FUNCTION__))->base.u.bits.unsigned_flag))); | |||
1086 | return wide_int_to_tree (const_cast<tree> (type), max); | |||
1087 | } | |||
1088 | if (frange::supports_p (type)) | |||
1089 | { | |||
1090 | REAL_VALUE_TYPEstruct real_value r = frange_val_max (type); | |||
1091 | return build_real (const_cast <tree> (type), r); | |||
1092 | } | |||
1093 | return NULL_TREE(tree) nullptr; | |||
1094 | } | |||
1095 | ||||
1096 | // Return the minimum value for TYPE. | |||
1097 | ||||
1098 | inline tree | |||
1099 | vrp_val_min (const_tree type) | |||
1100 | { | |||
1101 | if (INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (type)->base.code) == INTEGER_TYPE)) | |||
1102 | return TYPE_MIN_VALUE (type)((tree_check5 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1102, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval ); | |||
1103 | if (POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE)) | |||
1104 | return build_zero_cst (const_cast<tree> (type)); | |||
1105 | if (frange::supports_p (type)) | |||
1106 | { | |||
1107 | REAL_VALUE_TYPEstruct real_value r = frange_val_min (type); | |||
1108 | return build_real (const_cast <tree> (type), r); | |||
1109 | } | |||
1110 | return NULL_TREE(tree) nullptr; | |||
1111 | } | |||
1112 | ||||
1113 | inline | |||
1114 | frange::frange () | |||
1115 | { | |||
1116 | m_discriminator = VR_FRANGE; | |||
1117 | set_undefined (); | |||
1118 | } | |||
1119 | ||||
1120 | inline | |||
1121 | frange::frange (const frange &src) | |||
1122 | { | |||
1123 | m_discriminator = VR_FRANGE; | |||
1124 | *this = src; | |||
1125 | } | |||
1126 | ||||
1127 | inline | |||
1128 | frange::frange (tree type) | |||
1129 | { | |||
1130 | m_discriminator = VR_FRANGE; | |||
1131 | set_varying (type); | |||
1132 | } | |||
1133 | ||||
1134 | // frange constructor from REAL_VALUE_TYPE endpoints. | |||
1135 | ||||
1136 | inline | |||
1137 | frange::frange (tree type, | |||
1138 | const REAL_VALUE_TYPEstruct real_value &min, const REAL_VALUE_TYPEstruct real_value &max, | |||
1139 | value_range_kind kind) | |||
1140 | { | |||
1141 | m_discriminator = VR_FRANGE; | |||
1142 | set (type, min, max, kind); | |||
1143 | } | |||
1144 | ||||
1145 | // frange constructor from trees. | |||
1146 | ||||
1147 | inline | |||
1148 | frange::frange (tree min, tree max, value_range_kind kind) | |||
1149 | { | |||
1150 | m_discriminator = VR_FRANGE; | |||
1151 | set (min, max, kind); | |||
1152 | } | |||
1153 | ||||
1154 | inline tree | |||
1155 | frange::type () const | |||
1156 | { | |||
1157 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1157, __FUNCTION__), 0 : 0)); | |||
1158 | return m_type; | |||
1159 | } | |||
1160 | ||||
1161 | inline void | |||
1162 | frange::set_varying (tree type) | |||
1163 | { | |||
1164 | m_kind = VR_VARYING; | |||
1165 | m_type = type; | |||
1166 | m_min = frange_val_min (type); | |||
1167 | m_max = frange_val_max (type); | |||
1168 | if (HONOR_NANS (m_type)) | |||
1169 | { | |||
1170 | m_pos_nan = true; | |||
1171 | m_neg_nan = true; | |||
1172 | } | |||
1173 | else | |||
1174 | { | |||
1175 | m_pos_nan = false; | |||
1176 | m_neg_nan = false; | |||
1177 | } | |||
1178 | } | |||
1179 | ||||
1180 | inline void | |||
1181 | frange::set_undefined () | |||
1182 | { | |||
1183 | m_kind = VR_UNDEFINED; | |||
1184 | m_type = NULLnullptr; | |||
1185 | m_pos_nan = false; | |||
1186 | m_neg_nan = false; | |||
1187 | // m_min and m_min are uninitialized as they are REAL_VALUE_TYPE ??. | |||
1188 | if (flag_checkingglobal_options.x_flag_checking) | |||
1189 | verify_range (); | |||
1190 | } | |||
1191 | ||||
1192 | // Set the NAN bit and adjust the range. | |||
1193 | ||||
1194 | inline void | |||
1195 | frange::update_nan () | |||
1196 | { | |||
1197 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1197, __FUNCTION__), 0 : 0)); | |||
1198 | if (HONOR_NANS (m_type)) | |||
1199 | { | |||
1200 | m_pos_nan = true; | |||
1201 | m_neg_nan = true; | |||
1202 | normalize_kind (); | |||
1203 | if (flag_checkingglobal_options.x_flag_checking) | |||
1204 | verify_range (); | |||
1205 | } | |||
1206 | } | |||
1207 | ||||
1208 | // Like above, but set the sign of the NAN. | |||
1209 | ||||
1210 | inline void | |||
1211 | frange::update_nan (bool sign) | |||
1212 | { | |||
1213 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1213, __FUNCTION__), 0 : 0)); | |||
1214 | if (HONOR_NANS (m_type)) | |||
1215 | { | |||
1216 | m_pos_nan = !sign; | |||
1217 | m_neg_nan = sign; | |||
1218 | normalize_kind (); | |||
1219 | if (flag_checkingglobal_options.x_flag_checking) | |||
1220 | verify_range (); | |||
1221 | } | |||
1222 | } | |||
1223 | ||||
1224 | // Clear the NAN bit and adjust the range. | |||
1225 | ||||
1226 | inline void | |||
1227 | frange::clear_nan () | |||
1228 | { | |||
1229 | gcc_checking_assert (!undefined_p ())((void)(!(!undefined_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1229, __FUNCTION__), 0 : 0)); | |||
1230 | m_pos_nan = false; | |||
1231 | m_neg_nan = false; | |||
1232 | normalize_kind (); | |||
1233 | if (flag_checkingglobal_options.x_flag_checking) | |||
1234 | verify_range (); | |||
1235 | } | |||
1236 | ||||
1237 | // Set R to maximum representable value for TYPE. | |||
1238 | ||||
1239 | inline REAL_VALUE_TYPEstruct real_value | |||
1240 | real_max_representable (const_tree type) | |||
1241 | { | |||
1242 | REAL_VALUE_TYPEstruct real_value r; | |||
1243 | char buf[128]; | |||
1244 | get_max_float (REAL_MODE_FORMAT (TYPE_MODE (type))(real_format_for_mode[(((enum mode_class) mode_class[((((enum tree_code) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1244, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode)]) == MODE_DECIMAL_FLOAT ) ? (((((((enum tree_code) ((tree_class_check ((type), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1244, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode)) - MIN_MODE_DECIMAL_FLOAT ) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class ) mode_class[((((enum tree_code) ((tree_class_check ((type), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1244, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode)]) == MODE_FLOAT ? (((( ((enum tree_code) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1244, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode)) - MIN_MODE_FLOAT) : ( (fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1244, __FUNCTION__)), 0)]), | |||
1245 | buf, sizeof (buf), false); | |||
1246 | int res = real_from_string (&r, buf); | |||
1247 | gcc_checking_assert (!res)((void)(!(!res) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/value-range.h" , 1247, __FUNCTION__), 0 : 0)); | |||
1248 | return r; | |||
1249 | } | |||
1250 | ||||
1251 | // Return the minimum representable value for TYPE. | |||
1252 | ||||
1253 | inline REAL_VALUE_TYPEstruct real_value | |||
1254 | real_min_representable (const_tree type) | |||
1255 | { | |||
1256 | REAL_VALUE_TYPEstruct real_value r = real_max_representable (type); | |||
1257 | r = real_value_negate (&r); | |||
1258 | return r; | |||
1259 | } | |||
1260 | ||||
1261 | // Return the minimum value for TYPE. | |||
1262 | ||||
1263 | inline REAL_VALUE_TYPEstruct real_value | |||
1264 | frange_val_min (const_tree type) | |||
1265 | { | |||
1266 | if (HONOR_INFINITIES (type)) | |||
1267 | return dconstninf; | |||
1268 | else | |||
1269 | return real_min_representable (type); | |||
1270 | } | |||
1271 | ||||
1272 | // Return the maximum value for TYPE. | |||
1273 | ||||
1274 | inline REAL_VALUE_TYPEstruct real_value | |||
1275 | frange_val_max (const_tree type) | |||
1276 | { | |||
1277 | if (HONOR_INFINITIES (type)) | |||
1278 | return dconstinf; | |||
1279 | else | |||
1280 | return real_max_representable (type); | |||
1281 | } | |||
1282 | ||||
1283 | // Return TRUE if R is the minimum value for TYPE. | |||
1284 | ||||
1285 | inline bool | |||
1286 | frange_val_is_min (const REAL_VALUE_TYPEstruct real_value &r, const_tree type) | |||
1287 | { | |||
1288 | REAL_VALUE_TYPEstruct real_value min = frange_val_min (type); | |||
1289 | return real_identical (&min, &r); | |||
1290 | } | |||
1291 | ||||
1292 | // Return TRUE if R is the max value for TYPE. | |||
1293 | ||||
1294 | inline bool | |||
1295 | frange_val_is_max (const REAL_VALUE_TYPEstruct real_value &r, const_tree type) | |||
1296 | { | |||
1297 | REAL_VALUE_TYPEstruct real_value max = frange_val_max (type); | |||
1298 | return real_identical (&max, &r); | |||
1299 | } | |||
1300 | ||||
1301 | // Build a signless NAN of type TYPE. | |||
1302 | ||||
1303 | inline void | |||
1304 | frange::set_nan (tree type) | |||
1305 | { | |||
1306 | if (HONOR_NANS (type)) | |||
1307 | { | |||
1308 | m_kind = VR_NAN; | |||
1309 | m_type = type; | |||
1310 | m_pos_nan = true; | |||
1311 | m_neg_nan = true; | |||
1312 | if (flag_checkingglobal_options.x_flag_checking) | |||
1313 | verify_range (); | |||
1314 | } | |||
1315 | else | |||
1316 | set_undefined (); | |||
1317 | } | |||
1318 | ||||
1319 | // Build a NAN of type TYPE with SIGN. | |||
1320 | ||||
1321 | inline void | |||
1322 | frange::set_nan (tree type, bool sign) | |||
1323 | { | |||
1324 | if (HONOR_NANS (type)) | |||
1325 | { | |||
1326 | m_kind = VR_NAN; | |||
1327 | m_type = type; | |||
1328 | m_neg_nan = sign; | |||
1329 | m_pos_nan = !sign; | |||
1330 | if (flag_checkingglobal_options.x_flag_checking) | |||
1331 | verify_range (); | |||
1332 | } | |||
1333 | else | |||
1334 | set_undefined (); | |||
1335 | } | |||
1336 | ||||
1337 | // Return TRUE if range is known to be finite. | |||
1338 | ||||
1339 | inline bool | |||
1340 | frange::known_isfinite () const | |||
1341 | { | |||
1342 | if (undefined_p () || varying_p () || m_kind == VR_ANTI_RANGE) | |||
1343 | return false; | |||
1344 | return (!maybe_isnan () && !real_isinf (&m_min) && !real_isinf (&m_max |