Branch data Line data Source code
1 : : /* Symbolic values.
2 : : Copyright (C) 2019-2025 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 : : #ifndef GCC_ANALYZER_SVALUE_H
22 : : #define GCC_ANALYZER_SVALUE_H
23 : :
24 : : #include "analyzer/symbol.h"
25 : : #include "analyzer/store.h"
26 : : #include "analyzer/program-point.h"
27 : : #include "text-art/widget.h"
28 : :
29 : : using namespace ana;
30 : : using text_art::dump_widget_info;
31 : :
32 : : namespace ana {
33 : :
34 : : /* An enum for discriminating between the different concrete subclasses
35 : : of svalue. */
36 : :
37 : : enum svalue_kind
38 : : {
39 : : SK_REGION,
40 : : SK_CONSTANT,
41 : : SK_UNKNOWN,
42 : : SK_POISONED,
43 : : SK_SETJMP,
44 : : SK_INITIAL,
45 : : SK_UNARYOP,
46 : : SK_BINOP,
47 : : SK_SUB,
48 : : SK_REPEATED,
49 : : SK_BITS_WITHIN,
50 : : SK_UNMERGEABLE,
51 : : SK_PLACEHOLDER,
52 : : SK_WIDENING,
53 : : SK_COMPOUND,
54 : : SK_CONJURED,
55 : : SK_ASM_OUTPUT,
56 : : SK_CONST_FN_RESULT
57 : : };
58 : :
59 : : /* svalue and its subclasses.
60 : :
61 : : The class hierarchy looks like this (using indentation to show
62 : : inheritance, and with svalue_kinds shown for the concrete subclasses):
63 : :
64 : : svalue
65 : : region_svalue (SK_REGION): a pointer to a region
66 : : constant_svalue (SK_CONSTANT): a constant
67 : : unknown_svalue (SK_UNKNOWN): an unknowable value
68 : : poisoned_svalue (SK_POISONED): a unusable value (undefined)
69 : : setjmp_svalue (SK_SETJMP): a setjmp/longjmp buffer
70 : : initial_svalue (SK_INITIAL): the initial value of a region
71 : : unaryop_svalue (SK_UNARYOP): unary operation on another svalue
72 : : binop_svalue (SK_BINOP): binary operation on two svalues
73 : : sub_svalue (SK_SUB): the result of accessing a subregion
74 : : repeated_svalue (SK_REPEATED): repeating an svalue to fill a larger region
75 : : bits_within_svalue (SK_BITS_WITHIN): a range of bits/bytes within a larger
76 : : svalue
77 : : unmergeable_svalue (SK_UNMERGEABLE): a value that is so interesting
78 : : from a control-flow perspective that it can inhibit state-merging
79 : : placeholder_svalue (SK_PLACEHOLDER): for use in selftests.
80 : : widening_svalue (SK_WIDENING): a merger of two svalues (possibly
81 : : in an iteration).
82 : : compound_svalue (SK_COMPOUND): a mapping of bit-ranges to svalues
83 : : conjured_svalue (SK_CONJURED): a value arising from a stmt
84 : : asm_output_svalue (SK_ASM_OUTPUT): an output from a deterministic
85 : : asm stmt.
86 : : const_fn_result_svalue (SK_CONST_FN_RESULT): the return value from
87 : : a function with __attribute((const)) for given inputs. */
88 : :
89 : : /* An abstract base class representing a value held by a region of memory. */
90 : :
91 : : class svalue : public symbol
92 : : {
93 : : public:
94 : 28 : virtual ~svalue () {}
95 : :
96 : 37529578 : tree get_type () const { return m_type; }
97 : :
98 : : virtual enum svalue_kind get_kind () const = 0;
99 : :
100 : : void print (const region_model &model,
101 : : pretty_printer *pp) const;
102 : :
103 : : virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
104 : : void dump () const;
105 : : void dump (bool simple) const;
106 : : label_text get_desc (bool simple=true) const;
107 : :
108 : : std::unique_ptr<json::value> to_json () const;
109 : :
110 : : std::unique_ptr<text_art::tree_widget>
111 : : make_dump_widget (const dump_widget_info &dwi,
112 : : const char *prefix = nullptr) const;
113 : :
114 : : virtual const region_svalue *
115 : 9550083 : dyn_cast_region_svalue () const { return NULL; }
116 : : virtual const constant_svalue *
117 : 8556867 : dyn_cast_constant_svalue () const { return NULL; }
118 : : virtual const poisoned_svalue *
119 : 1662870 : dyn_cast_poisoned_svalue () const { return NULL; }
120 : : virtual const setjmp_svalue *
121 : 38 : dyn_cast_setjmp_svalue () const { return NULL; }
122 : : virtual const initial_svalue *
123 : 2535682 : dyn_cast_initial_svalue () const { return NULL; }
124 : : virtual const unaryop_svalue *
125 : 9301614 : dyn_cast_unaryop_svalue () const { return NULL; }
126 : : virtual const binop_svalue *
127 : 873740 : dyn_cast_binop_svalue () const { return NULL; }
128 : : virtual const sub_svalue *
129 : 2225426 : dyn_cast_sub_svalue () const { return NULL; }
130 : : virtual const repeated_svalue *
131 : 14009 : dyn_cast_repeated_svalue () const { return NULL; }
132 : : virtual const bits_within_svalue *
133 : 0 : dyn_cast_bits_within_svalue () const { return NULL; }
134 : : virtual const unmergeable_svalue *
135 : 15209234 : dyn_cast_unmergeable_svalue () const { return NULL; }
136 : : virtual const widening_svalue *
137 : 406244 : dyn_cast_widening_svalue () const { return NULL; }
138 : : virtual const compound_svalue *
139 : 9234167 : dyn_cast_compound_svalue () const { return NULL; }
140 : : virtual const conjured_svalue *
141 : 0 : dyn_cast_conjured_svalue () const { return NULL; }
142 : : virtual const asm_output_svalue *
143 : 0 : dyn_cast_asm_output_svalue () const { return NULL; }
144 : : virtual const const_fn_result_svalue *
145 : 0 : dyn_cast_const_fn_result_svalue () const { return NULL; }
146 : :
147 : : tree maybe_get_constant () const;
148 : : const region *maybe_get_region () const;
149 : : const svalue *maybe_undo_cast () const;
150 : : const svalue *unwrap_any_unmergeable () const;
151 : :
152 : : const svalue *can_merge_p (const svalue *other,
153 : : region_model_manager *mgr,
154 : : model_merger *merger) const;
155 : :
156 : : virtual void accept (visitor *v) const = 0;
157 : :
158 : : bool live_p (const svalue_set *live_svalues,
159 : : const region_model *model) const;
160 : : virtual bool implicitly_live_p (const svalue_set *live_svalues,
161 : : const region_model *model) const;
162 : :
163 : : static int cmp_ptr (const svalue *, const svalue *);
164 : : static int cmp_ptr_ptr (const void *, const void *);
165 : :
166 : : bool involves_p (const svalue *other) const;
167 : :
168 : : const svalue *
169 : : extract_bit_range (tree type,
170 : : const bit_range &subrange,
171 : : region_model_manager *mgr) const;
172 : :
173 : : virtual const svalue *
174 : : maybe_fold_bits_within (tree type,
175 : : const bit_range &subrange,
176 : : region_model_manager *mgr) const;
177 : :
178 : : virtual bool all_zeroes_p () const;
179 : :
180 : : /* Can this svalue be involved in constraints and sm-state?
181 : : Most can, but UNKNOWN and POISONED svalues are singletons
182 : : per-type and thus it's meaningless for them to "have state". */
183 : 2194257 : virtual bool can_have_associated_state_p () const { return true; }
184 : :
185 : : const region *maybe_get_deref_base_region () const;
186 : :
187 : : bool maybe_print_for_user (pretty_printer *pp,
188 : : const region_model &model,
189 : : const svalue *outer_sval = nullptr) const;
190 : :
191 : : tree maybe_get_type_from_typeinfo () const;
192 : :
193 : : protected:
194 : 200287 : svalue (complexity c, symbol::id_t id, tree type)
195 : 88426 : : symbol (c, id), m_type (type)
196 : : {}
197 : :
198 : : void print_svalue_node_label (pretty_printer *pp) const;
199 : :
200 : : private:
201 : : virtual void
202 : : print_dump_widget_label (pretty_printer *pp) const = 0;
203 : : virtual void
204 : : add_dump_widget_children (text_art::tree_widget &,
205 : : const dump_widget_info &dwi) const = 0;
206 : :
207 : : tree m_type;
208 : : };
209 : :
210 : : /* Concrete subclass of svalue representing a pointer value that points to
211 : : a known region */
212 : :
213 : : class region_svalue : public svalue
214 : : {
215 : : public:
216 : : /* A support class for uniquifying instances of region_svalue. */
217 : : struct key_t
218 : : {
219 : 966828 : key_t (tree type, const region *reg)
220 : 966828 : : m_type (type), m_reg (reg)
221 : : {}
222 : :
223 : 4984744 : hashval_t hash () const
224 : : {
225 : 4984744 : inchash::hash hstate;
226 : 4984744 : hstate.add_ptr (m_type);
227 : 4984744 : hstate.add_ptr (m_reg);
228 : 4984744 : return hstate.end ();
229 : : }
230 : :
231 : 4735237 : bool operator== (const key_t &other) const
232 : : {
233 : 4735237 : return (m_type == other.m_type && m_reg == other.m_reg);
234 : : }
235 : :
236 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
237 : 95714 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
238 : 5302325 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
239 : 17753651 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
240 : :
241 : : tree m_type;
242 : : const region *m_reg;
243 : : };
244 : :
245 : 25104 : region_svalue (symbol::id_t id, tree type, const region *reg)
246 : 25104 : : svalue (complexity (reg), id, type),
247 : 25104 : m_reg (reg)
248 : : {
249 : 25104 : gcc_assert (m_reg != NULL);
250 : 25104 : }
251 : :
252 : 12113480 : enum svalue_kind get_kind () const final override { return SK_REGION; }
253 : : const region_svalue *
254 : 2275281 : dyn_cast_region_svalue () const final override { return this; }
255 : :
256 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
257 : :
258 : : void
259 : : print_dump_widget_label (pretty_printer *pp) const final override;
260 : : void
261 : : add_dump_widget_children (text_art::tree_widget &w,
262 : : const dump_widget_info &dwi) const final override;
263 : :
264 : : void accept (visitor *v) const final override;
265 : : bool implicitly_live_p (const svalue_set *,
266 : : const region_model *) const final override;
267 : :
268 : 4425149 : const region * get_pointee () const { return m_reg; }
269 : :
270 : : static tristate eval_condition (const region_svalue *lhs_ptr,
271 : : enum tree_code op,
272 : : const region_svalue *rhs_ptr);
273 : :
274 : : private:
275 : : const region *m_reg;
276 : : };
277 : :
278 : : } // namespace ana
279 : :
280 : : template <>
281 : : template <>
282 : : inline bool
283 : 56985 : is_a_helper <const region_svalue *>::test (const svalue *sval)
284 : : {
285 : 56985 : return sval->get_kind () == SK_REGION;
286 : : }
287 : :
288 : : template <> struct default_hash_traits<region_svalue::key_t>
289 : : : public member_function_hash_traits<region_svalue::key_t>
290 : : {
291 : : static const bool empty_zero_p = false;
292 : : };
293 : :
294 : : namespace ana {
295 : :
296 : : /* Concrete subclass of svalue representing a specific constant value.
297 : : The type will either be the same as that of the underlying tree constant,
298 : : or NULL_TREE indicating the constant is intended to be "typeless". */
299 : :
300 : : class constant_svalue : public svalue
301 : : {
302 : : public:
303 : : /* A support class for uniquifying instances of region_svalue. */
304 : : struct key_t
305 : : {
306 : 2174784 : key_t (tree type, tree cst)
307 : 2174784 : : m_type (type), m_cst (cst)
308 : : {}
309 : :
310 : 13732417 : hashval_t hash () const
311 : : {
312 : 13732417 : inchash::hash hstate;
313 : 13732417 : hstate.add_ptr (m_type);
314 : 13732417 : hstate.add_ptr (m_cst);
315 : 13732417 : return hstate.end ();
316 : : }
317 : :
318 : 13780244 : bool operator== (const key_t &other) const
319 : : {
320 : 13780244 : return (m_type == other.m_type && m_cst == other.m_cst);
321 : : }
322 : :
323 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
324 : 168641 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
325 : 14445397 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
326 : 42327747 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
327 : :
328 : : tree m_type;
329 : : tree m_cst;
330 : : };
331 : :
332 : 54010 : constant_svalue (symbol::id_t id, tree type, tree cst_expr)
333 : 54010 : : svalue (complexity (1, 1), id, type),
334 : 54010 : m_cst_expr (cst_expr)
335 : : {
336 : 54010 : gcc_assert (cst_expr);
337 : 54010 : gcc_assert (CONSTANT_CLASS_P (cst_expr));
338 : 54010 : gcc_assert (type == TREE_TYPE (cst_expr) || type == NULL_TREE);
339 : 54010 : }
340 : :
341 : 22922630 : enum svalue_kind get_kind () const final override { return SK_CONSTANT; }
342 : : const constant_svalue *
343 : 3646439 : dyn_cast_constant_svalue () const final override { return this; }
344 : :
345 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
346 : :
347 : : void
348 : : print_dump_widget_label (pretty_printer *pp) const final override;
349 : : void
350 : : add_dump_widget_children (text_art::tree_widget &w,
351 : : const dump_widget_info &dwi) const final override;
352 : :
353 : : void accept (visitor *v) const final override;
354 : : bool implicitly_live_p (const svalue_set *,
355 : : const region_model *) const final override;
356 : :
357 : 4958249 : tree get_constant () const { return m_cst_expr; }
358 : : static tristate eval_condition (const constant_svalue *lhs,
359 : : enum tree_code op,
360 : : const constant_svalue *rhs);
361 : :
362 : : const svalue *
363 : : maybe_fold_bits_within (tree type,
364 : : const bit_range &subrange,
365 : : region_model_manager *mgr) const final override;
366 : :
367 : : bool all_zeroes_p () const final override;
368 : :
369 : : private:
370 : : tree m_cst_expr;
371 : : };
372 : :
373 : : } // namespace ana
374 : :
375 : : template <>
376 : : template <>
377 : : inline bool
378 : 1901 : is_a_helper <const constant_svalue *>::test (const svalue *sval)
379 : : {
380 : 1901 : return sval->get_kind () == SK_CONSTANT;
381 : : }
382 : :
383 : : template <> struct default_hash_traits<constant_svalue::key_t>
384 : : : public member_function_hash_traits<constant_svalue::key_t>
385 : : {
386 : : static const bool empty_zero_p = false;
387 : : };
388 : :
389 : : namespace ana {
390 : :
391 : : /* Concrete subclass of svalue representing an unknowable value, the bottom
392 : : value when thinking of svalues as a lattice.
393 : : This is a singleton (w.r.t. its manager): there is a single unknown_svalue
394 : : per type. Self-comparisons of such instances yield "unknown". */
395 : :
396 : : class unknown_svalue : public svalue
397 : : {
398 : : public:
399 : 10419 : unknown_svalue (symbol::id_t id, tree type)
400 : 10419 : : svalue (complexity (1, 1), id, type)
401 : : {}
402 : :
403 : 4002909 : enum svalue_kind get_kind () const final override { return SK_UNKNOWN; }
404 : :
405 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
406 : :
407 : : void
408 : : print_dump_widget_label (pretty_printer *pp) const final override;
409 : : void
410 : : add_dump_widget_children (text_art::tree_widget &w,
411 : : const dump_widget_info &dwi) const final override;
412 : :
413 : : void accept (visitor *v) const final override;
414 : :
415 : : const svalue *
416 : : maybe_fold_bits_within (tree type,
417 : : const bit_range &subrange,
418 : : region_model_manager *mgr) const final override;
419 : :
420 : : /* Unknown values are singletons per-type, so can't have state. */
421 : 109345 : bool can_have_associated_state_p () const final override { return false; }
422 : : };
423 : :
424 : : /* An enum describing a particular kind of "poisoned" value. */
425 : :
426 : : enum class poison_kind
427 : : {
428 : : /* For use to describe uninitialized memory. */
429 : : uninit,
430 : :
431 : : /* For use to describe freed memory. */
432 : : freed,
433 : :
434 : : /* For use to describe deleted memory. */
435 : : deleted,
436 : :
437 : : /* For use on pointers to regions within popped stack frames. */
438 : : popped_stack
439 : : };
440 : :
441 : : extern const char *poison_kind_to_str (enum poison_kind);
442 : :
443 : : /* Concrete subclass of svalue representing a value that should not
444 : : be used (e.g. uninitialized memory, freed memory). */
445 : :
446 : : class poisoned_svalue : public svalue
447 : : {
448 : : public:
449 : : /* A support class for uniquifying instances of poisoned_svalue. */
450 : : struct key_t
451 : : {
452 : 233553 : key_t (enum poison_kind kind, tree type)
453 : 233553 : : m_kind (kind), m_type (type)
454 : : {}
455 : :
456 : 891240 : hashval_t hash () const
457 : : {
458 : 891240 : inchash::hash hstate;
459 : 891240 : hstate.add_int (static_cast<int> (m_kind));
460 : 891240 : hstate.add_ptr (m_type);
461 : 891240 : return hstate.end ();
462 : : }
463 : :
464 : 704804 : bool operator== (const key_t &other) const
465 : : {
466 : 704804 : return (m_kind == other.m_kind && m_type == other.m_type);
467 : : }
468 : :
469 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
470 : 50815 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
471 : 926584 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
472 : 3938919 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
473 : :
474 : : enum poison_kind m_kind;
475 : : tree m_type;
476 : : };
477 : :
478 : 5195 : poisoned_svalue (enum poison_kind kind, symbol::id_t id, tree type)
479 : 5195 : : svalue (complexity (1, 1), id, type), m_kind (kind) {}
480 : :
481 : 285792 : enum svalue_kind get_kind () const final override { return SK_POISONED; }
482 : : const poisoned_svalue *
483 : 4777 : dyn_cast_poisoned_svalue () const final override { return this; }
484 : :
485 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
486 : :
487 : : void
488 : : print_dump_widget_label (pretty_printer *pp) const final override;
489 : : void
490 : : add_dump_widget_children (text_art::tree_widget &w,
491 : : const dump_widget_info &dwi) const final override;
492 : :
493 : : void accept (visitor *v) const final override;
494 : :
495 : : const svalue *
496 : : maybe_fold_bits_within (tree type,
497 : : const bit_range &subrange,
498 : : region_model_manager *mgr) const final override;
499 : :
500 : 4794 : enum poison_kind get_poison_kind () const { return m_kind; }
501 : :
502 : : /* Poisoned svalues are singletons per-type, so can't have state. */
503 : 16999 : bool can_have_associated_state_p () const final override { return false; }
504 : :
505 : : private:
506 : : enum poison_kind m_kind;
507 : : };
508 : :
509 : : } // namespace ana
510 : :
511 : : template <>
512 : : template <>
513 : : inline bool
514 : 9 : is_a_helper <const poisoned_svalue *>::test (const svalue *sval)
515 : : {
516 : 9 : return sval->get_kind () == SK_POISONED;
517 : : }
518 : :
519 : : template <> struct default_hash_traits<poisoned_svalue::key_t>
520 : : : public member_function_hash_traits<poisoned_svalue::key_t>
521 : : {
522 : : static const bool empty_zero_p = false;
523 : : };
524 : :
525 : : namespace ana {
526 : :
527 : : /* A bundle of information recording a setjmp/sigsetjmp call, corresponding
528 : : roughly to a jmp_buf. */
529 : :
530 : : struct setjmp_record
531 : : {
532 : 34 : setjmp_record (const exploded_node *enode,
533 : : const gcall &setjmp_call)
534 : 34 : : m_enode (enode), m_setjmp_call (&setjmp_call)
535 : : {
536 : : }
537 : :
538 : 20 : bool operator== (const setjmp_record &other) const
539 : : {
540 : 20 : return (m_enode == other.m_enode
541 : 0 : && m_setjmp_call == other.m_setjmp_call);
542 : : }
543 : :
544 : 84 : void add_to_hash (inchash::hash *hstate) const
545 : : {
546 : 84 : hstate->add_ptr (m_enode);
547 : 84 : hstate->add_ptr (m_setjmp_call);
548 : 84 : }
549 : :
550 : : static int cmp (const setjmp_record &rec1, const setjmp_record &rec2);
551 : :
552 : : const exploded_node *m_enode;
553 : : const gcall *m_setjmp_call;
554 : : // non-null, but we can't use a reference since we're putting these in a hash_map
555 : : };
556 : :
557 : : /* Concrete subclass of svalue representing buffers for setjmp/sigsetjmp,
558 : : so that longjmp/siglongjmp can potentially "return" to an entirely
559 : : different function. */
560 : :
561 : : class setjmp_svalue : public svalue
562 : : {
563 : : public:
564 : : /* A support class for uniquifying instances of poisoned_svalue. */
565 : : struct key_t
566 : : {
567 : 34 : key_t (const setjmp_record &record, tree type)
568 : 34 : : m_record (record), m_type (type)
569 : : {}
570 : :
571 : 84 : hashval_t hash () const
572 : : {
573 : 84 : inchash::hash hstate;
574 : 84 : m_record.add_to_hash (&hstate);
575 : 84 : hstate.add_ptr (m_type);
576 : 84 : return hstate.end ();
577 : : }
578 : :
579 : 20 : bool operator== (const key_t &other) const
580 : : {
581 : 688 : return (m_record == other.m_record && m_type == other.m_type);
582 : : }
583 : :
584 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
585 : 50505 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
586 : 88 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
587 : 102012 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
588 : :
589 : : setjmp_record m_record;
590 : : tree m_type;
591 : : };
592 : :
593 : 34 : setjmp_svalue (const setjmp_record &setjmp_record,
594 : : symbol::id_t id,
595 : : tree type)
596 : 34 : : svalue (complexity (1, 1), id, type), m_setjmp_record (setjmp_record)
597 : : {}
598 : :
599 : 1715 : enum svalue_kind get_kind () const final override { return SK_SETJMP; }
600 : : const setjmp_svalue *
601 : 25 : dyn_cast_setjmp_svalue () const final override { return this; }
602 : :
603 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
604 : :
605 : : void
606 : : print_dump_widget_label (pretty_printer *pp) const final override;
607 : : void
608 : : add_dump_widget_children (text_art::tree_widget &w,
609 : : const dump_widget_info &dwi) const final override;
610 : :
611 : : void accept (visitor *v) const final override;
612 : :
613 : : int get_enode_index () const;
614 : :
615 : 0 : const setjmp_record &get_setjmp_record () const { return m_setjmp_record; }
616 : :
617 : : private:
618 : : setjmp_record m_setjmp_record;
619 : : };
620 : :
621 : : } // namespace ana
622 : :
623 : : template <>
624 : : template <>
625 : : inline bool
626 : : is_a_helper <const setjmp_svalue *>::test (const svalue *sval)
627 : : {
628 : : return sval->get_kind () == SK_SETJMP;
629 : : }
630 : :
631 : : template <> struct default_hash_traits<setjmp_svalue::key_t>
632 : : : public member_function_hash_traits<setjmp_svalue::key_t>
633 : : {
634 : : static const bool empty_zero_p = false;
635 : : };
636 : :
637 : : namespace ana {
638 : :
639 : : /* Concrete subclass of svalue representing the initial value of a
640 : : specific region.
641 : :
642 : : This represents the initial value at the start of the analysis path,
643 : : as opposed to the first time the region is accessed during the path.
644 : : Hence as soon as we have a call to an unknown function, all previously
645 : : unmodelled globals become implicitly "unknown" rathen than "initial". */
646 : :
647 : : class initial_svalue : public svalue
648 : : {
649 : : public:
650 : 25167 : initial_svalue (symbol::id_t id, tree type, const region *reg)
651 : 25167 : : svalue (complexity (reg), id, type), m_reg (reg)
652 : : {
653 : 25167 : gcc_assert (m_reg != NULL);
654 : 25167 : }
655 : :
656 : 22785517 : enum svalue_kind get_kind () const final override { return SK_INITIAL; }
657 : : const initial_svalue *
658 : 331822 : dyn_cast_initial_svalue () const final override { return this; }
659 : :
660 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
661 : :
662 : : void
663 : : print_dump_widget_label (pretty_printer *pp) const final override;
664 : : void
665 : : add_dump_widget_children (text_art::tree_widget &w,
666 : : const dump_widget_info &dwi) const final override;
667 : :
668 : : void accept (visitor *v) const final override;
669 : : bool implicitly_live_p (const svalue_set *,
670 : : const region_model *) const final override;
671 : :
672 : : bool initial_value_of_param_p () const;
673 : :
674 : 4470236 : const region *get_region () const { return m_reg; }
675 : :
676 : : private:
677 : : const region *m_reg;
678 : : };
679 : :
680 : : } // namespace ana
681 : :
682 : : template <>
683 : : template <>
684 : : inline bool
685 : 1358052 : is_a_helper <const initial_svalue *>::test (const svalue *sval)
686 : : {
687 : 1358052 : return sval->get_kind () == SK_INITIAL;
688 : : }
689 : :
690 : : namespace ana {
691 : :
692 : : /* Concrete subclass of svalue representing a unary operation on
693 : : another svalues (e.g. a cast). */
694 : :
695 : : class unaryop_svalue : public svalue
696 : : {
697 : : public:
698 : : /* A support class for uniquifying instances of unaryop_svalue. */
699 : : struct key_t
700 : : {
701 : 61962 : key_t (tree type, enum tree_code op, const svalue *arg)
702 : 61962 : : m_type (type), m_op (op), m_arg (arg)
703 : : {}
704 : :
705 : 364040 : hashval_t hash () const
706 : : {
707 : 364040 : inchash::hash hstate;
708 : 364040 : hstate.add_ptr (m_type);
709 : 364040 : hstate.add_int (m_op);
710 : 364040 : hstate.add_ptr (m_arg);
711 : 364040 : return hstate.end ();
712 : : }
713 : :
714 : 353985 : bool operator== (const key_t &other) const
715 : : {
716 : 353985 : return (m_type == other.m_type
717 : 161585 : && m_op == other.m_op
718 : 513729 : && m_arg == other.m_arg);
719 : : }
720 : :
721 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
722 : 65220 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
723 : 403182 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
724 : 1435520 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
725 : :
726 : : tree m_type;
727 : : enum tree_code m_op;
728 : : const svalue *m_arg;
729 : : };
730 : :
731 : 8680 : unaryop_svalue (symbol::id_t id, tree type, enum tree_code op,
732 : : const svalue *arg)
733 : 8680 : : svalue (complexity (arg), id, type), m_op (op), m_arg (arg)
734 : : {
735 : 8680 : gcc_assert (arg->can_have_associated_state_p ());
736 : 8680 : }
737 : :
738 : 2024374 : enum svalue_kind get_kind () const final override { return SK_UNARYOP; }
739 : : const unaryop_svalue *
740 : 153839 : dyn_cast_unaryop_svalue () const final override { return this; }
741 : :
742 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
743 : :
744 : : void
745 : : print_dump_widget_label (pretty_printer *pp) const final override;
746 : : void
747 : : add_dump_widget_children (text_art::tree_widget &w,
748 : : const dump_widget_info &dwi) const final override;
749 : :
750 : : void accept (visitor *v) const final override;
751 : : bool implicitly_live_p (const svalue_set *,
752 : : const region_model *) const final override;
753 : :
754 : 365834 : enum tree_code get_op () const { return m_op; }
755 : 465716 : const svalue *get_arg () const { return m_arg; }
756 : :
757 : : const svalue *
758 : : maybe_fold_bits_within (tree type,
759 : : const bit_range &subrange,
760 : : region_model_manager *mgr) const final override;
761 : :
762 : : private:
763 : : enum tree_code m_op;
764 : : const svalue *m_arg;
765 : : };
766 : :
767 : : } // namespace ana
768 : :
769 : : template <>
770 : : template <>
771 : : inline bool
772 : 230310 : is_a_helper <const unaryop_svalue *>::test (const svalue *sval)
773 : : {
774 : 230310 : return sval->get_kind () == SK_UNARYOP;
775 : : }
776 : :
777 : : template <> struct default_hash_traits<unaryop_svalue::key_t>
778 : : : public member_function_hash_traits<unaryop_svalue::key_t>
779 : : {
780 : : static const bool empty_zero_p = false;
781 : : };
782 : :
783 : : namespace ana {
784 : :
785 : : /* Concrete subclass of svalue representing a binary operation of
786 : : two svalues. */
787 : :
788 : : class binop_svalue : public svalue
789 : : {
790 : : public:
791 : : /* A support class for uniquifying instances of binop_svalue. */
792 : : struct key_t
793 : : {
794 : 91147 : key_t (tree type, enum tree_code op,
795 : : const svalue *arg0, const svalue *arg1)
796 : 91147 : : m_type (type), m_op (op), m_arg0 (arg0), m_arg1 (arg1)
797 : : {}
798 : :
799 : 659420 : hashval_t hash () const
800 : : {
801 : 659420 : inchash::hash hstate;
802 : 659420 : hstate.add_ptr (m_type);
803 : 659420 : hstate.add_int (m_op);
804 : 659420 : hstate.add_ptr (m_arg0);
805 : 659420 : hstate.add_ptr (m_arg1);
806 : 659420 : return hstate.end ();
807 : : }
808 : :
809 : 654264 : bool operator== (const key_t &other) const
810 : : {
811 : 654264 : return (m_type == other.m_type
812 : 291679 : && m_op == other.m_op
813 : 215312 : && m_arg0 == other.m_arg0
814 : 742954 : && m_arg1 == other.m_arg1);
815 : : }
816 : :
817 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
818 : 107051 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
819 : 739290 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
820 : 2418402 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
821 : :
822 : : tree m_type;
823 : : enum tree_code m_op;
824 : : const svalue *m_arg0;
825 : : const svalue *m_arg1;
826 : : };
827 : :
828 : 21388 : binop_svalue (symbol::id_t id, tree type, enum tree_code op,
829 : : const svalue *arg0, const svalue *arg1)
830 : 21388 : : svalue (complexity::from_pair (arg0->get_complexity (),
831 : : arg1->get_complexity ()),
832 : : id,
833 : : type),
834 : 21388 : m_op (op), m_arg0 (arg0), m_arg1 (arg1)
835 : : {
836 : 21388 : gcc_assert (arg0->can_have_associated_state_p ());
837 : 21388 : gcc_assert (arg1->can_have_associated_state_p ());
838 : 21388 : }
839 : :
840 : 10268563 : enum svalue_kind get_kind () const final override { return SK_BINOP; }
841 : 112729 : const binop_svalue *dyn_cast_binop_svalue () const final override
842 : : {
843 : 112729 : return this;
844 : : }
845 : :
846 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
847 : :
848 : : void
849 : : print_dump_widget_label (pretty_printer *pp) const final override;
850 : : void
851 : : add_dump_widget_children (text_art::tree_widget &w,
852 : : const dump_widget_info &dwi) const final override;
853 : :
854 : : void accept (visitor *v) const final override;
855 : : bool implicitly_live_p (const svalue_set *,
856 : : const region_model *) const final override;
857 : :
858 : 2078395 : enum tree_code get_op () const { return m_op; }
859 : 1982523 : const svalue *get_arg0 () const { return m_arg0; }
860 : 1783604 : const svalue *get_arg1 () const { return m_arg1; }
861 : :
862 : : private:
863 : : enum tree_code m_op;
864 : : const svalue *m_arg0;
865 : : const svalue *m_arg1;
866 : : };
867 : :
868 : : } // namespace ana
869 : :
870 : : template <>
871 : : template <>
872 : : inline bool
873 : 190862 : is_a_helper <const binop_svalue *>::test (const svalue *sval)
874 : : {
875 : 190862 : return sval->get_kind () == SK_BINOP;
876 : : }
877 : :
878 : : template <> struct default_hash_traits<binop_svalue::key_t>
879 : : : public member_function_hash_traits<binop_svalue::key_t>
880 : : {
881 : : static const bool empty_zero_p = false;
882 : : };
883 : :
884 : : namespace ana {
885 : :
886 : : /* Concrete subclass of svalue representing the result of accessing a subregion
887 : : of another svalue (the value of a component/field of a struct, or an element
888 : : from an array). */
889 : :
890 : : class sub_svalue : public svalue
891 : : {
892 : : public:
893 : : /* A support class for uniquifying instances of sub_svalue. */
894 : : struct key_t
895 : : {
896 : 14013 : key_t (tree type, const svalue *parent_svalue, const region *subregion)
897 : 14013 : : m_type (type), m_parent_svalue (parent_svalue), m_subregion (subregion)
898 : : {}
899 : :
900 : 85784 : hashval_t hash () const
901 : : {
902 : 85784 : inchash::hash hstate;
903 : 85784 : hstate.add_ptr (m_type);
904 : 85784 : hstate.add_ptr (m_parent_svalue);
905 : 85784 : hstate.add_ptr (m_subregion);
906 : 85784 : return hstate.end ();
907 : : }
908 : :
909 : 85956 : bool operator== (const key_t &other) const
910 : : {
911 : 85956 : return (m_type == other.m_type
912 : 41028 : && m_parent_svalue == other.m_parent_svalue
913 : 104467 : && m_subregion == other.m_subregion);
914 : : }
915 : :
916 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
917 : 53963 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
918 : 97485 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
919 : 419657 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
920 : :
921 : : tree m_type;
922 : : const svalue *m_parent_svalue;
923 : : const region *m_subregion;
924 : : };
925 : : sub_svalue (symbol::id_t id, tree type, const svalue *parent_svalue,
926 : : const region *subregion);
927 : :
928 : 146120 : enum svalue_kind get_kind () const final override { return SK_SUB; }
929 : 11265 : const sub_svalue *dyn_cast_sub_svalue () const final override
930 : : {
931 : 11265 : return this;
932 : : }
933 : :
934 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
935 : :
936 : : void
937 : : print_dump_widget_label (pretty_printer *pp) const final override;
938 : : void
939 : : add_dump_widget_children (text_art::tree_widget &w,
940 : : const dump_widget_info &dwi) const final override;
941 : :
942 : : void accept (visitor *v) const final override;
943 : : bool implicitly_live_p (const svalue_set *,
944 : : const region_model *) const final override;
945 : :
946 : 78307 : const svalue *get_parent () const { return m_parent_svalue; }
947 : 17473 : const region *get_subregion () const { return m_subregion; }
948 : :
949 : : private:
950 : : const svalue *m_parent_svalue;
951 : : const region *m_subregion;
952 : : };
953 : :
954 : : } // namespace ana
955 : :
956 : : template <>
957 : : template <>
958 : : inline bool
959 : 0 : is_a_helper <const sub_svalue *>::test (const svalue *sval)
960 : : {
961 : 0 : return sval->get_kind () == SK_SUB;
962 : : }
963 : :
964 : : template <> struct default_hash_traits<sub_svalue::key_t>
965 : : : public member_function_hash_traits<sub_svalue::key_t>
966 : : {
967 : : static const bool empty_zero_p = false;
968 : : };
969 : :
970 : : namespace ana {
971 : :
972 : : /* Concrete subclass of svalue representing repeating an inner svalue
973 : : (possibly not a whole number of times) to fill a larger region of
974 : : type TYPE of size OUTER_SIZE bytes. */
975 : :
976 : : class repeated_svalue : public svalue
977 : : {
978 : : public:
979 : : /* A support class for uniquifying instances of repeated_svalue. */
980 : : struct key_t
981 : : {
982 : 2057 : key_t (tree type,
983 : : const svalue *outer_size,
984 : : const svalue *inner_svalue)
985 : 2057 : : m_type (type), m_outer_size (outer_size), m_inner_svalue (inner_svalue)
986 : : {}
987 : :
988 : 10460 : hashval_t hash () const
989 : : {
990 : 10460 : inchash::hash hstate;
991 : 10460 : hstate.add_ptr (m_type);
992 : 10460 : hstate.add_ptr (m_outer_size);
993 : 10460 : hstate.add_ptr (m_inner_svalue);
994 : 10460 : return hstate.end ();
995 : : }
996 : :
997 : 9223 : bool operator== (const key_t &other) const
998 : : {
999 : 9223 : return (m_type == other.m_type
1000 : 9089 : && m_outer_size == other.m_outer_size
1001 : 10837 : && m_inner_svalue == other.m_inner_svalue);
1002 : : }
1003 : :
1004 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
1005 : 51001 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
1006 : 11151 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
1007 : 145520 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
1008 : :
1009 : : tree m_type;
1010 : : const svalue *m_outer_size;
1011 : : const svalue *m_inner_svalue;
1012 : : };
1013 : : repeated_svalue (symbol::id_t id,
1014 : : tree type,
1015 : : const svalue *outer_size,
1016 : : const svalue *inner_svalue);
1017 : :
1018 : 93742 : enum svalue_kind get_kind () const final override { return SK_REPEATED; }
1019 : 104 : const repeated_svalue *dyn_cast_repeated_svalue () const final override
1020 : : {
1021 : 104 : return this;
1022 : : }
1023 : :
1024 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1025 : :
1026 : : void
1027 : : print_dump_widget_label (pretty_printer *pp) const final override;
1028 : : void
1029 : : add_dump_widget_children (text_art::tree_widget &w,
1030 : : const dump_widget_info &dwi) const final override;
1031 : :
1032 : : void accept (visitor *v) const final override;
1033 : :
1034 : 34 : const svalue *get_outer_size () const { return m_outer_size; }
1035 : 611 : const svalue *get_inner_svalue () const { return m_inner_svalue; }
1036 : :
1037 : : bool all_zeroes_p () const final override;
1038 : :
1039 : : const svalue *
1040 : : maybe_fold_bits_within (tree type,
1041 : : const bit_range &subrange,
1042 : : region_model_manager *mgr) const final override;
1043 : :
1044 : : private:
1045 : : const svalue *m_outer_size;
1046 : : const svalue *m_inner_svalue;
1047 : : };
1048 : :
1049 : : } // namespace ana
1050 : :
1051 : : template <>
1052 : : template <>
1053 : : inline bool
1054 : 34 : is_a_helper <const repeated_svalue *>::test (const svalue *sval)
1055 : : {
1056 : 34 : return sval->get_kind () == SK_REPEATED;
1057 : : }
1058 : :
1059 : : template <> struct default_hash_traits<repeated_svalue::key_t>
1060 : : : public member_function_hash_traits<repeated_svalue::key_t>
1061 : : {
1062 : : static const bool empty_zero_p = false;
1063 : : };
1064 : :
1065 : : namespace ana {
1066 : :
1067 : : /* A range of bits/bytes within another svalue
1068 : : e.g. bytes 5-39 of INITIAL_SVALUE(R).
1069 : : These can be generated for prefixes and suffixes when part of a binding
1070 : : is clobbered, so that we don't lose too much information. */
1071 : :
1072 : : class bits_within_svalue : public svalue
1073 : : {
1074 : : public:
1075 : : /* A support class for uniquifying instances of bits_within_svalue. */
1076 : : struct key_t
1077 : : {
1078 : 1252 : key_t (tree type,
1079 : : const bit_range &bits,
1080 : : const svalue *inner_svalue)
1081 : 1252 : : m_type (type), m_bits (bits), m_inner_svalue (inner_svalue)
1082 : : {}
1083 : :
1084 : 7568 : hashval_t hash () const
1085 : : {
1086 : 7568 : inchash::hash hstate;
1087 : 7568 : hstate.add_ptr (m_type);
1088 : 7568 : hstate.add_ptr (m_inner_svalue);
1089 : 7568 : return hstate.end ();
1090 : : }
1091 : :
1092 : 7339 : bool operator== (const key_t &other) const
1093 : : {
1094 : 7339 : return (m_type == other.m_type
1095 : 6497 : && m_bits == other.m_bits
1096 : 8848 : && m_inner_svalue == other.m_inner_svalue);
1097 : : }
1098 : :
1099 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
1100 : 51347 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
1101 : 10955 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
1102 : 141371 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
1103 : :
1104 : : tree m_type;
1105 : : bit_range m_bits;
1106 : : const svalue *m_inner_svalue;
1107 : : };
1108 : : bits_within_svalue (symbol::id_t id,
1109 : : tree type,
1110 : : const bit_range &bits,
1111 : : const svalue *inner_svalue);
1112 : :
1113 : 38191 : enum svalue_kind get_kind () const final override { return SK_BITS_WITHIN; }
1114 : : const bits_within_svalue *
1115 : 0 : dyn_cast_bits_within_svalue () const final override
1116 : : {
1117 : 0 : return this;
1118 : : }
1119 : :
1120 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1121 : :
1122 : : void
1123 : : print_dump_widget_label (pretty_printer *pp) const final override;
1124 : : void
1125 : : add_dump_widget_children (text_art::tree_widget &w,
1126 : : const dump_widget_info &dwi) const final override;
1127 : :
1128 : : void accept (visitor *v) const final override;
1129 : : bool implicitly_live_p (const svalue_set *,
1130 : : const region_model *) const final override;
1131 : :
1132 : 1196 : const bit_range &get_bits () const { return m_bits; }
1133 : 48 : const svalue *get_inner_svalue () const { return m_inner_svalue; }
1134 : :
1135 : : const svalue *
1136 : : maybe_fold_bits_within (tree type,
1137 : : const bit_range &subrange,
1138 : : region_model_manager *mgr) const final override;
1139 : :
1140 : : private:
1141 : : const bit_range m_bits;
1142 : : const svalue *m_inner_svalue;
1143 : : };
1144 : :
1145 : : } // namespace ana
1146 : :
1147 : : template <>
1148 : : template <>
1149 : : inline bool
1150 : 0 : is_a_helper <const bits_within_svalue *>::test (const svalue *sval)
1151 : : {
1152 : 0 : return sval->get_kind () == SK_BITS_WITHIN;
1153 : : }
1154 : :
1155 : : template <> struct default_hash_traits<bits_within_svalue::key_t>
1156 : : : public member_function_hash_traits<bits_within_svalue::key_t>
1157 : : {
1158 : : static const bool empty_zero_p = false;
1159 : : };
1160 : :
1161 : : namespace ana {
1162 : :
1163 : : /* Concrete subclass of svalue: decorate another svalue,
1164 : : so that the resulting svalue can be identified as being
1165 : : "interesting to control flow".
1166 : : For example, consider the return value from setjmp. We
1167 : : don't want to merge states in which the result is 0 with
1168 : : those in which the result is non-zero. By using an
1169 : : unmergeable_svalue for the result, we can inhibit such merges
1170 : : and have separate exploded nodes for those states, keeping
1171 : : the first and second returns from setjmp distinct in the exploded
1172 : : graph. */
1173 : :
1174 : : class unmergeable_svalue : public svalue
1175 : : {
1176 : : public:
1177 : 202 : unmergeable_svalue (symbol::id_t id, const svalue *arg)
1178 : 202 : : svalue (complexity (arg), id, arg->get_type ()), m_arg (arg)
1179 : : {
1180 : 202 : }
1181 : :
1182 : 20253 : enum svalue_kind get_kind () const final override { return SK_UNMERGEABLE; }
1183 : : const unmergeable_svalue *
1184 : 4547 : dyn_cast_unmergeable_svalue () const final override { return this; }
1185 : :
1186 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1187 : :
1188 : : void
1189 : : print_dump_widget_label (pretty_printer *pp) const final override;
1190 : : void
1191 : : add_dump_widget_children (text_art::tree_widget &w,
1192 : : const dump_widget_info &dwi) const final override;
1193 : :
1194 : : void accept (visitor *v) const final override;
1195 : : bool implicitly_live_p (const svalue_set *,
1196 : : const region_model *) const final override;
1197 : :
1198 : 5498 : const svalue *get_arg () const { return m_arg; }
1199 : :
1200 : : private:
1201 : : const svalue *m_arg;
1202 : : };
1203 : :
1204 : : } // namespace ana
1205 : :
1206 : : template <>
1207 : : template <>
1208 : : inline bool
1209 : 0 : is_a_helper <const unmergeable_svalue *>::test (const svalue *sval)
1210 : : {
1211 : 0 : return sval->get_kind () == SK_UNMERGEABLE;
1212 : : }
1213 : :
1214 : : namespace ana {
1215 : :
1216 : : /* Concrete subclass of svalue for use in selftests, where
1217 : : we want a specific but unknown svalue.
1218 : : Unlike other svalue subclasses these aren't managed by
1219 : : region_model_manager. */
1220 : :
1221 : 28 : class placeholder_svalue : public svalue
1222 : : {
1223 : : public:
1224 : 14463 : placeholder_svalue (symbol::id_t id, tree type, const char *name)
1225 : 14463 : : svalue (complexity (1, 1), id, type), m_name (name)
1226 : : {
1227 : : }
1228 : :
1229 : 34311 : enum svalue_kind get_kind () const final override { return SK_PLACEHOLDER; }
1230 : :
1231 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1232 : :
1233 : : void
1234 : : print_dump_widget_label (pretty_printer *pp) const final override;
1235 : : void
1236 : : add_dump_widget_children (text_art::tree_widget &w,
1237 : : const dump_widget_info &dwi) const final override;
1238 : :
1239 : : void accept (visitor *v) const final override;
1240 : :
1241 : 0 : const char *get_name () const { return m_name; }
1242 : :
1243 : : private:
1244 : : const char *m_name;
1245 : : };
1246 : :
1247 : : } // namespace ana
1248 : :
1249 : : template <>
1250 : : template <>
1251 : : inline bool
1252 : : is_a_helper <const placeholder_svalue *>::test (const svalue *sval)
1253 : : {
1254 : : return sval->get_kind () == SK_PLACEHOLDER;
1255 : : }
1256 : :
1257 : : namespace ana {
1258 : :
1259 : : /* Concrete subclass of svalue representing a "widening" seen when merging
1260 : : states, widening from a base value to {base value, iter value} and thus
1261 : : representing a possible fixed point in an iteration from the base to
1262 : : +ve infinity, or -ve infinity, and thus useful for representing a value
1263 : : within a loop.
1264 : : We also need to capture the program_point at which the merger happens,
1265 : : so that distinguish between different iterators, and thus handle
1266 : : nested loops. (currently we capture the function_point instead, for
1267 : : simplicity of hashing). */
1268 : :
1269 : : class widening_svalue : public svalue
1270 : : {
1271 : : public:
1272 : : /* A support class for uniquifying instances of widening_svalue. */
1273 : : struct key_t
1274 : : {
1275 : 4938 : key_t (tree type, const function_point &point,
1276 : : const svalue *base_sval, const svalue *iter_sval)
1277 : 4938 : : m_type (type), m_point (point),
1278 : 4938 : m_base_sval (base_sval), m_iter_sval (iter_sval)
1279 : : {}
1280 : :
1281 : 30559 : hashval_t hash () const
1282 : : {
1283 : 30559 : inchash::hash hstate;
1284 : 30559 : hstate.add_ptr (m_base_sval);
1285 : 30559 : hstate.add_ptr (m_iter_sval);
1286 : 30559 : return hstate.end ();
1287 : : }
1288 : :
1289 : 35922 : bool operator== (const key_t &other) const
1290 : : {
1291 : 35922 : return (m_type == other.m_type
1292 : 22059 : && m_point == other.m_point
1293 : 3442 : && m_base_sval == other.m_base_sval
1294 : 38551 : && m_iter_sval == other.m_iter_sval);
1295 : : }
1296 : :
1297 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
1298 : 52666 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
1299 : 53646 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
1300 : 275863 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
1301 : :
1302 : : tree m_type;
1303 : : function_point m_point;
1304 : : const svalue *m_base_sval;
1305 : : const svalue *m_iter_sval;
1306 : : };
1307 : :
1308 : : enum direction_t
1309 : : {
1310 : : DIR_ASCENDING,
1311 : : DIR_DESCENDING,
1312 : : DIR_UNKNOWN
1313 : : };
1314 : :
1315 : 2482 : widening_svalue (symbol::id_t id, tree type, const function_point &point,
1316 : : const svalue *base_sval, const svalue *iter_sval)
1317 : 2482 : : svalue (complexity::from_pair (base_sval->get_complexity (),
1318 : : iter_sval->get_complexity ()),
1319 : : id,
1320 : : type),
1321 : 2482 : m_point (point),
1322 : 2482 : m_base_sval (base_sval), m_iter_sval (iter_sval)
1323 : : {
1324 : 2482 : gcc_assert (base_sval->can_have_associated_state_p ());
1325 : 2482 : gcc_assert (iter_sval->can_have_associated_state_p ());
1326 : 2482 : }
1327 : :
1328 : 926081 : enum svalue_kind get_kind () const final override { return SK_WIDENING; }
1329 : 32206 : const widening_svalue *dyn_cast_widening_svalue () const final override
1330 : : {
1331 : 32206 : return this;
1332 : : }
1333 : :
1334 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1335 : :
1336 : : void
1337 : : print_dump_widget_label (pretty_printer *pp) const final override;
1338 : : void
1339 : : add_dump_widget_children (text_art::tree_widget &w,
1340 : : const dump_widget_info &dwi) const final override;
1341 : :
1342 : : void accept (visitor *v) const final override;
1343 : :
1344 : 4557 : const function_point &get_point () const { return m_point; }
1345 : 27660 : const svalue *get_base_svalue () const { return m_base_sval; }
1346 : 6639 : const svalue *get_iter_svalue () const { return m_iter_sval; }
1347 : :
1348 : : enum direction_t get_direction () const;
1349 : :
1350 : : tristate eval_condition_without_cm (enum tree_code op,
1351 : : tree rhs_cst) const;
1352 : :
1353 : : private:
1354 : : function_point m_point;
1355 : : const svalue *m_base_sval;
1356 : : const svalue *m_iter_sval;
1357 : : };
1358 : :
1359 : : } // namespace ana
1360 : :
1361 : : template <>
1362 : : template <>
1363 : : inline bool
1364 : 485 : is_a_helper <const widening_svalue *>::test (const svalue *sval)
1365 : : {
1366 : 485 : return sval->get_kind () == SK_WIDENING;
1367 : : }
1368 : :
1369 : : template <> struct default_hash_traits<widening_svalue::key_t>
1370 : : : public member_function_hash_traits<widening_svalue::key_t>
1371 : : {
1372 : : static const bool empty_zero_p = false;
1373 : : };
1374 : :
1375 : : namespace ana {
1376 : :
1377 : : /* Concrete subclass of svalue representing a mapping of bit-ranges
1378 : : to svalues, analogous to a cluster within the store.
1379 : :
1380 : : This is for use in places where we want to represent a store-like
1381 : : mapping, but are required to use an svalue, such as when handling
1382 : : compound assignments and compound return values.
1383 : :
1384 : : All keys within the underlying binding_map are required to be concrete,
1385 : : not symbolic.
1386 : :
1387 : : Instances of this class shouldn't be bound as-is into the store;
1388 : : instead they should be unpacked. Similarly, they should not be
1389 : : nested. */
1390 : :
1391 : : class compound_svalue : public svalue
1392 : : {
1393 : : public:
1394 : : typedef binding_map::iterator_t iterator_t;
1395 : :
1396 : : /* A support class for uniquifying instances of compound_svalue.
1397 : : Note that to avoid copies, keys store pointers to binding_maps,
1398 : : rather than the maps themselves. */
1399 : : struct key_t
1400 : : {
1401 : 4877 : key_t (tree type, const binding_map *map_ptr)
1402 : 4224 : : m_type (type), m_map_ptr (map_ptr)
1403 : : {}
1404 : :
1405 : 20172 : hashval_t hash () const
1406 : : {
1407 : 20172 : inchash::hash hstate;
1408 : 20172 : hstate.add_ptr (m_type);
1409 : : //hstate.add_ptr (m_map_ptr); // TODO
1410 : 20172 : return hstate.end ();
1411 : : }
1412 : :
1413 : 23798 : bool operator== (const key_t &other) const
1414 : : {
1415 : 23798 : return (m_type == other.m_type
1416 : 23798 : && *m_map_ptr == *other.m_map_ptr);
1417 : : }
1418 : :
1419 : : void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
1420 : 50786 : void mark_empty () { m_type = reinterpret_cast<tree> (2); }
1421 : 35997 : bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
1422 : 213219 : bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
1423 : :
1424 : : tree m_type;
1425 : : const binding_map *m_map_ptr;
1426 : : };
1427 : :
1428 : : compound_svalue (symbol::id_t id, tree type, const binding_map &map);
1429 : :
1430 : 8673 : enum svalue_kind get_kind () const final override { return SK_COMPOUND; }
1431 : 5528 : const compound_svalue *dyn_cast_compound_svalue () const final override
1432 : : {
1433 : 5528 : return this;
1434 : : }
1435 : :
1436 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1437 : :
1438 : : void
1439 : : print_dump_widget_label (pretty_printer *pp) const final override;
1440 : : void
1441 : : add_dump_widget_children (text_art::tree_widget &w,
1442 : : const dump_widget_info &dwi) const final override;
1443 : :
1444 : : void accept (visitor *v) const final override;
1445 : :
1446 : 119 : const binding_map &get_map () const { return m_map; }
1447 : :
1448 : 6448 : iterator_t begin () const { return m_map.begin (); }
1449 : 24970 : iterator_t end () const { return m_map.end (); }
1450 : :
1451 : 653 : struct key_t make_key () const
1452 : : {
1453 : 653 : return key_t (get_type (), &m_map);
1454 : : }
1455 : :
1456 : : const svalue *
1457 : : maybe_fold_bits_within (tree type,
1458 : : const bit_range &subrange,
1459 : : region_model_manager *mgr) const final override;
1460 : :
1461 : : private:
1462 : : static complexity calc_complexity (const binding_map &map);
1463 : :
1464 : : binding_map m_map;
1465 : : };
1466 : :
1467 : : } // namespace ana
1468 : :
1469 : : template <>
1470 : : template <>
1471 : : inline bool
1472 : 329 : is_a_helper <const compound_svalue *>::test (const svalue *sval)
1473 : : {
1474 : 329 : return sval->get_kind () == SK_COMPOUND;
1475 : : }
1476 : :
1477 : : template <> struct default_hash_traits<compound_svalue::key_t>
1478 : : : public member_function_hash_traits<compound_svalue::key_t>
1479 : : {
1480 : : static const bool empty_zero_p = false;
1481 : : };
1482 : :
1483 : : namespace ana {
1484 : :
1485 : : /* A bundle of state for purging information from a program_state about
1486 : : a conjured_svalue. We pass this whenever calling
1487 : : get_or_create_conjured_svalue, so that if the program_state already
1488 : : has information about this conjured_svalue on an execution path, we
1489 : : can purge that information, to avoid the analyzer confusing the two
1490 : : values as being the same. */
1491 : :
1492 : : class conjured_purge
1493 : : {
1494 : : public:
1495 : 46920 : conjured_purge (region_model *model, region_model_context *ctxt)
1496 : 46780 : : m_model (model), m_ctxt (ctxt)
1497 : : {
1498 : : }
1499 : : void purge (const conjured_svalue *sval) const;
1500 : :
1501 : : private:
1502 : : region_model *m_model;
1503 : : region_model_context *m_ctxt;
1504 : : };
1505 : :
1506 : : /* A defined value arising from a statement, where we want to identify a
1507 : : particular unknown value, rather than resorting to the unknown_value
1508 : : singleton, so that the value can have sm-state.
1509 : :
1510 : : Comparisons of variables that share the same conjured_svalue are known
1511 : : to be equal, even if we don't know what the value is.
1512 : :
1513 : : For example, this is used for the values of regions that may have been
1514 : : touched when calling an unknown function.
1515 : :
1516 : : The value captures a region as well as a stmt in order to avoid falsely
1517 : : aliasing the various values that could arise in one statement. For
1518 : : example, after:
1519 : : unknown_fn (&a, &b);
1520 : : we want values to clobber a and b with, but we don't want to use the
1521 : : same value, or it would falsely implicitly assume that a == b. */
1522 : :
1523 : : class conjured_svalue : public svalue
1524 : : {
1525 : : public:
1526 : : /* A support class for uniquifying instances of conjured_svalue. */
1527 : : struct key_t
1528 : : {
1529 : 66875 : key_t (tree type, const gimple *stmt, const region *id_reg, unsigned idx)
1530 : 66875 : : m_type (type), m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
1531 : : {}
1532 : :
1533 : 579739 : hashval_t hash () const
1534 : : {
1535 : 579739 : inchash::hash hstate;
1536 : 579739 : hstate.add_ptr (m_type);
1537 : 579739 : hstate.add_ptr (m_stmt);
1538 : 579739 : hstate.add_ptr (m_id_reg);
1539 : 579739 : return hstate.end ();
1540 : : }
1541 : :
1542 : 588390 : bool operator== (const key_t &other) const
1543 : : {
1544 : 588390 : return (m_type == other.m_type
1545 : 237775 : && m_stmt == other.m_stmt
1546 : 62319 : && m_id_reg == other.m_id_reg
1547 : 636888 : && m_idx == other.m_idx);
1548 : : }
1549 : :
1550 : : /* Use m_stmt to mark empty/deleted, as m_type can be NULL for
1551 : : legitimate instances. */
1552 : : void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
1553 : 0 : void mark_empty () { m_stmt = NULL; }
1554 : 690450 : bool is_deleted () const
1555 : : {
1556 : 690450 : return m_stmt == reinterpret_cast<const gimple *> (1);
1557 : : }
1558 : 2220393 : bool is_empty () const { return m_stmt == NULL; }
1559 : :
1560 : : tree m_type;
1561 : : const gimple *m_stmt;
1562 : : const region *m_id_reg;
1563 : : unsigned m_idx;
1564 : : };
1565 : :
1566 : 28391 : conjured_svalue (symbol::id_t id, tree type, const gimple *stmt,
1567 : : const region *id_reg, unsigned idx)
1568 : 28391 : : svalue (complexity (id_reg), id, type),
1569 : 28391 : m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
1570 : : {
1571 : 28391 : gcc_assert (m_stmt != NULL);
1572 : 28391 : }
1573 : :
1574 : 6819681 : enum svalue_kind get_kind () const final override { return SK_CONJURED; }
1575 : 0 : const conjured_svalue *dyn_cast_conjured_svalue () const final override
1576 : : {
1577 : 0 : return this;
1578 : : }
1579 : :
1580 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1581 : :
1582 : : void
1583 : : print_dump_widget_label (pretty_printer *pp) const final override;
1584 : : void
1585 : : add_dump_widget_children (text_art::tree_widget &w,
1586 : : const dump_widget_info &dwi) const final override;
1587 : :
1588 : : void accept (visitor *v) const final override;
1589 : :
1590 : 189548 : const gimple *get_stmt () const { return m_stmt; }
1591 : 103812 : const region *get_id_region () const { return m_id_reg; }
1592 : : bool lhs_value_p () const;
1593 : :
1594 : : private:
1595 : : const gimple *m_stmt;
1596 : : const region *m_id_reg;
1597 : : unsigned m_idx;
1598 : : };
1599 : :
1600 : : } // namespace ana
1601 : :
1602 : : template <>
1603 : : template <>
1604 : : inline bool
1605 : : is_a_helper <const conjured_svalue *>::test (const svalue *sval)
1606 : : {
1607 : : return sval->get_kind () == SK_CONJURED;
1608 : : }
1609 : :
1610 : : template <> struct default_hash_traits<conjured_svalue::key_t>
1611 : : : public member_function_hash_traits<conjured_svalue::key_t>
1612 : : {
1613 : : static const bool empty_zero_p = true;
1614 : : };
1615 : :
1616 : : namespace ana {
1617 : :
1618 : : /* An output from a deterministic asm stmt, where we want to identify a
1619 : : particular unknown value, rather than resorting to the unknown_value
1620 : : singleton.
1621 : :
1622 : : Comparisons of variables that share the same asm_output_svalue are known
1623 : : to be equal, even if we don't know what the value is. */
1624 : :
1625 : : class asm_output_svalue : public svalue
1626 : : {
1627 : : public:
1628 : : /* Imposing an upper limit and using a (small) array allows key_t
1629 : : to avoid memory management. */
1630 : : static const unsigned MAX_INPUTS = 2;
1631 : :
1632 : : /* A support class for uniquifying instances of asm_output_svalue. */
1633 : : struct key_t
1634 : : {
1635 : 394 : key_t (tree type,
1636 : : const char *asm_string,
1637 : : unsigned output_idx,
1638 : : const vec<const svalue *> &inputs)
1639 : 394 : : m_type (type), m_asm_string (asm_string), m_output_idx (output_idx),
1640 : 394 : m_num_inputs (inputs.length ())
1641 : : {
1642 : 394 : gcc_assert (inputs.length () <= MAX_INPUTS);
1643 : 1066 : for (unsigned i = 0; i < m_num_inputs; i++)
1644 : 672 : m_input_arr[i] = inputs[i];
1645 : 394 : }
1646 : :
1647 : 1679 : hashval_t hash () const
1648 : : {
1649 : 1679 : inchash::hash hstate;
1650 : 1679 : hstate.add_ptr (m_type);
1651 : : /* We don't bother hashing m_asm_str. */
1652 : 1679 : hstate.add_int (m_output_idx);
1653 : 4612 : for (unsigned i = 0; i < m_num_inputs; i++)
1654 : 2933 : hstate.add_ptr (m_input_arr[i]);
1655 : 1679 : return hstate.end ();
1656 : : }
1657 : :
1658 : 1220 : bool operator== (const key_t &other) const
1659 : : {
1660 : 1220 : if (!(m_type == other.m_type
1661 : 914 : && 0 == (strcmp (m_asm_string, other.m_asm_string))
1662 : 841 : && m_output_idx == other.m_output_idx
1663 : 689 : && m_num_inputs == other.m_num_inputs))
1664 : : return false;
1665 : 1222 : for (unsigned i = 0; i < m_num_inputs; i++)
1666 : 1020 : if (m_input_arr[i] != other.m_input_arr[i])
1667 : : return false;
1668 : : return true;
1669 : : }
1670 : :
1671 : : /* Use m_asm_string to mark empty/deleted, as m_type can be NULL for
1672 : : legitimate instances. */
1673 : : void mark_deleted () { m_asm_string = reinterpret_cast<const char *> (1); }
1674 : 0 : void mark_empty () { m_asm_string = NULL; }
1675 : 1755 : bool is_deleted () const
1676 : : {
1677 : 1755 : return m_asm_string == reinterpret_cast<const char *> (1);
1678 : : }
1679 : 110218 : bool is_empty () const { return m_asm_string == NULL; }
1680 : :
1681 : : tree m_type;
1682 : : const char *m_asm_string;
1683 : : unsigned m_output_idx;
1684 : : unsigned m_num_inputs;
1685 : : const svalue *m_input_arr[MAX_INPUTS];
1686 : : };
1687 : :
1688 : 192 : asm_output_svalue (symbol::id_t id,
1689 : : tree type,
1690 : : const char *asm_string,
1691 : : unsigned output_idx,
1692 : : unsigned num_outputs,
1693 : : const vec<const svalue *> &inputs)
1694 : 192 : : svalue (complexity::from_vec_svalue (inputs), id, type),
1695 : 192 : m_asm_string (asm_string),
1696 : 192 : m_output_idx (output_idx),
1697 : 192 : m_num_outputs (num_outputs),
1698 : 192 : m_num_inputs (inputs.length ())
1699 : : {
1700 : 192 : gcc_assert (inputs.length () <= MAX_INPUTS);
1701 : 488 : for (unsigned i = 0; i < m_num_inputs; i++)
1702 : 296 : m_input_arr[i] = inputs[i];
1703 : 192 : }
1704 : :
1705 : 11295 : enum svalue_kind get_kind () const final override { return SK_ASM_OUTPUT; }
1706 : : const asm_output_svalue *
1707 : 0 : dyn_cast_asm_output_svalue () const final override
1708 : : {
1709 : 0 : return this;
1710 : : }
1711 : :
1712 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1713 : :
1714 : : void
1715 : : print_dump_widget_label (pretty_printer *pp) const final override;
1716 : : void
1717 : : add_dump_widget_children (text_art::tree_widget &w,
1718 : : const dump_widget_info &dwi) const final override;
1719 : :
1720 : : void accept (visitor *v) const final override;
1721 : :
1722 : 126 : const char *get_asm_string () const { return m_asm_string; }
1723 : 202 : unsigned get_output_idx () const { return m_output_idx; }
1724 : 102 : unsigned get_num_outputs () const { return m_num_outputs; }
1725 : 408 : unsigned get_num_inputs () const { return m_num_inputs; }
1726 : 212 : const svalue *get_input (unsigned idx) const { return m_input_arr[idx]; }
1727 : :
1728 : : private:
1729 : : void dump_input (pretty_printer *pp,
1730 : : unsigned input_idx,
1731 : : const svalue *sval,
1732 : : bool simple) const;
1733 : : unsigned input_idx_to_asm_idx (unsigned input_idx) const;
1734 : :
1735 : : const char *m_asm_string;
1736 : : unsigned m_output_idx;
1737 : :
1738 : : /* We capture this so that we can offset the input indices
1739 : : to match the %0, %1, %2 in the asm_string when dumping. */
1740 : : unsigned m_num_outputs;
1741 : :
1742 : : unsigned m_num_inputs;
1743 : : const svalue *m_input_arr[MAX_INPUTS];
1744 : : };
1745 : :
1746 : : } // namespace ana
1747 : :
1748 : : template <>
1749 : : template <>
1750 : : inline bool
1751 : 8 : is_a_helper <const asm_output_svalue *>::test (const svalue *sval)
1752 : : {
1753 : 8 : return sval->get_kind () == SK_ASM_OUTPUT;
1754 : : }
1755 : :
1756 : : template <> struct default_hash_traits<asm_output_svalue::key_t>
1757 : : : public member_function_hash_traits<asm_output_svalue::key_t>
1758 : : {
1759 : : static const bool empty_zero_p = true;
1760 : : };
1761 : :
1762 : : namespace ana {
1763 : :
1764 : : /* The return value from a function with __attribute((const)) for given
1765 : : inputs, provided that we don't have too many inputs, and all of them
1766 : : are deterministic.
1767 : :
1768 : : Comparisons of variables that share the same const_fn_result_svalue are known
1769 : : to be equal, even if we don't know what the value is. */
1770 : :
1771 : : class const_fn_result_svalue : public svalue
1772 : : {
1773 : : public:
1774 : : /* Imposing an upper limit and using a (small) array allows key_t
1775 : : to avoid memory management. */
1776 : : static const unsigned MAX_INPUTS = 2;
1777 : :
1778 : : /* A support class for uniquifying instances of const_fn_result_svalue. */
1779 : : struct key_t
1780 : : {
1781 : 1098 : key_t (tree type,
1782 : : tree fndecl,
1783 : : const vec<const svalue *> &inputs)
1784 : 1098 : : m_type (type), m_fndecl (fndecl),
1785 : 1098 : m_num_inputs (inputs.length ())
1786 : : {
1787 : 1098 : gcc_assert (inputs.length () <= MAX_INPUTS);
1788 : 1769 : for (unsigned i = 0; i < m_num_inputs; i++)
1789 : 671 : m_input_arr[i] = inputs[i];
1790 : 1098 : }
1791 : :
1792 : 3753 : hashval_t hash () const
1793 : : {
1794 : 3753 : inchash::hash hstate;
1795 : 3753 : hstate.add_ptr (m_type);
1796 : 3753 : hstate.add_ptr (m_fndecl);
1797 : 6988 : for (unsigned i = 0; i < m_num_inputs; i++)
1798 : 3235 : hstate.add_ptr (m_input_arr[i]);
1799 : 3753 : return hstate.end ();
1800 : : }
1801 : :
1802 : 2889 : bool operator== (const key_t &other) const
1803 : : {
1804 : 2889 : if (!(m_type == other.m_type
1805 : 2843 : && m_fndecl == other.m_fndecl
1806 : 1731 : && m_num_inputs == other.m_num_inputs))
1807 : : return false;
1808 : 2316 : for (unsigned i = 0; i < m_num_inputs; i++)
1809 : 1473 : if (m_input_arr[i] != other.m_input_arr[i])
1810 : : return false;
1811 : : return true;
1812 : : }
1813 : :
1814 : : /* Use m_fndecl to mark empty/deleted. */
1815 : : void mark_deleted () { m_fndecl = reinterpret_cast<tree> (1); }
1816 : 0 : void mark_empty () { m_fndecl = NULL; }
1817 : 4010 : bool is_deleted () const
1818 : : {
1819 : 4010 : return m_fndecl == reinterpret_cast<tree> (1);
1820 : : }
1821 : 122402 : bool is_empty () const { return m_fndecl == NULL; }
1822 : :
1823 : : tree m_type;
1824 : : tree m_fndecl;
1825 : : unsigned m_num_inputs;
1826 : : const svalue *m_input_arr[MAX_INPUTS];
1827 : : };
1828 : :
1829 : 255 : const_fn_result_svalue (symbol::id_t id,
1830 : : tree type,
1831 : : tree fndecl,
1832 : : const vec<const svalue *> &inputs)
1833 : 255 : : svalue (complexity::from_vec_svalue (inputs), id, type),
1834 : 255 : m_fndecl (fndecl),
1835 : 255 : m_num_inputs (inputs.length ())
1836 : : {
1837 : 255 : gcc_assert (inputs.length () <= MAX_INPUTS);
1838 : 510 : for (unsigned i = 0; i < m_num_inputs; i++)
1839 : 255 : m_input_arr[i] = inputs[i];
1840 : 255 : }
1841 : :
1842 : 50233 : enum svalue_kind get_kind () const final override
1843 : : {
1844 : 50233 : return SK_CONST_FN_RESULT;
1845 : : }
1846 : : const const_fn_result_svalue *
1847 : 0 : dyn_cast_const_fn_result_svalue () const final override
1848 : : {
1849 : 0 : return this;
1850 : : }
1851 : :
1852 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1853 : :
1854 : : void
1855 : : print_dump_widget_label (pretty_printer *pp) const final override;
1856 : : void
1857 : : add_dump_widget_children (text_art::tree_widget &w,
1858 : : const dump_widget_info &dwi) const final override;
1859 : :
1860 : : void accept (visitor *v) const final override;
1861 : :
1862 : 98 : tree get_fndecl () const { return m_fndecl; }
1863 : 114 : unsigned get_num_inputs () const { return m_num_inputs; }
1864 : 66 : const svalue *get_input (unsigned idx) const { return m_input_arr[idx]; }
1865 : :
1866 : : private:
1867 : : void dump_input (pretty_printer *pp,
1868 : : unsigned input_idx,
1869 : : const svalue *sval,
1870 : : bool simple) const;
1871 : :
1872 : : tree m_fndecl;
1873 : : unsigned m_num_inputs;
1874 : : const svalue *m_input_arr[MAX_INPUTS];
1875 : : };
1876 : :
1877 : : } // namespace ana
1878 : :
1879 : : template <>
1880 : : template <>
1881 : : inline bool
1882 : 2 : is_a_helper <const const_fn_result_svalue *>::test (const svalue *sval)
1883 : : {
1884 : 2 : return sval->get_kind () == SK_CONST_FN_RESULT;
1885 : : }
1886 : :
1887 : : template <> struct default_hash_traits<const_fn_result_svalue::key_t>
1888 : : : public member_function_hash_traits<const_fn_result_svalue::key_t>
1889 : : {
1890 : : static const bool empty_zero_p = true;
1891 : : };
1892 : :
1893 : : #endif /* GCC_ANALYZER_SVALUE_H */
|