Line data Source code
1 : /* Consolidation of svalues and regions.
2 : Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "analyzer/common.h"
22 :
23 : #include "fold-const.h"
24 : #include "ordered-hash-map.h"
25 : #include "options.h"
26 : #include "analyzer/supergraph.h"
27 : #include "sbitmap.h"
28 : #include "target.h"
29 :
30 : #include "analyzer/analyzer-logging.h"
31 : #include "analyzer/call-string.h"
32 : #include "analyzer/program-point.h"
33 : #include "analyzer/store.h"
34 : #include "analyzer/region-model.h"
35 : #include "analyzer/constraint-manager.h"
36 :
37 : #if ENABLE_ANALYZER
38 :
39 : namespace ana {
40 :
41 : /* class region_model_manager. */
42 :
43 : /* region_model_manager's ctor. */
44 :
45 4034 : region_model_manager::region_model_manager (logger *logger)
46 4034 : : m_logger (logger),
47 4034 : m_next_symbol_id (0),
48 4034 : m_empty_call_string (),
49 4034 : m_root_region (alloc_symbol_id ()),
50 4034 : m_stack_region (alloc_symbol_id (), &m_root_region),
51 4034 : m_heap_region (alloc_symbol_id (), &m_root_region),
52 4034 : m_unknown_NULL (nullptr),
53 4034 : m_checking_feasibility (false),
54 4034 : m_max_complexity (0, 0),
55 4034 : m_code_region (alloc_symbol_id (), &m_root_region),
56 4034 : m_fndecls_map (), m_labels_map (),
57 4034 : m_globals_region (alloc_symbol_id (), &m_root_region),
58 4034 : m_globals_map (),
59 4034 : m_thread_local_region (alloc_symbol_id (), &m_root_region),
60 4034 : m_errno_region (alloc_symbol_id (), &m_thread_local_region),
61 4034 : m_store_mgr (this),
62 4034 : m_range_mgr (new bounded_ranges_manager ()),
63 12102 : m_known_fn_mgr (logger)
64 : {
65 4034 : }
66 :
67 : /* region_model_manager's dtor. Delete all of the managed svalues
68 : and regions. */
69 :
70 8068 : region_model_manager::~region_model_manager ()
71 : {
72 : /* Delete consolidated svalues. */
73 61637 : for (constants_map_t::iterator iter = m_constants_map.begin ();
74 119240 : iter != m_constants_map.end (); ++iter)
75 57603 : delete (*iter).second;
76 12951 : for (unknowns_map_t::iterator iter = m_unknowns_map.begin ();
77 21868 : iter != m_unknowns_map.end (); ++iter)
78 8917 : delete (*iter).second;
79 4034 : delete m_unknown_NULL;
80 10229 : for (poisoned_values_map_t::iterator iter = m_poisoned_values_map.begin ();
81 16424 : iter != m_poisoned_values_map.end (); ++iter)
82 6195 : delete (*iter).second;
83 4068 : for (setjmp_values_map_t::iterator iter = m_setjmp_values_map.begin ();
84 4102 : iter != m_setjmp_values_map.end (); ++iter)
85 34 : delete (*iter).second;
86 31848 : for (initial_values_map_t::iterator iter = m_initial_values_map.begin ();
87 59662 : iter != m_initial_values_map.end (); ++iter)
88 27814 : delete (*iter).second;
89 30443 : for (pointer_values_map_t::iterator iter = m_pointer_values_map.begin ();
90 56852 : iter != m_pointer_values_map.end (); ++iter)
91 26409 : delete (*iter).second;
92 12785 : for (unaryop_values_map_t::iterator iter = m_unaryop_values_map.begin ();
93 21536 : iter != m_unaryop_values_map.end (); ++iter)
94 8751 : delete (*iter).second;
95 24932 : for (binop_values_map_t::iterator iter = m_binop_values_map.begin ();
96 45830 : iter != m_binop_values_map.end (); ++iter)
97 20898 : delete (*iter).second;
98 6402 : for (sub_values_map_t::iterator iter = m_sub_values_map.begin ();
99 8770 : iter != m_sub_values_map.end (); ++iter)
100 2368 : delete (*iter).second;
101 5058 : for (auto iter : m_repeated_values_map)
102 512 : delete iter.second;
103 5576 : for (auto iter : m_bits_within_values_map)
104 771 : delete iter.second;
105 4244 : for (unmergeable_values_map_t::iterator iter
106 4034 : = m_unmergeable_values_map.begin ();
107 4454 : iter != m_unmergeable_values_map.end (); ++iter)
108 210 : delete (*iter).second;
109 6395 : for (widening_values_map_t::iterator iter = m_widening_values_map.begin ();
110 8756 : iter != m_widening_values_map.end (); ++iter)
111 2361 : delete (*iter).second;
112 4695 : for (compound_values_map_t::iterator iter = m_compound_values_map.begin ();
113 5356 : iter != m_compound_values_map.end (); ++iter)
114 661 : delete (*iter).second;
115 30655 : for (conjured_values_map_t::iterator iter = m_conjured_values_map.begin ();
116 57276 : iter != m_conjured_values_map.end (); ++iter)
117 26621 : delete (*iter).second;
118 4408 : for (auto iter : m_asm_output_values_map)
119 187 : delete iter.second;
120 4408 : for (auto iter : m_const_fn_result_values_map)
121 187 : delete iter.second;
122 :
123 : /* Delete consolidated regions. */
124 13992 : for (fndecls_map_t::iterator iter = m_fndecls_map.begin ();
125 23950 : iter != m_fndecls_map.end (); ++iter)
126 9958 : delete (*iter).second;
127 4084 : for (labels_map_t::iterator iter = m_labels_map.begin ();
128 4134 : iter != m_labels_map.end (); ++iter)
129 50 : delete (*iter).second;
130 10432 : for (globals_map_t::iterator iter = m_globals_map.begin ();
131 16830 : iter != m_globals_map.end (); ++iter)
132 6398 : delete (*iter).second;
133 7869 : for (string_map_t::iterator iter = m_string_map.begin ();
134 11704 : iter != m_string_map.end (); ++iter)
135 3835 : delete (*iter).second;
136 :
137 4034 : delete m_range_mgr;
138 8068 : }
139 :
140 : /* Return true if C exceeds the complexity limit for svalues. */
141 :
142 : bool
143 176295 : region_model_manager::too_complex_p (const complexity &c) const
144 : {
145 176295 : if (c.m_max_depth > (unsigned)param_analyzer_max_svalue_depth)
146 1989 : return true;
147 : return false;
148 : }
149 :
150 : /* If SVAL exceeds the complexity limit for svalues, delete it
151 : and return true.
152 : Otherwise update m_max_complexity and return false. */
153 :
154 : bool
155 183571 : region_model_manager::reject_if_too_complex (svalue *sval)
156 : {
157 183571 : if (m_checking_feasibility)
158 : return false;
159 :
160 176295 : const complexity &c = sval->get_complexity ();
161 176295 : if (!too_complex_p (c))
162 : {
163 174306 : if (m_max_complexity.m_num_nodes < c.m_num_nodes)
164 12071 : m_max_complexity.m_num_nodes = c.m_num_nodes;
165 174306 : if (m_max_complexity.m_max_depth < c.m_max_depth)
166 11037 : m_max_complexity.m_max_depth = c.m_max_depth;
167 174306 : return false;
168 : }
169 :
170 1989 : pretty_printer pp;
171 1989 : pp_format_decoder (&pp) = default_tree_printer;
172 1989 : sval->dump_to_pp (&pp, true);
173 1989 : if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex,
174 : "symbol too complicated: %qs",
175 : pp_formatted_text (&pp)))
176 2 : inform (input_location,
177 : "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i",
178 2 : c.m_max_depth, param_analyzer_max_svalue_depth);
179 :
180 1989 : delete sval;
181 1989 : return true;
182 1989 : }
183 :
184 : /* Macro for imposing a complexity limit on svalues, for use within
185 : region_model_manager member functions.
186 :
187 : If SVAL exceeds the complexity limit, delete it and return an UNKNOWN
188 : value of the same type.
189 : Otherwise update m_max_complexity and carry on. */
190 :
191 : #define RETURN_UNKNOWN_IF_TOO_COMPLEX(SVAL) \
192 : do { \
193 : svalue *sval_ = (SVAL); \
194 : tree type_ = sval_->get_type (); \
195 : if (reject_if_too_complex (sval_)) \
196 : return get_or_create_unknown_svalue (type_); \
197 : } while (0)
198 :
199 : /* svalue consolidation. */
200 :
201 : /* Return the svalue * for a constant_svalue for CST_EXPR,
202 : creating it if necessary.
203 : The constant_svalue instances are reused, based on pointer equality
204 : of trees */
205 :
206 : const svalue *
207 2629513 : region_model_manager::get_or_create_constant_svalue (tree type, tree cst_expr)
208 : {
209 2629513 : gcc_assert (cst_expr);
210 2629513 : gcc_assert (CONSTANT_CLASS_P (cst_expr));
211 2629513 : gcc_assert (type == TREE_TYPE (cst_expr) || type == NULL_TREE);
212 :
213 2629513 : constant_svalue::key_t key (type, cst_expr);
214 2629513 : constant_svalue **slot = m_constants_map.get (key);
215 2629513 : if (slot)
216 2571106 : return *slot;
217 58407 : constant_svalue *cst_sval
218 58407 : = new constant_svalue (alloc_symbol_id (), type, cst_expr);
219 58407 : RETURN_UNKNOWN_IF_TOO_COMPLEX (cst_sval);
220 57603 : m_constants_map.put (key, cst_sval);
221 57603 : return cst_sval;
222 : }
223 :
224 : const svalue *
225 1690620 : region_model_manager::get_or_create_constant_svalue (tree cst_expr)
226 : {
227 1690620 : tree type = TREE_TYPE (cst_expr);
228 1690620 : if (TREE_CODE (cst_expr) == RAW_DATA_CST)
229 : /* The type of a RAW_DATA_CST is the type of each element, rather than
230 : that of the constant as a whole, so use NULL_TREE for simplicity. */
231 14 : type = NULL_TREE;
232 1690620 : return get_or_create_constant_svalue (type, cst_expr);
233 : }
234 :
235 : /* Return the svalue * for a constant_svalue for the INTEGER_CST
236 : for VAL of type TYPE, creating it if necessary. */
237 :
238 : const svalue *
239 900284 : region_model_manager::get_or_create_int_cst (tree type,
240 : const poly_wide_int_ref &cst)
241 : {
242 900284 : tree effective_type = type;
243 900284 : if (!type)
244 7464 : effective_type = ptrdiff_type_node;
245 900284 : gcc_assert (INTEGRAL_TYPE_P (effective_type)
246 : || POINTER_TYPE_P (effective_type));
247 900284 : tree tree_cst = wide_int_to_tree (effective_type, cst);
248 900284 : return get_or_create_constant_svalue (type, tree_cst);
249 : }
250 :
251 : /* Return the svalue * for the constant_svalue for the NULL pointer
252 : of POINTER_TYPE, creating it if necessary. */
253 :
254 : const svalue *
255 1678 : region_model_manager::get_or_create_null_ptr (tree pointer_type)
256 : {
257 1678 : gcc_assert (pointer_type);
258 1678 : gcc_assert (POINTER_TYPE_P (pointer_type));
259 1678 : return get_or_create_int_cst (pointer_type, 0);
260 : }
261 :
262 : /* Return the svalue * for a unknown_svalue for TYPE (which can be NULL_TREE),
263 : creating it if necessary.
264 : The unknown_svalue instances are reused, based on pointer equality
265 : of the types */
266 :
267 : const svalue *
268 858566 : region_model_manager::get_or_create_unknown_svalue (tree type)
269 : {
270 : /* Don't create unknown values when doing feasibility testing;
271 : instead, create a unique svalue. */
272 858566 : if (m_checking_feasibility)
273 12421 : return create_unique_svalue (type);
274 :
275 : /* Special-case NULL, so that the hash_map can use NULL as the
276 : "empty" value. */
277 846145 : if (type == NULL_TREE)
278 : {
279 120817 : if (!m_unknown_NULL)
280 1764 : m_unknown_NULL = new unknown_svalue (alloc_symbol_id (), type);
281 120817 : return m_unknown_NULL;
282 : }
283 :
284 725328 : unknown_svalue **slot = m_unknowns_map.get (type);
285 725328 : if (slot)
286 716411 : return *slot;
287 8917 : unknown_svalue *sval = new unknown_svalue (alloc_symbol_id (), type);
288 8917 : m_unknowns_map.put (type, sval);
289 8917 : return sval;
290 : }
291 :
292 : /* Return a freshly-allocated svalue of TYPE, owned by this manager. */
293 :
294 : const svalue *
295 12421 : region_model_manager::create_unique_svalue (tree type)
296 : {
297 12421 : svalue *sval = new placeholder_svalue (alloc_symbol_id (), type, "unique");
298 12421 : m_managed_dynamic_svalues.safe_push (sval);
299 12421 : return sval;
300 : }
301 :
302 : /* Return the svalue * for the initial value of REG, creating it if
303 : necessary. */
304 :
305 : const svalue *
306 3182991 : region_model_manager::get_or_create_initial_value (const region *reg,
307 : bool check_poisoned)
308 : {
309 3182991 : if (!reg->can_have_initial_svalue_p () && check_poisoned)
310 203754 : return get_or_create_poisoned_svalue (poison_kind::uninit,
311 203754 : reg->get_type ());
312 :
313 : /* The initial value of a cast is a cast of the initial value. */
314 2979237 : if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
315 : {
316 3566 : const region *original_reg = cast_reg->get_parent_region ();
317 3566 : return get_or_create_cast (cast_reg->get_type (),
318 3566 : get_or_create_initial_value (original_reg));
319 : }
320 :
321 : /* Simplify:
322 : INIT_VAL(ELEMENT_REG(STRING_REG), CONSTANT_SVAL)
323 : to:
324 : CONSTANT_SVAL(STRING[N]). */
325 2975671 : if (const element_region *element_reg = reg->dyn_cast_element_region ())
326 7303 : if (tree cst_idx = element_reg->get_index ()->maybe_get_constant ())
327 8516 : if (const string_region *string_reg
328 4258 : = element_reg->get_parent_region ()->dyn_cast_string_region ())
329 702 : if (tree_fits_shwi_p (cst_idx))
330 : {
331 702 : HOST_WIDE_INT idx = tree_to_shwi (cst_idx);
332 702 : tree string_cst = string_reg->get_string_cst ();
333 1404 : if (idx >= 0 && idx <= TREE_STRING_LENGTH (string_cst))
334 : {
335 702 : int ch = TREE_STRING_POINTER (string_cst)[idx];
336 702 : return get_or_create_int_cst (reg->get_type (), ch);
337 : }
338 : }
339 :
340 : /* INIT_VAL (*UNKNOWN_PTR) -> UNKNOWN_VAL. */
341 2974969 : if (reg->symbolic_for_unknown_ptr_p ())
342 7789 : return get_or_create_unknown_svalue (reg->get_type ());
343 :
344 2967180 : if (initial_svalue **slot = m_initial_values_map.get (reg))
345 2938975 : return *slot;
346 28205 : initial_svalue *initial_sval
347 28205 : = new initial_svalue (alloc_symbol_id (), reg->get_type (), reg);
348 28205 : RETURN_UNKNOWN_IF_TOO_COMPLEX (initial_sval);
349 27814 : m_initial_values_map.put (reg, initial_sval);
350 27814 : return initial_sval;
351 : }
352 :
353 : /* Return the svalue * for R using type TYPE, creating it if
354 : necessary. */
355 :
356 : const svalue *
357 34 : region_model_manager::get_or_create_setjmp_svalue (const setjmp_record &r,
358 : tree type)
359 : {
360 34 : setjmp_svalue::key_t key (r, type);
361 34 : if (setjmp_svalue **slot = m_setjmp_values_map.get (key))
362 0 : return *slot;
363 34 : setjmp_svalue *setjmp_sval = new setjmp_svalue (r, alloc_symbol_id (), type);
364 34 : RETURN_UNKNOWN_IF_TOO_COMPLEX (setjmp_sval);
365 34 : m_setjmp_values_map.put (key, setjmp_sval);
366 34 : return setjmp_sval;
367 : }
368 :
369 : /* Return the svalue * for a poisoned value of KIND and TYPE, creating it if
370 : necessary. */
371 :
372 : const svalue *
373 211337 : region_model_manager::get_or_create_poisoned_svalue (enum poison_kind kind,
374 : tree type)
375 : {
376 211337 : poisoned_svalue::key_t key (kind, type);
377 211337 : if (poisoned_svalue **slot = m_poisoned_values_map.get (key))
378 205142 : return *slot;
379 6195 : poisoned_svalue *poisoned_sval
380 6195 : = new poisoned_svalue (kind, alloc_symbol_id (), type);
381 6195 : RETURN_UNKNOWN_IF_TOO_COMPLEX (poisoned_sval);
382 6195 : m_poisoned_values_map.put (key, poisoned_sval);
383 6195 : return poisoned_sval;
384 : }
385 :
386 : /* Return the svalue * for a pointer to POINTEE of type PTR_TYPE,
387 : creating it if necessary. */
388 :
389 : const svalue *
390 1011605 : region_model_manager::get_ptr_svalue (tree ptr_type, const region *pointee)
391 : {
392 : /* If this is a symbolic region from dereferencing a pointer, and the types
393 : match, then return the original pointer. */
394 1011605 : if (const symbolic_region *sym_reg = pointee->dyn_cast_symbolic_region ())
395 183 : if (ptr_type == sym_reg->get_pointer ()->get_type ())
396 : return sym_reg->get_pointer ();
397 :
398 1011438 : region_svalue::key_t key (ptr_type, pointee);
399 1011438 : if (region_svalue **slot = m_pointer_values_map.get (key))
400 984517 : return *slot;
401 26921 : region_svalue *sval
402 26921 : = new region_svalue (alloc_symbol_id (), ptr_type, pointee);
403 26921 : RETURN_UNKNOWN_IF_TOO_COMPLEX (sval);
404 26409 : m_pointer_values_map.put (key, sval);
405 26409 : return sval;
406 : }
407 :
408 : /* Subroutine of region_model_manager::maybe_fold_unaryop
409 : when the arg is a binop_svalue.
410 : Invert comparisons e.g. "!(x == y)" => "x != y".
411 : Otherwise, return nullptr. */
412 :
413 : const svalue *
414 16 : region_model_manager::
415 : maybe_invert_comparison_in_unaryop (tree result_type,
416 : const binop_svalue *binop)
417 : {
418 16 : if (TREE_CODE_CLASS (binop->get_op ()) == tcc_comparison)
419 : {
420 16 : enum tree_code inv_op
421 16 : = invert_tree_comparison (binop->get_op (),
422 16 : HONOR_NANS (binop->get_type ()));
423 16 : if (inv_op != ERROR_MARK)
424 16 : return get_or_create_cast
425 16 : (result_type,
426 : get_or_create_binop (binop->get_type (), inv_op,
427 : binop->get_arg0 (),
428 16 : binop->get_arg1 ()));
429 : }
430 : return nullptr;
431 : }
432 :
433 : /* Subroutine of region_model_manager::get_or_create_unaryop.
434 : Attempt to fold the inputs and return a simpler svalue *.
435 : Otherwise, return nullptr. */
436 :
437 : const svalue *
438 343736 : region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
439 : const svalue *arg)
440 : {
441 : /* Ops on "unknown" are also unknown. */
442 353551 : if (arg->get_kind () == SK_UNKNOWN)
443 43593 : return get_or_create_unknown_svalue (type);
444 : /* Likewise for "poisoned". */
445 619916 : else if (const poisoned_svalue *poisoned_sval
446 309958 : = arg->dyn_cast_poisoned_svalue ())
447 1396 : return get_or_create_poisoned_svalue (poisoned_sval->get_poison_kind (),
448 1396 : type);
449 :
450 308562 : gcc_assert (arg->can_have_associated_state_p ());
451 :
452 308562 : switch (op)
453 : {
454 : default: break;
455 307324 : case VIEW_CONVERT_EXPR:
456 307324 : case NOP_EXPR:
457 307324 : {
458 307324 : if (!type)
459 : return nullptr;
460 :
461 : /* Handle redundant casts. */
462 306259 : if (arg->get_type ()
463 306259 : && useless_type_conversion_p (arg->get_type (), type))
464 : return arg;
465 :
466 : /* Fold "cast<TYPE> (cast <INNER_TYPE> (innermost_arg))
467 : => "cast<TYPE> (innermost_arg)",
468 : unless INNER_TYPE is narrower than TYPE. */
469 152910 : if (const svalue *innermost_arg = arg->maybe_undo_cast ())
470 : {
471 22179 : if (tree inner_type = arg->get_type ())
472 22019 : if (TYPE_SIZE (type)
473 22019 : && TYPE_SIZE (inner_type)
474 44038 : && (fold_binary (LE_EXPR, boolean_type_node,
475 : TYPE_SIZE (type), TYPE_SIZE (inner_type))
476 22019 : == boolean_true_node))
477 : return maybe_fold_unaryop (type, op, innermost_arg);
478 : }
479 : /* Avoid creating symbolic regions for pointer casts by
480 : simplifying (T*)(®ION) to ((T*)®ION). */
481 143095 : if (const region_svalue *region_sval = arg->dyn_cast_region_svalue ())
482 4195 : if (POINTER_TYPE_P (type)
483 333 : && region_sval->get_type ()
484 4349 : && POINTER_TYPE_P (region_sval->get_type ()))
485 64 : return get_ptr_svalue (type, region_sval->get_pointee ());
486 :
487 : /* Casting all zeroes should give all zeroes. */
488 143031 : if (type
489 143031 : && arg->all_zeroes_p ()
490 6642 : && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
491 5861 : return get_or_create_int_cst (type, 0);
492 : }
493 : break;
494 8 : case TRUTH_NOT_EXPR:
495 8 : {
496 : /* Invert comparisons e.g. "!(x == y)" => "x != y". */
497 8 : if (const binop_svalue *binop = arg->dyn_cast_binop_svalue ())
498 16 : if (const svalue *folded
499 8 : = maybe_invert_comparison_in_unaryop (type, binop))
500 : return folded;
501 : }
502 : break;
503 519 : case NEGATE_EXPR:
504 519 : {
505 : /* -(-(VAL)) is VAL, for integer types. */
506 519 : if (const unaryop_svalue *unaryop = arg->dyn_cast_unaryop_svalue ())
507 10 : if (unaryop->get_op () == NEGATE_EXPR
508 1 : && type == unaryop->get_type ()
509 1 : && type
510 11 : && INTEGRAL_TYPE_P (type))
511 1 : return unaryop->get_arg ();
512 : }
513 : break;
514 251 : case BIT_NOT_EXPR:
515 251 : {
516 : /* Invert comparisons for e.g. "~(x == y)" => "x != y". */
517 251 : if (type
518 251 : && TREE_CODE (type) == BOOLEAN_TYPE
519 182 : && arg->get_type ()
520 433 : && TREE_CODE (arg->get_type ()) == BOOLEAN_TYPE)
521 182 : if (const binop_svalue *binop = arg->dyn_cast_binop_svalue ())
522 16 : if (const svalue *folded
523 8 : = maybe_invert_comparison_in_unaryop (type, binop))
524 : return folded;
525 : }
526 : break;
527 : }
528 :
529 : /* Constants. */
530 138391 : if (type)
531 138175 : if (tree cst = arg->maybe_get_constant ())
532 18798 : if (tree result = fold_unary (op, type, cst))
533 : {
534 17835 : if (CONSTANT_CLASS_P (result))
535 17835 : return get_or_create_constant_svalue (result);
536 :
537 : /* fold_unary can return casts of constants; try to handle them. */
538 0 : if (op != NOP_EXPR
539 0 : && TREE_CODE (result) == NOP_EXPR
540 0 : && CONSTANT_CLASS_P (TREE_OPERAND (result, 0)))
541 : {
542 0 : const svalue *inner_cst
543 0 : = get_or_create_constant_svalue (TREE_OPERAND (result, 0));
544 0 : return get_or_create_cast (type,
545 0 : get_or_create_cast (TREE_TYPE (result),
546 0 : inner_cst));
547 : }
548 : }
549 :
550 : return nullptr;
551 : }
552 :
553 : /* Return the svalue * for an unary operation OP on ARG with a result of
554 : type TYPE, creating it if necessary. */
555 :
556 : const svalue *
557 343736 : region_model_manager::get_or_create_unaryop (tree type, enum tree_code op,
558 : const svalue *arg)
559 : {
560 343736 : if (const svalue *folded = maybe_fold_unaryop (type, op, arg))
561 : return folded;
562 121621 : unaryop_svalue::key_t key (type, op, arg);
563 121621 : if (unaryop_svalue **slot = m_unaryop_values_map.get (key))
564 112782 : return *slot;
565 8839 : unaryop_svalue *unaryop_sval
566 8839 : = new unaryop_svalue (alloc_symbol_id (), type, op, arg);
567 8839 : RETURN_UNKNOWN_IF_TOO_COMPLEX (unaryop_sval);
568 8751 : m_unaryop_values_map.put (key, unaryop_sval);
569 8751 : return unaryop_sval;
570 : }
571 :
572 : /* Get a tree code for a cast to DST_TYPE from SRC_TYPE.
573 : Use NOP_EXPR if possible (e.g. to help fold_unary convert casts
574 : of 0 to (T*) to simple pointer constants), but use FIX_TRUNC_EXPR
575 : and VIEW_CONVERT_EXPR for cases that fold_unary would otherwise crash
576 : on. */
577 :
578 : static enum tree_code
579 266633 : get_code_for_cast (tree dst_type, tree src_type)
580 : {
581 0 : if (!dst_type)
582 : return NOP_EXPR;
583 0 : if (!src_type)
584 : return NOP_EXPR;
585 :
586 260888 : if (SCALAR_FLOAT_TYPE_P (src_type))
587 : {
588 355 : if (TREE_CODE (dst_type) == INTEGER_TYPE)
589 : return FIX_TRUNC_EXPR;
590 : else
591 351 : return VIEW_CONVERT_EXPR;
592 : }
593 :
594 : return NOP_EXPR;
595 : }
596 :
597 : /* Return the svalue * for a cast of ARG to type TYPE, creating it
598 : if necessary. */
599 :
600 : const svalue *
601 1274058 : region_model_manager::get_or_create_cast (tree type, const svalue *arg)
602 : {
603 : /* No-op if the types are the same. */
604 1274058 : if (type == arg->get_type ())
605 : return arg;
606 :
607 : /* Don't attempt to handle casts involving vector types for now. */
608 276463 : if (type)
609 266720 : if (VECTOR_TYPE_P (type)
610 266720 : || (arg->get_type ()
611 260888 : && VECTOR_TYPE_P (arg->get_type ())))
612 87 : return get_or_create_unknown_svalue (type);
613 :
614 266633 : enum tree_code op = get_code_for_cast (type, arg->get_type ());
615 276376 : return get_or_create_unaryop (type, op, arg);
616 : }
617 :
618 : /* Subroutine of region_model_manager::maybe_fold_binop for handling
619 : (TYPE)(COMPOUND_SVAL BIT_AND_EXPR CST) that may have been generated by
620 : optimize_bit_field_compare, where CST is from ARG1.
621 :
622 : Support masking out bits from a compound_svalue for comparing a bitfield
623 : against a value, as generated by optimize_bit_field_compare for
624 : BITFIELD == VALUE.
625 :
626 : If COMPOUND_SVAL has a value for the appropriate bits, return it,
627 : shifted accordingly.
628 : Otherwise return nullptr. */
629 :
630 : const svalue *
631 58 : region_model_manager::
632 : maybe_undo_optimize_bit_field_compare (tree type,
633 : const compound_svalue *compound_sval,
634 : tree cst,
635 : const svalue *arg1)
636 : {
637 58 : if (!type)
638 : return nullptr;
639 58 : if (!INTEGRAL_TYPE_P (type))
640 : return nullptr;
641 :
642 56 : const concrete_binding_map &map = compound_sval->get_concrete_bindings ();
643 56 : unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (cst);
644 : /* If "mask" is a contiguous range of set bits, see if the
645 : compound_sval has a value for those bits. */
646 56 : bit_range bits (0, 0);
647 56 : if (!bit_range::from_mask (mask, &bits))
648 : return nullptr;
649 :
650 56 : bit_range bound_bits (bits);
651 56 : if (BYTES_BIG_ENDIAN)
652 : bound_bits = bit_range (BITS_PER_UNIT - bits.get_next_bit_offset (),
653 : bits.m_size_in_bits);
654 56 : const svalue *sval = map.get_any_exact_binding (bound_bits);
655 56 : if (!sval)
656 : {
657 : /* In theory we could also look for bindings that straddle the
658 : bit range. For simplicity, bail out on this case. */
659 : return nullptr;
660 : }
661 :
662 : /* We have a value;
663 : shift it by the correct number of bits. */
664 56 : const svalue *lhs = get_or_create_cast (type, sval);
665 56 : HOST_WIDE_INT bit_offset = bits.get_start_bit_offset ().to_shwi ();
666 56 : const svalue *shift_sval = get_or_create_int_cst (type, bit_offset);
667 56 : const svalue *shifted_sval = get_or_create_binop (type, LSHIFT_EXPR,
668 : lhs, shift_sval);
669 : /* Reapply the mask (needed for negative
670 : signed bitfields). */
671 56 : return get_or_create_binop (type, BIT_AND_EXPR,
672 56 : shifted_sval, arg1);
673 : }
674 :
675 : /* Subroutine of region_model_manager::get_or_create_binop.
676 : Attempt to fold the inputs and return a simpler svalue *.
677 : Otherwise, return nullptr. */
678 :
679 : const svalue *
680 236927 : region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
681 : const svalue *arg0,
682 : const svalue *arg1)
683 : {
684 236927 : tree cst0 = arg0->maybe_get_constant ();
685 236927 : tree cst1 = arg1->maybe_get_constant ();
686 : /* (CST OP CST). */
687 236927 : if (cst0 && cst1)
688 : {
689 79747 : if (type)
690 : {
691 41138 : if (tree result = fold_binary (op, type, cst0, cst1))
692 41100 : if (CONSTANT_CLASS_P (result))
693 41098 : return get_or_create_constant_svalue (result);
694 : }
695 : else
696 : {
697 38609 : if (tree result = int_const_binop (op, cst0, cst1, -1))
698 38609 : return get_or_create_constant_svalue (NULL_TREE, result);
699 : }
700 : }
701 :
702 109678 : if ((type && FLOAT_TYPE_P (type))
703 156733 : || (arg0->get_type () && FLOAT_TYPE_P (arg0->get_type ()))
704 313901 : || (arg1->get_type () && FLOAT_TYPE_P (arg1->get_type ())))
705 : return nullptr;
706 :
707 156671 : switch (op)
708 : {
709 : default:
710 : break;
711 98568 : case POINTER_PLUS_EXPR:
712 98568 : case PLUS_EXPR:
713 : /* (VAL + 0) -> VAL. */
714 98568 : if (cst1 && zerop (cst1))
715 15535 : return get_or_create_cast (type, arg0);
716 : /* X + (-X) -> 0. */
717 83033 : if (const unaryop_svalue *unary_op = arg1->dyn_cast_unaryop_svalue ())
718 2130 : if (unary_op->get_op () == NEGATE_EXPR
719 780 : && unary_op->get_arg () == arg0
720 2252 : && type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
721 120 : return get_or_create_int_cst (type, 0);
722 : /* X + (Y - X) -> Y. */
723 82913 : if (const binop_svalue *bin_op = arg1->dyn_cast_binop_svalue ())
724 9110 : if (bin_op->get_op () == MINUS_EXPR)
725 203 : if (bin_op->get_arg1 () == arg0)
726 8 : return get_or_create_cast (type, bin_op->get_arg0 ());
727 : break;
728 4348 : case MINUS_EXPR:
729 : /* (VAL - 0) -> VAL. */
730 4348 : if (cst1 && zerop (cst1))
731 47 : return get_or_create_cast (type, arg0);
732 : /* (0 - VAL) -> -VAL. */
733 4301 : if (cst0 && zerop (cst0))
734 17 : return get_or_create_unaryop (type, NEGATE_EXPR, arg1);
735 : /* (X + Y) - X -> Y. */
736 4284 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
737 874 : if (binop->get_op () == PLUS_EXPR)
738 139 : if (binop->get_arg0 () == arg1)
739 15 : return get_or_create_cast (type, binop->get_arg1 ());
740 : break;
741 1110 : case POINTER_DIFF_EXPR:
742 : /* (X POINTER_PLUS Y) POINTER_DIFF_EXPR X -> Y. */
743 1110 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
744 257 : if (binop->get_op () == POINTER_PLUS_EXPR)
745 257 : if (binop->get_arg0 () == arg1)
746 142 : return get_or_create_cast (type, binop->get_arg1 ());
747 : break;
748 26642 : case MULT_EXPR:
749 : /* (VAL * 0). */
750 26642 : if (cst1
751 26036 : && zerop (cst1)
752 26706 : && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
753 56 : return get_or_create_int_cst (type, 0);
754 : /* (VAL * 1) -> VAL. */
755 26586 : if (cst1 && integer_onep (cst1))
756 348 : return get_or_create_cast (type, arg0);
757 : break;
758 3292 : case BIT_AND_EXPR:
759 3292 : if (cst1)
760 : {
761 2762 : if (zerop (cst1)
762 2762 : && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
763 : /* "(ARG0 & 0)" -> "0". */
764 58 : return get_or_create_int_cst (type, 0);
765 :
766 5408 : if (const compound_svalue *compound_sval
767 2704 : = arg0->dyn_cast_compound_svalue ())
768 116 : if (const svalue *sval
769 58 : = maybe_undo_optimize_bit_field_compare (type,
770 : compound_sval,
771 : cst1, arg1))
772 : return sval;
773 : }
774 3178 : if (arg0->get_type () == boolean_type_node
775 3178 : && arg1->get_type () == boolean_type_node)
776 : {
777 : /* If the LHS are both _Bool, then... */
778 : /* ..."(1 & x) -> x". */
779 559 : if (cst0 && !zerop (cst0))
780 0 : return get_or_create_cast (type, arg1);
781 : /* ..."(x & 1) -> x". */
782 559 : if (cst1 && !zerop (cst1))
783 268 : return get_or_create_cast (type, arg0);
784 : /* ..."(0 & x) -> 0". */
785 291 : if (cst0 && zerop (cst0))
786 0 : return get_or_create_int_cst (type, 0);
787 : /* ..."(x & 0) -> 0". */
788 291 : if (cst1 && zerop (cst1))
789 0 : return get_or_create_int_cst (type, 0);
790 : }
791 : break;
792 3174 : case BIT_IOR_EXPR:
793 3174 : if (arg0->get_type () == boolean_type_node
794 3174 : && arg1->get_type () == boolean_type_node)
795 : {
796 : /* If the LHS are both _Bool, then... */
797 : /* ..."(1 | x) -> 1". */
798 120 : if (cst0 && !zerop (cst0))
799 0 : return get_or_create_int_cst (type, 1);
800 : /* ..."(x | 1) -> 1". */
801 120 : if (cst1 && !zerop (cst1))
802 38 : return get_or_create_int_cst (type, 1);
803 : /* ..."(0 | x) -> x". */
804 82 : if (cst0 && zerop (cst0))
805 0 : return get_or_create_cast (type, arg1);
806 : /* ..."(x | 0) -> x". */
807 82 : if (cst1 && zerop (cst1))
808 20 : return get_or_create_cast (type, arg0);
809 : }
810 : break;
811 12 : case TRUTH_ANDIF_EXPR:
812 12 : case TRUTH_AND_EXPR:
813 12 : if (cst1)
814 : {
815 12 : if (zerop (cst1) && INTEGRAL_TYPE_P (type))
816 : /* "(ARG0 && 0)" -> "0". */
817 4 : return get_or_create_constant_svalue (build_int_cst (type, 0));
818 : else
819 : /* "(ARG0 && nonzero-cst)" -> "ARG0". */
820 8 : return get_or_create_cast (type, arg0);
821 : }
822 : break;
823 12 : case TRUTH_ORIF_EXPR:
824 12 : case TRUTH_OR_EXPR:
825 12 : if (cst1)
826 : {
827 12 : if (zerop (cst1))
828 : /* "(ARG0 || 0)" -> "ARG0". */
829 8 : return get_or_create_cast (type, arg0);
830 : else
831 : /* "(ARG0 && nonzero-cst)" -> "nonzero-cst". */
832 4 : return get_or_create_cast (type, arg1);
833 : }
834 : break;
835 :
836 1220 : case TRUNC_DIV_EXPR:
837 1220 : case CEIL_DIV_EXPR:
838 1220 : case FLOOR_DIV_EXPR:
839 1220 : case ROUND_DIV_EXPR:
840 1220 : case TRUNC_MOD_EXPR:
841 1220 : case CEIL_MOD_EXPR:
842 1220 : case FLOOR_MOD_EXPR:
843 1220 : case ROUND_MOD_EXPR:
844 1220 : case RDIV_EXPR:
845 1220 : case EXACT_DIV_EXPR:
846 1220 : {
847 1220 : value_range arg1_vr;
848 1220 : if (arg1->maybe_get_value_range (arg1_vr))
849 1123 : if (arg1_vr.zero_p ())
850 0 : return get_or_create_unknown_svalue (type);
851 1220 : }
852 1220 : break;
853 : }
854 :
855 : /* For associative ops, fold "(X op CST_A) op CST_B)" to
856 : "X op (CST_A op CST_B)". */
857 139919 : if (cst1 && associative_tree_code (op))
858 65081 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
859 17027 : if (binop->get_op () == op
860 17027 : && binop->get_arg1 ()->maybe_get_constant ())
861 2632 : return get_or_create_binop
862 2632 : (type, op, binop->get_arg0 (),
863 : get_or_create_binop (type, op,
864 2632 : binop->get_arg1 (), arg1));
865 :
866 : /* associative_tree_code is false for POINTER_PLUS_EXPR, but we
867 : can fold:
868 : "(PTR ptr+ CST_A) ptr+ CST_B)" to "PTR ptr+ (CST_A ptr+ CST_B)"
869 : e.g. in data-model-1.c: test_4c. */
870 137287 : if (cst1 && op == POINTER_PLUS_EXPR)
871 27063 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
872 1661 : if (binop->get_op () == POINTER_PLUS_EXPR)
873 1509 : if (binop->get_arg1 ()->maybe_get_constant ())
874 1168 : return get_or_create_binop
875 1168 : (type, op, binop->get_arg0 (),
876 : get_or_create_binop (size_type_node, op,
877 1168 : binop->get_arg1 (), arg1));
878 :
879 : /* Distribute multiplication by a constant through addition/subtraction:
880 : (X + Y) * CST => (X * CST) + (Y * CST). */
881 136119 : if (cst1 && op == MULT_EXPR)
882 25469 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
883 2817 : if (binop->get_op () == PLUS_EXPR
884 2817 : || binop->get_op () == MINUS_EXPR)
885 : {
886 2146 : return get_or_create_binop
887 2146 : (type, binop->get_op (),
888 : get_or_create_binop (type, op,
889 : binop->get_arg0 (), arg1),
890 : get_or_create_binop (type, op,
891 2146 : binop->get_arg1 (), arg1));
892 : }
893 :
894 :
895 : /* Typeless operations, assumed to be effectively arbitrary sized
896 : integers following normal arithmetic rules. */
897 133973 : if (!type)
898 34751 : switch (op)
899 : {
900 : default:
901 : break;
902 827 : case MINUS_EXPR:
903 827 : {
904 : /* (X - X) -> 0. */
905 827 : if (arg0 == arg1)
906 751 : return get_or_create_int_cst (type, 0);
907 :
908 : /* (X + A) - (A + B) -> (A - B). */
909 76 : if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
910 60 : if (const binop_svalue *binop1 = arg1->dyn_cast_binop_svalue ())
911 36 : if (binop0->get_op () == PLUS_EXPR
912 28 : && binop1->get_op () == PLUS_EXPR
913 56 : && binop0->get_arg0 () == binop1->get_arg0 ())
914 20 : return get_or_create_binop (NULL_TREE, op,
915 : binop0->get_arg1 (),
916 20 : binop1->get_arg1 ());
917 : }
918 : break;
919 :
920 73 : case EXACT_DIV_EXPR:
921 73 : {
922 73 : if (const unaryop_svalue *unaryop0 = arg0->dyn_cast_unaryop_svalue ())
923 : {
924 0 : if (unaryop0->get_op () == NOP_EXPR)
925 0 : if (const svalue *sval = maybe_fold_binop (NULL_TREE, op,
926 : unaryop0->get_arg (),
927 : arg1))
928 : return sval;
929 : }
930 73 : if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
931 : {
932 72 : switch (binop0->get_op ())
933 : {
934 : default:
935 : break;
936 :
937 26 : case PLUS_EXPR:
938 26 : case MINUS_EXPR:
939 : /* (A op B) / C -> (A / C) op (B / C). */
940 26 : {
941 26 : if (const svalue *op_on_a
942 26 : = maybe_fold_binop (NULL_TREE, op,
943 : binop0->get_arg0 (), arg1))
944 26 : if (const svalue *op_on_b
945 26 : = maybe_fold_binop (NULL_TREE, op,
946 : binop0->get_arg1 (), arg1))
947 26 : return get_or_create_binop (NULL_TREE,
948 : binop0->get_op (),
949 26 : op_on_a, op_on_b);
950 : }
951 : break;
952 :
953 46 : case MULT_EXPR:
954 : /* (A * B) / C -> A * (B / C) if C is a divisor of B.
955 : In particular, this should also handle the case
956 : (A * B) / B -> A. */
957 46 : if (const svalue *b_div_c
958 46 : = maybe_fold_binop (NULL_TREE, op,
959 : binop0->get_arg1 (), arg1))
960 46 : return get_or_create_binop (NULL_TREE, binop0->get_op (),
961 46 : binop0->get_arg0 (), b_div_c);
962 : }
963 : }
964 : }
965 : break;
966 : }
967 :
968 : /* etc. */
969 :
970 : return nullptr;
971 : }
972 :
973 : /* Return the svalue * for an binary operation OP on ARG0 and ARG1
974 : with a result of type TYPE, creating it if necessary. */
975 :
976 : const svalue *
977 236648 : region_model_manager::get_or_create_binop (tree type, enum tree_code op,
978 : const svalue *arg0,
979 : const svalue *arg1)
980 : {
981 : /* For commutative ops, put any constant on the RHS. */
982 236648 : if (arg0->maybe_get_constant () && commutative_tree_code (op))
983 : std::swap (arg0, arg1);
984 :
985 236648 : if (const svalue *folded = maybe_fold_binop (type, op, arg0, arg1))
986 : return folded;
987 :
988 : /* Ops on "unknown"/"poisoned" are unknown (unless we were able to fold
989 : it via an identity in maybe_fold_binop). */
990 133678 : if (!arg0->can_have_associated_state_p ()
991 133678 : || !arg1->can_have_associated_state_p ())
992 25539 : return get_or_create_unknown_svalue (type);
993 :
994 108139 : binop_svalue::key_t key (type, op, arg0, arg1);
995 108139 : if (binop_svalue **slot = m_binop_values_map.get (key))
996 87122 : return *slot;
997 21017 : binop_svalue *binop_sval
998 21017 : = new binop_svalue (alloc_symbol_id (), type, op, arg0, arg1);
999 21017 : RETURN_UNKNOWN_IF_TOO_COMPLEX (binop_sval);
1000 20898 : m_binop_values_map.put (key, binop_sval);
1001 20898 : return binop_sval;
1002 : }
1003 :
1004 : /* Subroutine of region_model_manager::get_or_create_sub_svalue.
1005 : Return a folded svalue, or nullptr. */
1006 :
1007 : const svalue *
1008 66220 : region_model_manager::maybe_fold_sub_svalue (tree type,
1009 : const svalue *parent_svalue,
1010 : const region *subregion)
1011 : {
1012 : /* Subvalues of "unknown"/"poisoned" are unknown. */
1013 66220 : if (!parent_svalue->can_have_associated_state_p ())
1014 42589 : return get_or_create_unknown_svalue (type);
1015 :
1016 : /* If we have a subvalue of a zero constant, it's zero. */
1017 23631 : if (tree cst = parent_svalue->maybe_get_constant ())
1018 6521 : if (TREE_CODE (cst) == INTEGER_CST)
1019 132 : if (zerop (cst))
1020 123 : return get_or_create_cast (type, parent_svalue);
1021 :
1022 : /* If we have a subregion of a zero-fill, it's zero. */
1023 47016 : if (const unaryop_svalue *unary
1024 23508 : = parent_svalue->dyn_cast_unaryop_svalue ())
1025 : {
1026 663 : if (unary->get_op () == NOP_EXPR
1027 663 : || unary->get_op () == VIEW_CONVERT_EXPR)
1028 663 : if (tree cst = unary->get_arg ()->maybe_get_constant ())
1029 663 : if (zerop (cst) && type)
1030 : {
1031 651 : const svalue *cst_sval
1032 651 : = get_or_create_constant_svalue (cst);
1033 651 : return get_or_create_cast (type, cst_sval);
1034 : }
1035 : }
1036 :
1037 : /* Handle getting individual chars from a STRING_CST or RAW_DATA_CST. */
1038 22857 : if (tree cst = parent_svalue->maybe_get_constant ())
1039 6398 : if (TREE_CODE (cst) == STRING_CST
1040 6398 : || TREE_CODE (cst) == RAW_DATA_CST)
1041 : {
1042 : /* If we have a concrete 1-byte access within the parent region... */
1043 6376 : byte_range subregion_bytes (0, 0);
1044 6376 : if (subregion->get_relative_concrete_byte_range (&subregion_bytes)
1045 6376 : && subregion_bytes.m_size_in_bytes == 1
1046 12493 : && type)
1047 : {
1048 : /* ...then attempt to get that char from the constant. */
1049 6117 : HOST_WIDE_INT hwi_start_byte
1050 6117 : = subregion_bytes.m_start_byte_offset.to_shwi ();
1051 6117 : tree cst_idx
1052 6117 : = build_int_cst_type (size_type_node, hwi_start_byte);
1053 12234 : if (const svalue *char_sval
1054 6117 : = maybe_get_char_from_cst (cst, cst_idx))
1055 6081 : return get_or_create_cast (type, char_sval);
1056 : }
1057 : }
1058 :
1059 33552 : if (const initial_svalue *init_sval
1060 16776 : = parent_svalue->dyn_cast_initial_svalue ())
1061 : {
1062 : /* SUB(INIT(r)).FIELD -> INIT(r.FIELD)
1063 : i.e.
1064 : Subvalue(InitialValue(R1), FieldRegion(R2, F))
1065 : -> InitialValue(FieldRegion(R1, F)). */
1066 564 : if (const field_region *field_reg = subregion->dyn_cast_field_region ())
1067 : {
1068 358 : const region *field_reg_new
1069 358 : = get_field_region (init_sval->get_region (),
1070 : field_reg->get_field ());
1071 358 : return get_or_create_initial_value (field_reg_new);
1072 : }
1073 : /* SUB(INIT(r)[ELEMENT] -> INIT(e[ELEMENT])
1074 : i.e.
1075 : Subvalue(InitialValue(R1), ElementRegion(R2, IDX))
1076 : -> InitialValue(ElementRegion(R1, IDX)). */
1077 206 : if (const element_region *element_reg = subregion->dyn_cast_element_region ())
1078 : {
1079 124 : const region *element_reg_new
1080 124 : = get_element_region (init_sval->get_region (),
1081 : element_reg->get_type (),
1082 : element_reg->get_index ());
1083 124 : return get_or_create_initial_value (element_reg_new);
1084 : }
1085 : }
1086 :
1087 32588 : if (const repeated_svalue *repeated_sval
1088 16294 : = parent_svalue->dyn_cast_repeated_svalue ())
1089 100 : if (type)
1090 96 : return get_or_create_cast (type, repeated_sval->get_inner_svalue ());
1091 :
1092 : return nullptr;
1093 : }
1094 :
1095 : /* Return the svalue * for extracting a subvalue of type TYPE from
1096 : PARENT_SVALUE based on SUBREGION, creating it if necessary. */
1097 :
1098 : const svalue *
1099 66220 : region_model_manager::get_or_create_sub_svalue (tree type,
1100 : const svalue *parent_svalue,
1101 : const region *subregion)
1102 : {
1103 132440 : if (const svalue *folded
1104 66220 : = maybe_fold_sub_svalue (type, parent_svalue, subregion))
1105 : return folded;
1106 :
1107 16198 : sub_svalue::key_t key (type, parent_svalue, subregion);
1108 16198 : if (sub_svalue **slot = m_sub_values_map.get (key))
1109 13830 : return *slot;
1110 2368 : sub_svalue *sub_sval
1111 2368 : = new sub_svalue (alloc_symbol_id (), type, parent_svalue, subregion);
1112 2368 : RETURN_UNKNOWN_IF_TOO_COMPLEX (sub_sval);
1113 2368 : m_sub_values_map.put (key, sub_sval);
1114 2368 : return sub_sval;
1115 : }
1116 :
1117 : /* Subroutine of region_model_manager::get_or_create_repeated_svalue.
1118 : Return a folded svalue, or nullptr. */
1119 :
1120 : const svalue *
1121 2965 : region_model_manager::maybe_fold_repeated_svalue (tree type,
1122 : const svalue *outer_size,
1123 : const svalue *inner_svalue)
1124 : {
1125 : /* Repeated "unknown"/"poisoned" is unknown. */
1126 2965 : if (!outer_size->can_have_associated_state_p ()
1127 2965 : || !inner_svalue->can_have_associated_state_p ())
1128 8 : return get_or_create_unknown_svalue (type);
1129 :
1130 : /* If INNER_SVALUE is the same size as OUTER_SIZE,
1131 : turn into simply a cast. */
1132 2957 : if (inner_svalue->get_type ())
1133 2945 : if (tree cst_outer_num_bytes = outer_size->maybe_get_constant ())
1134 : {
1135 2791 : HOST_WIDE_INT num_bytes_inner_svalue
1136 2791 : = int_size_in_bytes (inner_svalue->get_type ());
1137 2791 : if (num_bytes_inner_svalue != -1)
1138 2791 : if (num_bytes_inner_svalue
1139 2791 : == (HOST_WIDE_INT)tree_to_uhwi (cst_outer_num_bytes))
1140 : {
1141 261 : if (type)
1142 241 : return get_or_create_cast (type, inner_svalue);
1143 : else
1144 : return inner_svalue;
1145 : }
1146 : }
1147 :
1148 : /* Handle zero-fill of a specific type. */
1149 2696 : if (tree cst = inner_svalue->maybe_get_constant ())
1150 2673 : if (zerop (cst) && type)
1151 680 : return get_or_create_cast (type, inner_svalue);
1152 :
1153 : return nullptr;
1154 : }
1155 :
1156 : /* Return the svalue * of type TYPE in which INNER_SVALUE is repeated
1157 : enough times to be of size OUTER_SIZE, creating it if necessary.
1158 : e.g. for filling buffers with a constant value. */
1159 :
1160 : const svalue *
1161 2965 : region_model_manager::get_or_create_repeated_svalue (tree type,
1162 : const svalue *outer_size,
1163 : const svalue *inner_svalue)
1164 : {
1165 5930 : if (const svalue *folded
1166 2965 : = maybe_fold_repeated_svalue (type, outer_size, inner_svalue))
1167 : return folded;
1168 :
1169 2016 : repeated_svalue::key_t key (type, outer_size, inner_svalue);
1170 2016 : if (repeated_svalue **slot = m_repeated_values_map.get (key))
1171 1504 : return *slot;
1172 512 : repeated_svalue *repeated_sval
1173 512 : = new repeated_svalue (alloc_symbol_id (), type, outer_size, inner_svalue);
1174 512 : RETURN_UNKNOWN_IF_TOO_COMPLEX (repeated_sval);
1175 512 : m_repeated_values_map.put (key, repeated_sval);
1176 512 : return repeated_sval;
1177 : }
1178 :
1179 : /* Attempt to get the bit_range for FIELD within a RECORD_TYPE.
1180 : Return true and write the result to OUT if successful.
1181 : Return false otherwise. */
1182 :
1183 : static bool
1184 954 : get_bit_range_for_field (tree field, bit_range *out)
1185 : {
1186 954 : bit_size_t bit_size;
1187 954 : if (!int_size_in_bits (TREE_TYPE (field), &bit_size))
1188 : return false;
1189 954 : int field_bit_offset = int_bit_position (field);
1190 954 : *out = bit_range (field_bit_offset, bit_size);
1191 954 : return true;
1192 : }
1193 :
1194 : /* Attempt to get the byte_range for FIELD within a RECORD_TYPE.
1195 : Return true and write the result to OUT if successful.
1196 : Return false otherwise. */
1197 :
1198 : static bool
1199 954 : get_byte_range_for_field (tree field, byte_range *out)
1200 : {
1201 954 : bit_range field_bits (0, 0);
1202 954 : if (!get_bit_range_for_field (field, &field_bits))
1203 : return false;
1204 954 : return field_bits.as_byte_range (out);
1205 : }
1206 :
1207 : /* Attempt to determine if there is a specific field within RECORD_TYPE
1208 : at BYTES. If so, return it, and write the location of BYTES relative
1209 : to the field to *OUT_RANGE_WITHIN_FIELD.
1210 : Otherwise, return NULL_TREE.
1211 : For example, given:
1212 : struct foo { uint32 a; uint32; b};
1213 : and
1214 : bytes = {bytes 6-7} (of foo)
1215 : we have bytes 3-4 of field b. */
1216 :
1217 : static tree
1218 954 : get_field_at_byte_range (tree record_type, const byte_range &bytes,
1219 : byte_range *out_range_within_field)
1220 : {
1221 954 : bit_offset_t bit_offset = bytes.m_start_byte_offset * BITS_PER_UNIT;
1222 :
1223 954 : tree field = get_field_at_bit_offset (record_type, bit_offset);
1224 954 : if (!field)
1225 : return NULL_TREE;
1226 :
1227 954 : byte_range field_bytes (0,0);
1228 954 : if (!get_byte_range_for_field (field, &field_bytes))
1229 : return NULL_TREE;
1230 :
1231 : /* Is BYTES fully within field_bytes? */
1232 948 : byte_range bytes_within_field (0,0);
1233 948 : if (!field_bytes.contains_p (bytes, &bytes_within_field))
1234 : return NULL_TREE;
1235 :
1236 396 : *out_range_within_field = bytes_within_field;
1237 396 : return field;
1238 : }
1239 :
1240 : /* Subroutine of region_model_manager::get_or_create_bits_within.
1241 : Return a folded svalue, or NULL. */
1242 :
1243 : const svalue *
1244 21653 : region_model_manager::maybe_fold_bits_within_svalue (tree type,
1245 : const bit_range &bits,
1246 : const svalue *inner_svalue)
1247 : {
1248 21653 : tree inner_type = inner_svalue->get_type ();
1249 : /* Fold:
1250 : BITS_WITHIN ((0, sizeof (VAL), VAL))
1251 : to:
1252 : CAST(TYPE, VAL). */
1253 21653 : if (bits.m_start_bit_offset == 0 && inner_type)
1254 : {
1255 1602 : bit_size_t inner_type_size;
1256 1602 : if (int_size_in_bits (inner_type, &inner_type_size))
1257 1602 : if (inner_type_size == bits.m_size_in_bits)
1258 : {
1259 557 : if (type)
1260 557 : return get_or_create_cast (type, inner_svalue);
1261 : else
1262 : return inner_svalue;
1263 : }
1264 : }
1265 :
1266 : /* Kind-specific folding. */
1267 42192 : if (const svalue *sval
1268 21096 : = inner_svalue->maybe_fold_bits_within (type, bits, this))
1269 : return sval;
1270 :
1271 1886 : byte_range bytes (0,0);
1272 1886 : if (bits.as_byte_range (&bytes) && inner_type)
1273 1738 : switch (TREE_CODE (inner_type))
1274 : {
1275 : default:
1276 : break;
1277 623 : case ARRAY_TYPE:
1278 623 : {
1279 : /* Fold:
1280 : BITS_WITHIN (range, KIND(REG))
1281 : to:
1282 : BITS_WITHIN (range - offsetof(ELEMENT), KIND(REG.ELEMENT))
1283 : if range1 is a byte-range fully within one ELEMENT. */
1284 623 : tree element_type = TREE_TYPE (inner_type);
1285 623 : HOST_WIDE_INT element_byte_size
1286 623 : = int_size_in_bytes (element_type);
1287 623 : if (element_byte_size > 0)
1288 : {
1289 623 : HOST_WIDE_INT start_idx
1290 623 : = (bytes.get_start_byte_offset ().to_shwi ()
1291 623 : / element_byte_size);
1292 623 : HOST_WIDE_INT last_idx
1293 623 : = (bytes.get_last_byte_offset ().to_shwi ()
1294 623 : / element_byte_size);
1295 623 : if (start_idx == last_idx)
1296 : {
1297 760 : if (const initial_svalue *initial_sval
1298 380 : = inner_svalue->dyn_cast_initial_svalue ())
1299 : {
1300 162 : bit_offset_t start_of_element
1301 162 : = start_idx * element_byte_size * BITS_PER_UNIT;
1302 162 : bit_range bits_within_element
1303 162 : (bits.m_start_bit_offset - start_of_element,
1304 162 : bits.m_size_in_bits);
1305 162 : const svalue *idx_sval
1306 162 : = get_or_create_int_cst (integer_type_node, start_idx);
1307 162 : const region *element_reg =
1308 162 : get_element_region (initial_sval->get_region (),
1309 : element_type, idx_sval);
1310 162 : const svalue *element_reg_sval
1311 162 : = get_or_create_initial_value (element_reg);
1312 162 : return get_or_create_bits_within (type,
1313 : bits_within_element,
1314 : element_reg_sval);
1315 : }
1316 : }
1317 : }
1318 : }
1319 : break;
1320 954 : case RECORD_TYPE:
1321 954 : {
1322 : /* Fold:
1323 : BYTES_WITHIN (range, KIND(REG))
1324 : to:
1325 : BYTES_WITHIN (range - offsetof(FIELD), KIND(REG.FIELD))
1326 : if range1 is fully within FIELD. */
1327 954 : byte_range bytes_within_field (0, 0);
1328 954 : if (tree field = get_field_at_byte_range (inner_type, bytes,
1329 : &bytes_within_field))
1330 : {
1331 792 : if (const initial_svalue *initial_sval
1332 396 : = inner_svalue->dyn_cast_initial_svalue ())
1333 : {
1334 213 : const region *field_reg =
1335 213 : get_field_region (initial_sval->get_region (), field);
1336 213 : const svalue *initial_reg_sval
1337 213 : = get_or_create_initial_value (field_reg);
1338 213 : return get_or_create_bits_within
1339 213 : (type,
1340 426 : bytes_within_field.as_bit_range (),
1341 : initial_reg_sval);
1342 : }
1343 : }
1344 : }
1345 741 : break;
1346 : }
1347 : return nullptr;
1348 : }
1349 :
1350 : /* Return the svalue * of type TYPE for extracting BITS from INNER_SVALUE,
1351 : creating it if necessary. */
1352 :
1353 : const svalue *
1354 21653 : region_model_manager::get_or_create_bits_within (tree type,
1355 : const bit_range &bits,
1356 : const svalue *inner_svalue)
1357 : {
1358 43306 : if (const svalue *folded
1359 21653 : = maybe_fold_bits_within_svalue (type, bits, inner_svalue))
1360 : return folded;
1361 :
1362 1511 : bits_within_svalue::key_t key (type, bits, inner_svalue);
1363 1511 : if (bits_within_svalue **slot = m_bits_within_values_map.get (key))
1364 740 : return *slot;
1365 771 : bits_within_svalue *bits_within_sval
1366 771 : = new bits_within_svalue (alloc_symbol_id (), type, bits, inner_svalue);
1367 771 : RETURN_UNKNOWN_IF_TOO_COMPLEX (bits_within_sval);
1368 771 : m_bits_within_values_map.put (key, bits_within_sval);
1369 771 : return bits_within_sval;
1370 : }
1371 :
1372 : /* Return the svalue * that decorates ARG as being unmergeable,
1373 : creating it if necessary. */
1374 :
1375 : const svalue *
1376 869 : region_model_manager::get_or_create_unmergeable (const svalue *arg)
1377 : {
1378 869 : if (arg->get_kind () == SK_UNMERGEABLE)
1379 : return arg;
1380 :
1381 869 : if (unmergeable_svalue **slot = m_unmergeable_values_map.get (arg))
1382 659 : return *slot;
1383 210 : unmergeable_svalue *unmergeable_sval
1384 210 : = new unmergeable_svalue (alloc_symbol_id (), arg);
1385 210 : RETURN_UNKNOWN_IF_TOO_COMPLEX (unmergeable_sval);
1386 210 : m_unmergeable_values_map.put (arg, unmergeable_sval);
1387 210 : return unmergeable_sval;
1388 : }
1389 :
1390 : /* Return the svalue * of type TYPE for the merger of value BASE_SVAL
1391 : and ITER_SVAL at SNODE, creating it if necessary. */
1392 :
1393 : const svalue *
1394 5772 : region_model_manager::
1395 : get_or_create_widening_svalue (tree type,
1396 : const supernode *snode,
1397 : const svalue *base_sval,
1398 : const svalue *iter_sval)
1399 : {
1400 5772 : gcc_assert (base_sval->get_kind () != SK_WIDENING);
1401 5772 : gcc_assert (iter_sval->get_kind () != SK_WIDENING);
1402 5772 : widening_svalue::key_t key (type, snode, base_sval, iter_sval);
1403 5772 : if (widening_svalue **slot = m_widening_values_map.get (key))
1404 3411 : return *slot;
1405 2361 : widening_svalue *widening_sval
1406 : = new widening_svalue (alloc_symbol_id (), type, snode, base_sval,
1407 2361 : iter_sval);
1408 2361 : RETURN_UNKNOWN_IF_TOO_COMPLEX (widening_sval);
1409 2361 : m_widening_values_map.put (key, widening_sval);
1410 2361 : return widening_sval;
1411 : }
1412 :
1413 : /* Return the svalue * of type TYPE for the compound values in MAP,
1414 : creating it if necessary. */
1415 :
1416 : const svalue *
1417 3750 : region_model_manager::get_or_create_compound_svalue (tree type,
1418 : concrete_binding_map &&map)
1419 : {
1420 3750 : compound_svalue::key_t tmp_key (type, &map);
1421 3750 : if (compound_svalue **slot = m_compound_values_map.get (tmp_key))
1422 3139 : return *slot;
1423 611 : compound_svalue *compound_sval
1424 611 : = new compound_svalue (alloc_symbol_id (), type, std::move (map));
1425 611 : RETURN_UNKNOWN_IF_TOO_COMPLEX (compound_sval);
1426 : /* Use make_key rather than reusing the key, so that we use a
1427 : ptr to compound_sval's binding_map, rather than the MAP param. */
1428 611 : m_compound_values_map.put (compound_sval->make_key (), compound_sval);
1429 611 : return compound_sval;
1430 : }
1431 :
1432 : /* Return the svalue * of type TYPE for the compound values in MAP,
1433 : creating it if necessary. */
1434 :
1435 : const svalue *
1436 220 : region_model_manager::get_or_create_compound_svalue (tree type,
1437 : const concrete_binding_map &map)
1438 : {
1439 220 : compound_svalue::key_t tmp_key (type, &map);
1440 220 : if (compound_svalue **slot = m_compound_values_map.get (tmp_key))
1441 170 : return *slot;
1442 50 : compound_svalue *compound_sval
1443 50 : = new compound_svalue (alloc_symbol_id (), type, map);
1444 50 : RETURN_UNKNOWN_IF_TOO_COMPLEX (compound_sval);
1445 : /* Use make_key rather than reusing the key, so that we use a
1446 : ptr to compound_sval's binding_map, rather than the MAP param. */
1447 50 : m_compound_values_map.put (compound_sval->make_key (), compound_sval);
1448 50 : return compound_sval;
1449 : }
1450 :
1451 : /* class conjured_purge. */
1452 :
1453 : /* Purge state relating to SVAL. */
1454 :
1455 : void
1456 30201 : conjured_purge::purge (const conjured_svalue *sval) const
1457 : {
1458 30201 : m_model->purge_state_involving (sval, m_ctxt);
1459 30201 : }
1460 :
1461 : /* Return the svalue * of type TYPE for the value conjured for ID_REG
1462 : at STMT (using IDX for any further disambiguation),
1463 : creating it if necessary.
1464 : Use P to purge existing state from the svalue, for the case where a
1465 : conjured_svalue would be reused along an execution path. */
1466 :
1467 : const svalue *
1468 56892 : region_model_manager::get_or_create_conjured_svalue (tree type,
1469 : const gimple *stmt,
1470 : const region *id_reg,
1471 : const conjured_purge &p,
1472 : unsigned idx)
1473 : {
1474 56892 : conjured_svalue::key_t key (type, stmt, id_reg, idx);
1475 56892 : if (conjured_svalue **slot = m_conjured_values_map.get (key))
1476 : {
1477 30201 : const conjured_svalue *sval = *slot;
1478 : /* We're reusing an existing conjured_svalue, perhaps from a different
1479 : state within this analysis, or perhaps from an earlier state on this
1480 : execution path. For the latter, purge any state involving the "new"
1481 : svalue from the current program_state. */
1482 30201 : p.purge (sval);
1483 30201 : return sval;
1484 : }
1485 26691 : conjured_svalue *conjured_sval
1486 26691 : = new conjured_svalue (alloc_symbol_id (), type, stmt, id_reg, idx);
1487 26691 : RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
1488 26621 : m_conjured_values_map.put (key, conjured_sval);
1489 26621 : return conjured_sval;
1490 : }
1491 :
1492 : /* Subroutine of region_model_manager::get_or_create_asm_output_svalue.
1493 : Return a folded svalue, or nullptr. */
1494 :
1495 : const svalue *
1496 367 : region_model_manager::
1497 : maybe_fold_asm_output_svalue (tree type,
1498 : const vec<const svalue *> &inputs)
1499 : {
1500 : /* Unknown inputs should lead to unknown results. */
1501 1653 : for (const auto &iter : inputs)
1502 609 : if (iter->get_kind () == SK_UNKNOWN)
1503 9 : return get_or_create_unknown_svalue (type);
1504 :
1505 : return nullptr;
1506 : }
1507 :
1508 : /* Return the svalue * of type TYPE for OUTPUT_IDX of the deterministic
1509 : asm stmt ASM_STMT, given INPUTS as inputs. */
1510 :
1511 : const svalue *
1512 289 : region_model_manager::
1513 : get_or_create_asm_output_svalue (tree type,
1514 : const gasm *asm_stmt,
1515 : unsigned output_idx,
1516 : const vec<const svalue *> &inputs)
1517 : {
1518 289 : gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
1519 :
1520 578 : if (const svalue *folded
1521 289 : = maybe_fold_asm_output_svalue (type, inputs))
1522 : return folded;
1523 :
1524 280 : const char *asm_string = gimple_asm_string (asm_stmt);
1525 280 : const unsigned noutputs = gimple_asm_noutputs (asm_stmt);
1526 :
1527 280 : asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
1528 280 : if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
1529 108 : return *slot;
1530 172 : asm_output_svalue *asm_output_sval
1531 : = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
1532 172 : noutputs, inputs);
1533 172 : RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
1534 167 : m_asm_output_values_map.put (key, asm_output_sval);
1535 167 : return asm_output_sval;
1536 : }
1537 :
1538 : /* Return the svalue * of type TYPE for OUTPUT_IDX of a deterministic
1539 : asm stmt with string ASM_STRING with NUM_OUTPUTS outputs, given
1540 : INPUTS as inputs. */
1541 :
1542 : const svalue *
1543 78 : region_model_manager::
1544 : get_or_create_asm_output_svalue (tree type,
1545 : const char *asm_string,
1546 : unsigned output_idx,
1547 : unsigned num_outputs,
1548 : const vec<const svalue *> &inputs)
1549 : {
1550 78 : gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
1551 :
1552 156 : if (const svalue *folded
1553 78 : = maybe_fold_asm_output_svalue (type, inputs))
1554 : return folded;
1555 :
1556 78 : asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
1557 78 : if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
1558 58 : return *slot;
1559 20 : asm_output_svalue *asm_output_sval
1560 : = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
1561 20 : num_outputs, inputs);
1562 20 : RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
1563 20 : m_asm_output_values_map.put (key, asm_output_sval);
1564 20 : return asm_output_sval;
1565 : }
1566 :
1567 : /* Return the svalue * of type TYPE for the result of a call to FNDECL
1568 : with __attribute__((const)), given INPUTS as inputs. */
1569 :
1570 : const svalue *
1571 955 : region_model_manager::
1572 : get_or_create_const_fn_result_svalue (tree type,
1573 : tree fndecl,
1574 : const vec<const svalue *> &inputs)
1575 : {
1576 955 : gcc_assert (fndecl);
1577 955 : gcc_assert (DECL_P (fndecl));
1578 955 : gcc_assert (TREE_READONLY (fndecl));
1579 955 : gcc_assert (inputs.length () <= const_fn_result_svalue::MAX_INPUTS);
1580 :
1581 955 : const_fn_result_svalue::key_t key (type, fndecl, inputs);
1582 955 : if (const_fn_result_svalue **slot = m_const_fn_result_values_map.get (key))
1583 768 : return *slot;
1584 187 : const_fn_result_svalue *const_fn_result_sval
1585 187 : = new const_fn_result_svalue (alloc_symbol_id (), type, fndecl, inputs);
1586 187 : RETURN_UNKNOWN_IF_TOO_COMPLEX (const_fn_result_sval);
1587 187 : m_const_fn_result_values_map.put (key, const_fn_result_sval);
1588 187 : return const_fn_result_sval;
1589 : }
1590 :
1591 : /* Given DATA_CST (a STRING_CST or RAW_DATA_CST) and BYTE_OFFSET_CST a constant,
1592 : attempt to get the character at that offset, returning either
1593 : the svalue for the character constant, or nullptr if unsuccessful. */
1594 :
1595 : const svalue *
1596 6117 : region_model_manager::maybe_get_char_from_cst (tree data_cst,
1597 : tree byte_offset_cst)
1598 : {
1599 6117 : switch (TREE_CODE (data_cst))
1600 : {
1601 0 : default: gcc_unreachable ();
1602 4625 : case STRING_CST:
1603 4625 : return maybe_get_char_from_string_cst (data_cst, byte_offset_cst);
1604 1492 : case RAW_DATA_CST:
1605 1492 : return maybe_get_char_from_raw_data_cst (data_cst, byte_offset_cst);
1606 : }
1607 : }
1608 :
1609 : /* Get a tree for the size of STRING_CST, or NULL_TREE.
1610 : Note that this may be larger than TREE_STRING_LENGTH (implying
1611 : a run of trailing zero bytes from TREE_STRING_LENGTH up to this
1612 : higher limit). */
1613 :
1614 : tree
1615 5490 : get_string_cst_size (const_tree string_cst)
1616 : {
1617 5490 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1618 5490 : gcc_assert (TREE_CODE (TREE_TYPE (string_cst)) == ARRAY_TYPE);
1619 :
1620 5490 : return TYPE_SIZE_UNIT (TREE_TYPE (string_cst));
1621 : }
1622 :
1623 : /* Given STRING_CST, a STRING_CST and BYTE_OFFSET_CST a constant,
1624 : attempt to get the character at that offset, returning either
1625 : the svalue for the character constant, or nullptr if unsuccessful. */
1626 :
1627 : const svalue *
1628 5027 : region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
1629 : tree byte_offset_cst)
1630 : {
1631 5027 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1632 :
1633 : /* Adapted from fold_read_from_constant_string. */
1634 5027 : scalar_int_mode char_mode;
1635 5027 : if (TREE_CODE (byte_offset_cst) == INTEGER_CST
1636 10054 : && is_int_mode (TYPE_MODE (TREE_TYPE (TREE_TYPE (string_cst))),
1637 : &char_mode)
1638 10054 : && GET_MODE_SIZE (char_mode) == 1)
1639 : {
1640 : /* If we're beyond the string_cst, the read is unsuccessful. */
1641 5027 : if (compare_constants (byte_offset_cst,
1642 : GE_EXPR,
1643 5027 : get_string_cst_size (string_cst)).is_true ())
1644 : return nullptr;
1645 :
1646 4995 : int char_val;
1647 9990 : if (compare_tree_int (byte_offset_cst,
1648 4995 : TREE_STRING_LENGTH (string_cst)) < 0)
1649 : /* We're within the area defined by TREE_STRING_POINTER. */
1650 4993 : char_val = (TREE_STRING_POINTER (string_cst)
1651 4993 : [TREE_INT_CST_LOW (byte_offset_cst)]);
1652 : else
1653 : /* We're in the padding area of trailing zeroes. */
1654 : char_val = 0;
1655 4995 : tree char_cst
1656 4995 : = build_int_cst_type (TREE_TYPE (TREE_TYPE (string_cst)), char_val);
1657 4995 : return get_or_create_constant_svalue (char_cst);
1658 : }
1659 : return nullptr;
1660 : }
1661 :
1662 : /* Given RAW_DATA_CST, a RAW_DATA_CST and BYTE_OFFSET_CST a constant,
1663 : attempt to get the character at that offset, returning either
1664 : the svalue for the character constant, or nullptr if unsuccessful. */
1665 :
1666 : const svalue *
1667 1492 : region_model_manager::maybe_get_char_from_raw_data_cst (tree raw_data_cst,
1668 : tree byte_offset_cst)
1669 : {
1670 1492 : gcc_assert (TREE_CODE (raw_data_cst) == RAW_DATA_CST);
1671 1492 : gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST);
1672 :
1673 1492 : offset_int o = (wi::to_offset (byte_offset_cst));
1674 1492 : if (o >= 0 && o < RAW_DATA_LENGTH (raw_data_cst))
1675 1484 : return get_or_create_int_cst
1676 1484 : (TREE_TYPE (raw_data_cst),
1677 2968 : RAW_DATA_UCHAR_ELT (raw_data_cst, o.to_uhwi ()));
1678 : return nullptr;
1679 : }
1680 :
1681 : /* region consolidation. */
1682 :
1683 : /* Return the region for FNDECL, creating it if necessary. */
1684 :
1685 : const function_region *
1686 918514 : region_model_manager::get_region_for_fndecl (tree fndecl)
1687 : {
1688 918514 : gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
1689 :
1690 918514 : function_region **slot = m_fndecls_map.get (fndecl);
1691 918514 : if (slot)
1692 908556 : return *slot;
1693 9958 : function_region *reg
1694 9958 : = new function_region (alloc_symbol_id (), &m_code_region, fndecl);
1695 9958 : m_fndecls_map.put (fndecl, reg);
1696 9958 : return reg;
1697 : }
1698 :
1699 : /* Return the region for LABEL, creating it if necessary. */
1700 :
1701 : const label_region *
1702 465 : region_model_manager::get_region_for_label (tree label)
1703 : {
1704 465 : gcc_assert (TREE_CODE (label) == LABEL_DECL);
1705 :
1706 465 : label_region **slot = m_labels_map.get (label);
1707 465 : if (slot)
1708 415 : return *slot;
1709 :
1710 50 : tree fndecl = DECL_CONTEXT (label);
1711 50 : gcc_assert (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL);
1712 :
1713 50 : const function_region *func_reg = get_region_for_fndecl (fndecl);
1714 50 : label_region *reg
1715 50 : = new label_region (alloc_symbol_id (), func_reg, label);
1716 50 : m_labels_map.put (label, reg);
1717 50 : return reg;
1718 : }
1719 :
1720 : /* Return the region for EXPR, creating it if necessary. */
1721 :
1722 : const decl_region *
1723 52241 : region_model_manager::get_region_for_global (tree expr)
1724 : {
1725 52241 : gcc_assert (VAR_P (expr));
1726 :
1727 52241 : decl_region **slot = m_globals_map.get (expr);
1728 52241 : if (slot)
1729 45843 : return *slot;
1730 6398 : decl_region *reg
1731 6398 : = new decl_region (alloc_symbol_id (), &m_globals_region, expr);
1732 6398 : m_globals_map.put (expr, reg);
1733 6398 : return reg;
1734 : }
1735 :
1736 : /* Return the region for an unknown access of type REGION_TYPE,
1737 : creating it if necessary.
1738 : This is a symbolic_region, where the pointer is an unknown_svalue
1739 : of type ®ION_TYPE. */
1740 :
1741 : const region *
1742 13300 : region_model_manager::get_unknown_symbolic_region (tree region_type)
1743 : {
1744 13300 : tree ptr_type = region_type ? build_pointer_type (region_type) : NULL_TREE;
1745 13300 : const svalue *unknown_ptr = get_or_create_unknown_svalue (ptr_type);
1746 13300 : return get_symbolic_region (unknown_ptr);
1747 : }
1748 :
1749 : /* Return the region that describes accessing field FIELD of PARENT,
1750 : creating it if necessary. */
1751 :
1752 : const region *
1753 54591 : region_model_manager::get_field_region (const region *parent, tree field)
1754 : {
1755 54591 : gcc_assert (parent);
1756 54591 : gcc_assert (field);
1757 54591 : gcc_assert (TREE_CODE (field) == FIELD_DECL);
1758 :
1759 : /* (*UNKNOWN_PTR).field is (*UNKNOWN_PTR_OF_&FIELD_TYPE). */
1760 54591 : if (parent->symbolic_for_unknown_ptr_p ())
1761 4355 : return get_unknown_symbolic_region (TREE_TYPE (field));
1762 :
1763 50236 : field_region::key_t key (parent, field);
1764 91344 : if (field_region *reg = m_field_regions.get (key))
1765 : return reg;
1766 :
1767 9128 : field_region *field_reg
1768 9128 : = new field_region (alloc_symbol_id (), parent, field);
1769 9128 : m_field_regions.put (key, field_reg);
1770 9128 : return field_reg;
1771 : }
1772 :
1773 : /* Return the region that describes accessing the element of type
1774 : ELEMENT_TYPE at index INDEX of PARENT, creating it if necessary. */
1775 :
1776 : const region *
1777 29472 : region_model_manager::get_element_region (const region *parent,
1778 : tree element_type,
1779 : const svalue *index)
1780 : {
1781 : /* (UNKNOWN_PTR[IDX]) is (UNKNOWN_PTR). */
1782 29472 : if (parent->symbolic_for_unknown_ptr_p ())
1783 52 : return get_unknown_symbolic_region (element_type);
1784 :
1785 29420 : element_region::key_t key (parent, element_type, index);
1786 54600 : if (element_region *reg = m_element_regions.get (key))
1787 : return reg;
1788 :
1789 4240 : element_region *element_reg
1790 4240 : = new element_region (alloc_symbol_id (), parent, element_type, index);
1791 4240 : m_element_regions.put (key, element_reg);
1792 4240 : return element_reg;
1793 : }
1794 :
1795 : /* Return the region that describes accessing the subregion of type
1796 : ELEMENT_TYPE at offset BYTE_OFFSET within PARENT, creating it if
1797 : necessary. */
1798 :
1799 : const region *
1800 102206 : region_model_manager::get_offset_region (const region *parent,
1801 : tree type,
1802 : const svalue *byte_offset)
1803 : {
1804 : /* (UNKNOWN_PTR + OFFSET) is (UNKNOWN_PTR). */
1805 103331 : if (parent->symbolic_for_unknown_ptr_p ())
1806 8405 : return get_unknown_symbolic_region (type);
1807 :
1808 : /* If BYTE_OFFSET is zero, return PARENT. */
1809 94926 : if (tree cst_offset = byte_offset->maybe_get_constant ())
1810 85241 : if (zerop (cst_offset))
1811 70295 : return get_cast_region (parent, type);
1812 :
1813 : /* Fold OFFSET_REGION(OFFSET_REGION(REG, X), Y)
1814 : to OFFSET_REGION(REG, (X + Y)). */
1815 49262 : if (const offset_region *parent_offset_reg
1816 24631 : = parent->dyn_cast_offset_region ())
1817 : {
1818 1125 : const svalue *sval_x = parent_offset_reg->get_byte_offset ();
1819 1125 : const svalue *sval_sum
1820 1125 : = get_or_create_binop (byte_offset->get_type (),
1821 : POINTER_PLUS_EXPR, sval_x, byte_offset);
1822 1125 : return get_offset_region (parent->get_parent_region (), type, sval_sum);
1823 : }
1824 :
1825 23506 : offset_region::key_t key (parent, type, byte_offset);
1826 43355 : if (offset_region *reg = m_offset_regions.get (key))
1827 : return reg;
1828 :
1829 3657 : offset_region *offset_reg
1830 3657 : = new offset_region (alloc_symbol_id (), parent, type, byte_offset);
1831 3657 : m_offset_regions.put (key, offset_reg);
1832 3657 : return offset_reg;
1833 : }
1834 :
1835 : /* Return the region that describes accessing the subregion of type
1836 : TYPE of size BYTE_SIZE_SVAL within PARENT, creating it if necessary. */
1837 :
1838 : const region *
1839 10826 : region_model_manager::get_sized_region (const region *parent,
1840 : tree type,
1841 : const svalue *byte_size_sval)
1842 : {
1843 10826 : if (parent->symbolic_for_unknown_ptr_p ())
1844 276 : return get_unknown_symbolic_region (type);
1845 :
1846 10550 : if (byte_size_sval->get_type () != size_type_node)
1847 2587 : byte_size_sval = get_or_create_cast (size_type_node, byte_size_sval);
1848 :
1849 : /* If PARENT is already that size, return it. */
1850 10550 : const svalue *parent_byte_size_sval = parent->get_byte_size_sval (this);
1851 10550 : if (tree parent_size_cst = parent_byte_size_sval->maybe_get_constant ())
1852 3221 : if (tree size_cst = byte_size_sval->maybe_get_constant ())
1853 : {
1854 2320 : tree comparison
1855 2320 : = fold_binary (EQ_EXPR, boolean_type_node, parent_size_cst, size_cst);
1856 2320 : if (comparison == boolean_true_node)
1857 : return parent;
1858 : }
1859 :
1860 9188 : sized_region::key_t key (parent, type, byte_size_sval);
1861 14169 : if (sized_region *reg = m_sized_regions.get (key))
1862 : return reg;
1863 :
1864 4207 : sized_region *sized_reg
1865 4207 : = new sized_region (alloc_symbol_id (), parent, type, byte_size_sval);
1866 4207 : m_sized_regions.put (key, sized_reg);
1867 4207 : return sized_reg;
1868 : }
1869 :
1870 : /* Return the region that describes accessing PARENT_REGION as if
1871 : it were of type TYPE, creating it if necessary. */
1872 :
1873 : const region *
1874 73056 : region_model_manager::get_cast_region (const region *original_region,
1875 : tree type)
1876 : {
1877 : /* If types match, return ORIGINAL_REGION. */
1878 73056 : if (type == original_region->get_type ())
1879 : return original_region;
1880 :
1881 20969 : if (original_region->symbolic_for_unknown_ptr_p ())
1882 96 : return get_unknown_symbolic_region (type);
1883 :
1884 20873 : cast_region::key_t key (original_region, type);
1885 38542 : if (cast_region *reg = m_cast_regions.get (key))
1886 : return reg;
1887 :
1888 3204 : cast_region *cast_reg
1889 3204 : = new cast_region (alloc_symbol_id (), original_region, type);
1890 3204 : m_cast_regions.put (key, cast_reg);
1891 3204 : return cast_reg;
1892 : }
1893 :
1894 : /* Return the frame_region for call to FUN from CALLING_FRAME, creating it
1895 : if necessary. CALLING_FRAME may be nullptr. */
1896 :
1897 : const frame_region *
1898 41182 : region_model_manager::get_frame_region (const frame_region *calling_frame,
1899 : const function &fun)
1900 : {
1901 41182 : int index = calling_frame ? calling_frame->get_index () + 1 : 0;
1902 :
1903 41182 : frame_region::key_t key (calling_frame, fun);
1904 65858 : if (frame_region *reg = m_frame_regions.get (key))
1905 : return reg;
1906 :
1907 16506 : frame_region *frame_reg
1908 : = new frame_region (alloc_symbol_id (), &m_stack_region, calling_frame,
1909 16506 : fun, index);
1910 16506 : m_frame_regions.put (key, frame_reg);
1911 16506 : return frame_reg;
1912 : }
1913 :
1914 : /* Return the region that describes dereferencing SVAL, creating it
1915 : if necessary. */
1916 :
1917 : const region *
1918 80104 : region_model_manager::get_symbolic_region (const svalue *sval)
1919 : {
1920 80104 : symbolic_region::key_t key (&m_root_region, sval);
1921 151300 : if (symbolic_region *reg = m_symbolic_regions.get (key))
1922 : return reg;
1923 :
1924 8908 : symbolic_region *symbolic_reg
1925 8908 : = new symbolic_region (alloc_symbol_id (), &m_root_region, sval);
1926 8908 : m_symbolic_regions.put (key, symbolic_reg);
1927 8908 : return symbolic_reg;
1928 : }
1929 :
1930 : /* Return the region that describes accessing STRING_CST, creating it
1931 : if necessary. */
1932 :
1933 : const string_region *
1934 15749 : region_model_manager::get_region_for_string (tree string_cst)
1935 : {
1936 15749 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1937 :
1938 15749 : string_region **slot = m_string_map.get (string_cst);
1939 15749 : if (slot)
1940 11914 : return *slot;
1941 3835 : string_region *reg
1942 3835 : = new string_region (alloc_symbol_id (), &m_root_region, string_cst);
1943 3835 : m_string_map.put (string_cst, reg);
1944 3835 : return reg;
1945 : }
1946 :
1947 : /* Return the region that describes accessing BITS within PARENT as TYPE,
1948 : creating it if necessary. */
1949 :
1950 : const region *
1951 247 : region_model_manager::get_bit_range (const region *parent, tree type,
1952 : const bit_range &bits)
1953 : {
1954 247 : gcc_assert (parent);
1955 :
1956 247 : if (parent->symbolic_for_unknown_ptr_p ())
1957 0 : return get_unknown_symbolic_region (type);
1958 :
1959 247 : bit_range_region::key_t key (parent, type, bits);
1960 327 : if (bit_range_region *reg = m_bit_range_regions.get (key))
1961 : return reg;
1962 :
1963 167 : bit_range_region *bit_range_reg
1964 167 : = new bit_range_region (alloc_symbol_id (), parent, type, bits);
1965 167 : m_bit_range_regions.put (key, bit_range_reg);
1966 167 : return bit_range_reg;
1967 : }
1968 :
1969 : /* Return the region that describes accessing the IDX-th variadic argument
1970 : within PARENT_FRAME, creating it if necessary. */
1971 :
1972 : const var_arg_region *
1973 1311 : region_model_manager::get_var_arg_region (const frame_region *parent_frame,
1974 : unsigned idx)
1975 : {
1976 1311 : gcc_assert (parent_frame);
1977 :
1978 1311 : var_arg_region::key_t key (parent_frame, idx);
1979 2125 : if (var_arg_region *reg = m_var_arg_regions.get (key))
1980 : return reg;
1981 :
1982 497 : var_arg_region *var_arg_reg
1983 497 : = new var_arg_region (alloc_symbol_id (), parent_frame, idx);
1984 497 : m_var_arg_regions.put (key, var_arg_reg);
1985 497 : return var_arg_reg;
1986 : }
1987 :
1988 : /* If we see a tree code we don't know how to handle, rather than
1989 : ICE or generate bogus results, create a dummy region, and notify
1990 : CTXT so that it can mark the new state as being not properly
1991 : modelled. The exploded graph can then stop exploring that path,
1992 : since any diagnostics we might issue will have questionable
1993 : validity. */
1994 :
1995 : const region *
1996 84 : region_model_manager::
1997 : get_region_for_unexpected_tree_code (region_model_context *ctxt,
1998 : tree t,
1999 : const dump_location_t &loc)
2000 : {
2001 84 : tree type = TYPE_P (t) ? t : TREE_TYPE (t);
2002 84 : region *new_reg
2003 84 : = new unknown_region (alloc_symbol_id (), &m_root_region, type);
2004 84 : if (ctxt)
2005 52 : ctxt->on_unexpected_tree_code (t, loc);
2006 84 : return new_reg;
2007 : }
2008 :
2009 : /* Return a region describing a heap-allocated block of memory.
2010 : Reuse an existing heap_allocated_region is its id is not within
2011 : BASE_REGS_IN_USE. */
2012 :
2013 : const region *
2014 21025 : region_model_manager::
2015 : get_or_create_region_for_heap_alloc (const bitmap &base_regs_in_use)
2016 : {
2017 : /* Try to reuse an existing region, if it's unreferenced in the
2018 : client state. */
2019 79926 : for (auto existing_reg : m_managed_dynamic_regions)
2020 38590 : if (!bitmap_bit_p (base_regs_in_use, existing_reg->get_id ()))
2021 19386 : if (existing_reg->get_kind () == RK_HEAP_ALLOCATED)
2022 : return existing_reg;
2023 :
2024 : /* All existing ones (if any) are in use; create a new one. */
2025 1742 : region *reg
2026 1742 : = new heap_allocated_region (alloc_symbol_id (), &m_heap_region);
2027 1742 : m_managed_dynamic_regions.safe_push (reg);
2028 1742 : return reg;
2029 : }
2030 :
2031 : /* Return a new region describing a block of memory allocated within FRAME. */
2032 :
2033 : const region *
2034 1137 : region_model_manager::create_region_for_alloca (const frame_region *frame)
2035 : {
2036 1137 : gcc_assert (frame);
2037 1137 : region *reg = new alloca_region (alloc_symbol_id (), frame);
2038 1137 : m_managed_dynamic_regions.safe_push (reg);
2039 1137 : return reg;
2040 : }
2041 :
2042 : /* Log OBJ to LOGGER. */
2043 :
2044 : template <typename T>
2045 : static void
2046 211 : log_managed_object (logger *logger, const T *obj)
2047 : {
2048 211 : logger->start_log_line ();
2049 211 : pretty_printer *pp = logger->get_printer ();
2050 211 : pp_string (pp, " ");
2051 211 : obj->dump_to_pp (pp, true);
2052 211 : logger->end_log_line ();
2053 211 : }
2054 :
2055 : /* Specialization for frame_region, which also logs the count of locals
2056 : managed by the frame_region. */
2057 :
2058 : template <>
2059 : void
2060 6 : log_managed_object (logger *logger, const frame_region *obj)
2061 : {
2062 6 : logger->start_log_line ();
2063 6 : pretty_printer *pp = logger->get_printer ();
2064 6 : pp_string (pp, " ");
2065 6 : obj->dump_to_pp (pp, true);
2066 6 : pp_printf (pp, " [with %i region(s) for locals]", obj->get_num_locals ());
2067 6 : logger->end_log_line ();
2068 6 : }
2069 :
2070 : /* Dump the number of objects that were managed by UNIQ_MAP to LOGGER.
2071 : If SHOW_OBJS is true, also dump the objects themselves. */
2072 :
2073 : template <typename K, typename T>
2074 : static void
2075 105 : log_uniq_map (logger *logger, bool show_objs, const char *title,
2076 : const hash_map<K, T*> &uniq_map)
2077 : {
2078 105 : logger->log (" # %s: %li", title, (long)uniq_map.elements ());
2079 105 : if (!show_objs)
2080 0 : return;
2081 105 : auto_vec<const T *> vec_objs (uniq_map.elements ());
2082 105 : for (typename hash_map<K, T*>::iterator iter = uniq_map.begin ();
2083 376 : iter != uniq_map.end (); ++iter)
2084 166 : vec_objs.quick_push ((*iter).second);
2085 :
2086 271 : vec_objs.qsort (T::cmp_ptr_ptr);
2087 :
2088 : unsigned i;
2089 : const T *obj;
2090 306 : FOR_EACH_VEC_ELT (vec_objs, i, obj)
2091 166 : log_managed_object<T> (logger, obj);
2092 105 : }
2093 :
2094 : /* Dump the number of objects that were managed by MAP to LOGGER.
2095 : If SHOW_OBJS is true, also dump the objects themselves. */
2096 :
2097 : template <typename T>
2098 : static void
2099 55 : log_uniq_map (logger *logger, bool show_objs, const char *title,
2100 : const consolidation_map<T> &map)
2101 : {
2102 55 : logger->log (" # %s: %li", title, (long)map.elements ());
2103 55 : if (!show_objs)
2104 0 : return;
2105 :
2106 55 : auto_vec<const T *> vec_objs (map.elements ());
2107 55 : for (typename consolidation_map<T>::iterator iter = map.begin ();
2108 158 : iter != map.end (); ++iter)
2109 48 : vec_objs.quick_push ((*iter).second);
2110 :
2111 103 : vec_objs.qsort (T::cmp_ptr_ptr);
2112 :
2113 : unsigned i;
2114 : const T *obj;
2115 125 : FOR_EACH_VEC_ELT (vec_objs, i, obj)
2116 48 : log_managed_object<T> (logger, obj);
2117 55 : }
2118 :
2119 : /* Dump the number of objects of each class that were managed by this
2120 : manager to LOGGER.
2121 : If SHOW_OBJS is true, also dump the objects themselves. */
2122 :
2123 : void
2124 5 : region_model_manager::log_stats (logger *logger, bool show_objs) const
2125 : {
2126 5 : LOG_SCOPE (logger);
2127 5 : logger->log ("call string consolidation");
2128 5 : m_empty_call_string.recursive_log (logger);
2129 5 : logger->log ("next symbol id: %i", m_next_symbol_id);
2130 5 : logger->log ("svalue consolidation");
2131 5 : log_uniq_map (logger, show_objs, "constant_svalue", m_constants_map);
2132 5 : log_uniq_map (logger, show_objs, "unknown_svalue", m_unknowns_map);
2133 5 : if (m_unknown_NULL)
2134 3 : log_managed_object (logger, m_unknown_NULL);
2135 5 : log_uniq_map (logger, show_objs, "poisoned_svalue", m_poisoned_values_map);
2136 5 : log_uniq_map (logger, show_objs, "setjmp_svalue", m_setjmp_values_map);
2137 5 : log_uniq_map (logger, show_objs, "initial_svalue", m_initial_values_map);
2138 5 : log_uniq_map (logger, show_objs, "region_svalue", m_pointer_values_map);
2139 5 : log_uniq_map (logger, show_objs, "unaryop_svalue", m_unaryop_values_map);
2140 5 : log_uniq_map (logger, show_objs, "binop_svalue", m_binop_values_map);
2141 5 : log_uniq_map (logger, show_objs, "sub_svalue", m_sub_values_map);
2142 5 : log_uniq_map (logger, show_objs, "repeated_svalue", m_repeated_values_map);
2143 5 : log_uniq_map (logger, show_objs, "bits_within_svalue",
2144 5 : m_bits_within_values_map);
2145 5 : log_uniq_map (logger, show_objs, "unmergeable_svalue",
2146 5 : m_unmergeable_values_map);
2147 5 : log_uniq_map (logger, show_objs, "widening_svalue", m_widening_values_map);
2148 5 : log_uniq_map (logger, show_objs, "compound_svalue", m_compound_values_map);
2149 5 : log_uniq_map (logger, show_objs, "conjured_svalue", m_conjured_values_map);
2150 5 : log_uniq_map (logger, show_objs, "asm_output_svalue",
2151 5 : m_asm_output_values_map);
2152 5 : log_uniq_map (logger, show_objs, "const_fn_result_svalue",
2153 5 : m_const_fn_result_values_map);
2154 :
2155 5 : logger->log ("max accepted svalue num_nodes: %i",
2156 5 : m_max_complexity.m_num_nodes);
2157 5 : logger->log ("max accepted svalue max_depth: %i",
2158 5 : m_max_complexity.m_max_depth);
2159 :
2160 5 : logger->log ("region consolidation");
2161 5 : log_uniq_map (logger, show_objs, "function_region", m_fndecls_map);
2162 5 : log_uniq_map (logger, show_objs, "label_region", m_labels_map);
2163 5 : log_uniq_map (logger, show_objs, "decl_region for globals", m_globals_map);
2164 5 : log_uniq_map (logger, show_objs, "field_region", m_field_regions);
2165 5 : log_uniq_map (logger, show_objs, "element_region", m_element_regions);
2166 5 : log_uniq_map (logger, show_objs, "offset_region", m_offset_regions);
2167 5 : log_uniq_map (logger, show_objs, "sized_region", m_sized_regions);
2168 5 : log_uniq_map (logger, show_objs, "cast_region", m_cast_regions);
2169 5 : log_uniq_map (logger, show_objs, "frame_region", m_frame_regions);
2170 5 : log_uniq_map (logger, show_objs, "symbolic_region", m_symbolic_regions);
2171 5 : log_uniq_map (logger, show_objs, "string_region", m_string_map);
2172 5 : log_uniq_map (logger, show_objs, "bit_range_region", m_bit_range_regions);
2173 5 : log_uniq_map (logger, show_objs, "var_arg_region", m_var_arg_regions);
2174 5 : logger->log (" # managed dynamic regions: %i",
2175 : m_managed_dynamic_regions.length ());
2176 5 : m_store_mgr.log_stats (logger, show_objs);
2177 5 : m_range_mgr->log_stats (logger, show_objs);
2178 5 : }
2179 :
2180 : /* Dump the number of objects of each class that were managed by this
2181 : manager to LOGGER.
2182 : If SHOW_OBJS is true, also dump the objects themselves.
2183 : This is here so it can use log_uniq_map. */
2184 :
2185 : void
2186 5 : store_manager::log_stats (logger *logger, bool show_objs) const
2187 : {
2188 5 : LOG_SCOPE (logger);
2189 5 : log_uniq_map (logger, show_objs, "concrete_binding",
2190 5 : m_concrete_binding_key_mgr);
2191 5 : log_uniq_map (logger, show_objs, "symbolic_binding",
2192 5 : m_symbolic_binding_key_mgr);
2193 5 : }
2194 :
2195 : /* Emit a warning showing DECL_REG->tracked_p () for use in DejaGnu tests
2196 : (using -fdump-analyzer-untracked). */
2197 :
2198 : static void
2199 162 : dump_untracked_region (const decl_region *decl_reg)
2200 : {
2201 162 : tree decl = decl_reg->get_decl ();
2202 162 : if (TREE_CODE (decl) != VAR_DECL)
2203 : return;
2204 : /* For now, don't emit the status of decls in the constant pool, to avoid
2205 : differences in DejaGnu test results between targets that use these vs
2206 : those that don't.
2207 : (Eventually these decls should probably be untracked and we should test
2208 : for that, but that's not stage 4 material). */
2209 56 : if (DECL_IN_CONSTANT_POOL (decl))
2210 : return;
2211 85 : warning_at (DECL_SOURCE_LOCATION (decl), 0,
2212 : "track %qD: %s",
2213 56 : decl, (decl_reg->tracked_p () ? "yes" : "no"));
2214 : }
2215 :
2216 : /* Implementation of -fdump-analyzer-untracked. */
2217 :
2218 : void
2219 23 : region_model_manager::dump_untracked_regions () const
2220 : {
2221 74 : for (auto iter : m_globals_map)
2222 : {
2223 51 : const decl_region *decl_reg = iter.second;
2224 51 : dump_untracked_region (decl_reg);
2225 : }
2226 75 : for (auto frame_iter : m_frame_regions)
2227 : {
2228 52 : const frame_region *frame_reg = frame_iter.second;
2229 52 : frame_reg->dump_untracked_regions ();
2230 : }
2231 23 : }
2232 :
2233 : void
2234 52 : frame_region::dump_untracked_regions () const
2235 : {
2236 163 : for (auto iter : m_locals)
2237 : {
2238 111 : const decl_region *decl_reg = iter.second;
2239 111 : dump_untracked_region (decl_reg);
2240 : }
2241 52 : }
2242 :
2243 : } // namespace ana
2244 :
2245 : #endif /* #if ENABLE_ANALYZER */
|