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