Branch data Line data Source code
1 : : /* Regions of memory.
2 : : Copyright (C) 2019-2024 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_REGION_H
22 : : #define GCC_ANALYZER_REGION_H
23 : :
24 : : #include "analyzer/symbol.h"
25 : : #include "text-art/widget.h"
26 : :
27 : : namespace ana {
28 : :
29 : : /* An enum for identifying different spaces within memory. */
30 : :
31 : : enum memory_space
32 : : {
33 : : MEMSPACE_UNKNOWN,
34 : : MEMSPACE_CODE,
35 : : MEMSPACE_GLOBALS,
36 : : MEMSPACE_STACK,
37 : : MEMSPACE_HEAP,
38 : : MEMSPACE_READONLY_DATA,
39 : : MEMSPACE_THREAD_LOCAL,
40 : : MEMSPACE_PRIVATE
41 : : };
42 : :
43 : : /* An enum for discriminating between the different concrete subclasses
44 : : of region. */
45 : :
46 : : enum region_kind
47 : : {
48 : : RK_FRAME,
49 : : RK_GLOBALS,
50 : : RK_CODE,
51 : : RK_FUNCTION,
52 : : RK_LABEL,
53 : : RK_STACK,
54 : : RK_HEAP,
55 : : RK_THREAD_LOCAL,
56 : : RK_ROOT,
57 : : RK_SYMBOLIC,
58 : : RK_DECL,
59 : : RK_FIELD,
60 : : RK_ELEMENT,
61 : : RK_OFFSET,
62 : : RK_SIZED,
63 : : RK_CAST,
64 : : RK_HEAP_ALLOCATED,
65 : : RK_ALLOCA,
66 : : RK_STRING,
67 : : RK_BIT_RANGE,
68 : : RK_VAR_ARG,
69 : : RK_ERRNO,
70 : : RK_PRIVATE,
71 : : RK_UNKNOWN,
72 : : };
73 : :
74 : : /* Region and its subclasses.
75 : :
76 : : The class hierarchy looks like this (using indentation to show
77 : : inheritance, and with region_kinds shown for the concrete subclasses):
78 : :
79 : : region
80 : : space_region
81 : : frame_region (RK_FRAME): a function frame on the stack
82 : : globals_region (RK_GLOBALS): holds globals variables (data and bss)
83 : : code_region (RK_CODE): represents the code segment, containing functions
84 : : stack_region (RK_STACK): a stack, containing all stack frames
85 : : heap_region (RK_HEAP): the heap, containing heap_allocated_regions
86 : : thread_local_region (RK_THREAD_LOCAL): thread-local data for the thread
87 : : being analyzed
88 : : root_region (RK_ROOT): the top-level region
89 : : function_region (RK_FUNCTION): the code for a particular function
90 : : label_region (RK_LABEL): a particular label within a function
91 : : symbolic_region (RK_SYMBOLIC): dereferencing a symbolic pointer
92 : : decl_region (RK_DECL): the memory occupied by a particular global, local,
93 : : or SSA name
94 : : field_region (RK_FIELD): the memory occupied by a field within a struct
95 : : or union
96 : : element_region (RK_ELEMENT): an element within an array
97 : : offset_region (RK_OFFSET): a byte-offset within another region, for
98 : : handling pointer arithmetic as a region
99 : : sized_region (RK_SIZED): a subregion of symbolic size (in bytes)
100 : : within its parent
101 : : cast_region (RK_CAST): a region that views another region using a
102 : : different type
103 : : heap_allocated_region (RK_HEAP_ALLOCATED): an untyped region dynamically
104 : : allocated on the heap via
105 : : "malloc" or similar
106 : : alloca_region (RK_ALLOCA): an untyped region dynamically allocated on the
107 : : stack via "alloca"
108 : : string_region (RK_STRING): a region for a STRING_CST
109 : : bit_range_region (RK_BIT_RANGE): a region for a specific range of bits
110 : : within another region
111 : : var_arg_region (RK_VAR_ARG): a region for the N-th vararg within a
112 : : frame_region for a variadic call
113 : : errno_region (RK_ERRNO): a region for holding "errno"
114 : : private_region (RK_PRIVATE): a region for internal state of an API
115 : : unknown_region (RK_UNKNOWN): for handling unimplemented tree codes. */
116 : :
117 : : /* Abstract base class for representing ways of accessing chunks of memory.
118 : :
119 : : Regions form a tree-like hierarchy, with a root region at the base,
120 : : with memory space regions within it, representing the stack and
121 : : globals, with frames within the stack, and regions for variables
122 : : within the frames and the "globals" region. Regions for structs
123 : : can have subregions for fields. */
124 : :
125 : : class region : public symbol
126 : : {
127 : : public:
128 : : virtual ~region ();
129 : :
130 : : virtual enum region_kind get_kind () const = 0;
131 : : virtual const frame_region *
132 : 4000506 : dyn_cast_frame_region () const { return NULL; }
133 : : virtual const function_region *
134 : 32141 : dyn_cast_function_region () const { return NULL; }
135 : : virtual const symbolic_region *
136 : 11959411 : dyn_cast_symbolic_region () const { return NULL; }
137 : : virtual const decl_region *
138 : 1203698 : dyn_cast_decl_region () const { return NULL; }
139 : : virtual const field_region *
140 : 279 : dyn_cast_field_region () const { return NULL; }
141 : : virtual const element_region *
142 : 2515782 : dyn_cast_element_region () const { return NULL; }
143 : : virtual const offset_region *
144 : 2446769 : dyn_cast_offset_region () const { return NULL; }
145 : : virtual const sized_region *
146 : 0 : dyn_cast_sized_region () const { return NULL; }
147 : : virtual const cast_region *
148 : 5126369 : dyn_cast_cast_region () const { return NULL; }
149 : : virtual const string_region *
150 : 29260 : dyn_cast_string_region () const { return NULL; }
151 : : virtual const bit_range_region *
152 : 0 : dyn_cast_bit_range_region () const { return NULL; }
153 : : virtual const var_arg_region *
154 : 0 : dyn_cast_var_arg_region () const { return NULL; }
155 : :
156 : : virtual void accept (visitor *v) const;
157 : :
158 : 35789804 : const region *get_parent_region () const { return m_parent; }
159 : : const region *get_base_region () const;
160 : : bool base_region_p () const;
161 : : bool descendent_of_p (const region *elder) const;
162 : : const frame_region *maybe_get_frame_region () const;
163 : : enum memory_space get_memory_space () const;
164 : : bool can_have_initial_svalue_p () const;
165 : : const svalue *get_initial_value_at_main (region_model_manager *mgr) const;
166 : :
167 : : tree maybe_get_decl () const;
168 : :
169 : 16238092 : tree get_type () const { return m_type; }
170 : :
171 : : void print (const region_model &model,
172 : : pretty_printer *pp) const;
173 : : label_text get_desc (bool simple=true) const;
174 : :
175 : : virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
176 : : void dump (bool simple) const;
177 : : void dump () const;
178 : :
179 : : std::unique_ptr<json::value> to_json () const;
180 : :
181 : :
182 : : bool maybe_print_for_user (pretty_printer *pp,
183 : : const region_model &model) const;
184 : :
185 : : std::unique_ptr<text_art::tree_widget>
186 : : make_dump_widget (const text_art::dump_widget_info &dwi,
187 : : const char *prefix = nullptr) const;
188 : :
189 : : bool non_null_p () const;
190 : :
191 : : static int cmp_ptr_ptr (const void *, const void *);
192 : :
193 : : bool involves_p (const svalue *sval) const;
194 : :
195 : : region_offset get_offset (region_model_manager *mgr) const;
196 : : region_offset get_next_offset (region_model_manager *mgr) const;
197 : :
198 : : /* Attempt to get the size of this region as a concrete number of bytes.
199 : : If successful, return true and write the size to *OUT.
200 : : Otherwise return false.
201 : : This is the accessed size, not necessarily the size that's valid to
202 : : access. */
203 : : virtual bool get_byte_size (byte_size_t *out) const;
204 : :
205 : : /* Attempt to get the size of this region as a concrete number of bits.
206 : : If successful, return true and write the size to *OUT.
207 : : Otherwise return false.
208 : : This is the accessed size, not necessarily the size that's valid to
209 : : access. */
210 : : virtual bool get_bit_size (bit_size_t *out) const;
211 : :
212 : : /* Get a symbolic value describing the size of this region in bytes
213 : : (which could be "unknown").
214 : : This is the accessed size, not necessarily the size that's valid to
215 : : access. */
216 : : virtual const svalue *get_byte_size_sval (region_model_manager *mgr) const;
217 : :
218 : : /* Get a symbolic value describing the size of this region in bits
219 : : (which could be "unknown").
220 : : This is the accessed size, not necessarily the size that's valid to
221 : : access. */
222 : : virtual const svalue *get_bit_size_sval (region_model_manager *mgr) const;
223 : :
224 : : /* Attempt to get the offset in bits of this region relative to its parent.
225 : : If successful, return true and write to *OUT.
226 : : Otherwise return false. */
227 : : virtual bool get_relative_concrete_offset (bit_offset_t *out) const;
228 : :
229 : : /* Get the offset in bytes of this region relative to its parent as a svalue.
230 : : Might return an unknown_svalue. */
231 : : virtual const svalue *
232 : : get_relative_symbolic_offset (region_model_manager *mgr) const;
233 : :
234 : : /* Attempt to get the position and size of this region expressed as a
235 : : concrete range of bytes relative to its parent.
236 : : If successful, return true and write to *OUT.
237 : : Otherwise return false. */
238 : : bool get_relative_concrete_byte_range (byte_range *out) const;
239 : :
240 : : void
241 : : get_subregions_for_binding (region_model_manager *mgr,
242 : : bit_offset_t start_bit_offset,
243 : : bit_size_t size_in_bits,
244 : : tree type,
245 : : auto_vec <const region *> *out) const;
246 : :
247 : : bool symbolic_for_unknown_ptr_p () const;
248 : :
249 : : bool symbolic_p () const;
250 : :
251 : : /* For most base regions it makes sense to track the bindings of the region
252 : : within the store. As an optimization, some are not tracked (to avoid
253 : : bloating the store object with redundant binding clusters). */
254 : 525832 : virtual bool tracked_p () const { return true; }
255 : :
256 : : bool is_named_decl_p (const char *decl_name) const;
257 : :
258 : : bool empty_p () const;
259 : :
260 : : protected:
261 : : region (complexity c, symbol::id_t id, const region *parent, tree type);
262 : :
263 : : private:
264 : : region_offset calc_offset (region_model_manager *mgr) const;
265 : : const svalue *calc_initial_value_at_main (region_model_manager *mgr) const;
266 : :
267 : : virtual void
268 : : print_dump_widget_label (pretty_printer *pp) const = 0;
269 : : virtual void
270 : : add_dump_widget_children (text_art::tree_widget &,
271 : : const text_art::dump_widget_info &dwi) const;
272 : :
273 : : const region *m_parent;
274 : : tree m_type;
275 : :
276 : : mutable region_offset *m_cached_offset;
277 : :
278 : : /* For regions within a global decl, a cache of the svalue for the initial
279 : : value of this region when the program starts. */
280 : : mutable const svalue *m_cached_init_sval_at_main;
281 : : };
282 : :
283 : : } // namespace ana
284 : :
285 : : template <>
286 : : template <>
287 : : inline bool
288 : : is_a_helper <const region *>::test (const region *)
289 : : {
290 : : return true;
291 : : }
292 : :
293 : : namespace ana {
294 : :
295 : : /* Abstract subclass of region, for regions that represent an untyped
296 : : space within memory, such as the stack or the heap. */
297 : :
298 : 32231 : class space_region : public region
299 : : {
300 : : protected:
301 : 32231 : space_region (symbol::id_t id, const region *parent)
302 : 32231 : : region (complexity (parent), id, parent, NULL_TREE)
303 : 32231 : {}
304 : : };
305 : :
306 : : /* Concrete space_region subclass, representing a function frame on the stack,
307 : : to contain the locals.
308 : : The parent is the stack region; there's also a hierarchy of call-stack
309 : : prefixes expressed via m_calling_frame.
310 : : For example, given "oldest" calling "middle" called "newest" we would have
311 : : - a stack depth of 3
312 : : - frame (A) for "oldest" with index 0 for depth 1, calling_frame == NULL
313 : : - frame (B) for "middle" with index 1 for depth 2, calling_frame == (A)
314 : : - frame (C) for "newest" with index 2 for depth 3, calling_frame == (B)
315 : : where the parent region for each of the frames is the "stack" region.
316 : : The index is the count of frames earlier than this in the stack. */
317 : :
318 : : class frame_region : public space_region
319 : : {
320 : : public:
321 : : /* A support class for uniquifying instances of frame_region. */
322 : : struct key_t
323 : : {
324 : 32882 : key_t (const frame_region *calling_frame, const function &fun)
325 : 32882 : : m_calling_frame (calling_frame), m_fun (&fun)
326 : : {
327 : : /* calling_frame can be NULL. */
328 : : }
329 : :
330 : 211741 : hashval_t hash () const
331 : : {
332 : 211741 : inchash::hash hstate;
333 : 211741 : hstate.add_ptr (m_calling_frame);
334 : 211741 : hstate.add_ptr (m_fun);
335 : 211741 : return hstate.end ();
336 : : }
337 : :
338 : 189727 : bool operator== (const key_t &other) const
339 : : {
340 : 189727 : return (m_calling_frame == other.m_calling_frame
341 : 189727 : && m_fun == other.m_fun);
342 : : }
343 : :
344 : : void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
345 : 0 : void mark_empty () { m_fun = NULL; }
346 : 232036 : bool is_deleted () const
347 : : {
348 : 232036 : return m_fun == reinterpret_cast<function *> (1);
349 : : }
350 : 956901 : bool is_empty () const { return m_fun == NULL; }
351 : :
352 : : const frame_region *m_calling_frame;
353 : : const function *m_fun;
354 : : };
355 : :
356 : 13386 : frame_region (symbol::id_t id, const region *parent,
357 : : const frame_region *calling_frame,
358 : : const function &fun, int index)
359 : 26772 : : space_region (id, parent), m_calling_frame (calling_frame),
360 : 13386 : m_fun (fun), m_index (index)
361 : 13386 : {}
362 : : ~frame_region ();
363 : :
364 : : /* region vfuncs. */
365 : 12803589 : enum region_kind get_kind () const final override { return RK_FRAME; }
366 : 1587546 : const frame_region * dyn_cast_frame_region () const final override
367 : : {
368 : 1587546 : return this;
369 : : }
370 : : void accept (visitor *v) const final override;
371 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
372 : :
373 : : void print_dump_widget_label (pretty_printer *pp) const final override;
374 : :
375 : : /* Accessors. */
376 : 2223121 : const frame_region *get_calling_frame () const { return m_calling_frame; }
377 : 1406517 : const function &get_function () const { return m_fun; }
378 : 1006 : tree get_fndecl () const { return get_function ().decl; }
379 : 4562129 : int get_index () const { return m_index; }
380 : 5025344 : int get_stack_depth () const { return m_index + 1; }
381 : :
382 : : const decl_region *
383 : : get_region_for_local (region_model_manager *mgr,
384 : : tree expr,
385 : : const region_model_context *ctxt) const;
386 : :
387 : 2 : unsigned get_num_locals () const { return m_locals.elements (); }
388 : :
389 : : /* Implemented in region-model-manager.cc. */
390 : : void dump_untracked_regions () const;
391 : :
392 : : private:
393 : : const frame_region *m_calling_frame;
394 : : const function &m_fun;
395 : : int m_index;
396 : :
397 : : /* The regions for the decls within this frame are managed by this
398 : : object, rather than the region_model_manager, to make it a simple
399 : : lookup by tree. */
400 : : typedef hash_map<tree, decl_region *> map_t;
401 : : map_t m_locals;
402 : : };
403 : :
404 : : } // namespace ana
405 : :
406 : : template <>
407 : : template <>
408 : : inline bool
409 : 523 : is_a_helper <const frame_region *>::test (const region *reg)
410 : : {
411 : 523 : return reg->get_kind () == RK_FRAME;
412 : : }
413 : :
414 : : template <> struct default_hash_traits<frame_region::key_t>
415 : : : public member_function_hash_traits<frame_region::key_t>
416 : : {
417 : : static const bool empty_zero_p = true;
418 : : };
419 : :
420 : : namespace ana {
421 : :
422 : : /* Concrete space_region subclass, to hold global variables (data and bss). */
423 : :
424 : 3769 : class globals_region : public space_region
425 : : {
426 : : public:
427 : 3769 : globals_region (symbol::id_t id, const region *parent)
428 : 3769 : : space_region (id, parent)
429 : : {}
430 : :
431 : : /* region vfuncs. */
432 : 2870625 : enum region_kind get_kind () const final override { return RK_GLOBALS; }
433 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
434 : : void print_dump_widget_label (pretty_printer *pp) const final override;
435 : : };
436 : :
437 : : } // namespace ana
438 : :
439 : : template <>
440 : : template <>
441 : : inline bool
442 : : is_a_helper <const globals_region *>::test (const region *reg)
443 : : {
444 : : return reg->get_kind () == RK_GLOBALS;
445 : : }
446 : :
447 : : namespace ana {
448 : :
449 : : /* Concrete space_region subclass, representing the code segment
450 : : containing functions. */
451 : :
452 : 3769 : class code_region : public space_region
453 : : {
454 : : public:
455 : 3769 : code_region (symbol::id_t id, const region *parent)
456 : 3769 : : space_region (id, parent)
457 : : {}
458 : :
459 : : /* region vfuncs. */
460 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
461 : : void print_dump_widget_label (pretty_printer *pp) const final override;
462 : 27138 : enum region_kind get_kind () const final override { return RK_CODE; }
463 : : };
464 : :
465 : : } // namespace ana
466 : :
467 : : template <>
468 : : template <>
469 : : inline bool
470 : : is_a_helper <const code_region *>::test (const region *reg)
471 : : {
472 : : return reg->get_kind () == RK_CODE;
473 : : }
474 : :
475 : : namespace ana {
476 : :
477 : : /* Concrete region subclass. A region representing the code for
478 : : a particular function. */
479 : :
480 : : class function_region : public region
481 : : {
482 : : public:
483 : 8506 : function_region (symbol::id_t id, const code_region *parent, tree fndecl)
484 : 17012 : : region (complexity (parent), id, parent, TREE_TYPE (fndecl)),
485 : 8506 : m_fndecl (fndecl)
486 : : {
487 : 8506 : gcc_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndecl)));
488 : 8506 : }
489 : :
490 : : /* region vfuncs. */
491 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
492 : : void print_dump_widget_label (pretty_printer *pp) const final override;
493 : :
494 : 129384 : enum region_kind get_kind () const final override { return RK_FUNCTION; }
495 : : const function_region *
496 : 864745 : dyn_cast_function_region () const final override{ return this; }
497 : :
498 : 864668 : tree get_fndecl () const { return m_fndecl; }
499 : :
500 : : private:
501 : : tree m_fndecl;
502 : : };
503 : :
504 : : } // namespace ana
505 : :
506 : : template <>
507 : : template <>
508 : : inline bool
509 : 10 : is_a_helper <const function_region *>::test (const region *reg)
510 : : {
511 : 10 : return reg->get_kind () == RK_FUNCTION;
512 : : }
513 : :
514 : : namespace ana {
515 : :
516 : : /* Concrete region subclass. A region representing a particular label
517 : : within a function. */
518 : :
519 : : class label_region : public region
520 : : {
521 : : public:
522 : 46 : label_region (symbol::id_t id, const function_region *parent, tree label)
523 : 46 : : region (complexity (parent), id, parent, NULL_TREE), m_label (label)
524 : : {
525 : 46 : gcc_assert (TREE_CODE (label) == LABEL_DECL);
526 : 46 : }
527 : :
528 : : /* region vfuncs. */
529 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
530 : : void print_dump_widget_label (pretty_printer *pp) const final override;
531 : 24374 : enum region_kind get_kind () const final override { return RK_LABEL; }
532 : :
533 : 5 : tree get_label () const { return m_label; }
534 : :
535 : : private:
536 : : tree m_label;
537 : : };
538 : :
539 : : } // namespace ana
540 : :
541 : : template <>
542 : : template <>
543 : : inline bool
544 : 5 : is_a_helper <const label_region *>::test (const region *reg)
545 : : {
546 : 5 : return reg->get_kind () == RK_LABEL;
547 : : }
548 : :
549 : : namespace ana {
550 : :
551 : : /* Concrete space_region subclass representing a stack, containing all stack
552 : : frames. */
553 : :
554 : 3769 : class stack_region : public space_region
555 : : {
556 : : public:
557 : 3769 : stack_region (symbol::id_t id, region *parent)
558 : 3769 : : space_region (id, parent)
559 : : {}
560 : :
561 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
562 : : void print_dump_widget_label (pretty_printer *pp) const final override;
563 : :
564 : 568431 : enum region_kind get_kind () const final override { return RK_STACK; }
565 : : };
566 : :
567 : : } // namespace ana
568 : :
569 : : template <>
570 : : template <>
571 : : inline bool
572 : : is_a_helper <const stack_region *>::test (const region *reg)
573 : : {
574 : : return reg->get_kind () == RK_STACK;
575 : : }
576 : :
577 : : namespace ana {
578 : :
579 : : /* Concrete space_region subclass: a region within which regions can be
580 : : dynamically allocated. */
581 : :
582 : 3769 : class heap_region : public space_region
583 : : {
584 : : public:
585 : 3769 : heap_region (symbol::id_t id, region *parent)
586 : 3769 : : space_region (id, parent)
587 : : {}
588 : :
589 : 1375534 : enum region_kind get_kind () const final override { return RK_HEAP; }
590 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
591 : : void print_dump_widget_label (pretty_printer *pp) const final override;
592 : : };
593 : :
594 : : } // namespace ana
595 : :
596 : : template <>
597 : : template <>
598 : : inline bool
599 : : is_a_helper <const heap_region *>::test (const region *reg)
600 : : {
601 : : return reg->get_kind () == RK_HEAP;
602 : : }
603 : :
604 : : namespace ana {
605 : :
606 : : /* Concrete space_region subclass: thread-local data for the thread
607 : : being analyzed. */
608 : :
609 : 3769 : class thread_local_region : public space_region
610 : : {
611 : : public:
612 : 3769 : thread_local_region (symbol::id_t id, region *parent)
613 : 3769 : : space_region (id, parent)
614 : : {}
615 : :
616 : 211971 : enum region_kind get_kind () const final override { return RK_THREAD_LOCAL; }
617 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
618 : : void print_dump_widget_label (pretty_printer *pp) const final override;
619 : : };
620 : :
621 : : } // namespace ana
622 : :
623 : : template <>
624 : : template <>
625 : : inline bool
626 : : is_a_helper <const thread_local_region *>::test (const region *reg)
627 : : {
628 : : return reg->get_kind () == RK_THREAD_LOCAL;
629 : : }
630 : :
631 : : namespace ana {
632 : :
633 : : /* Concrete region subclass. The root region, containing all regions
634 : : (either directly, or as descendents).
635 : : Unique within a region_model_manager. */
636 : :
637 : 3769 : class root_region : public region
638 : : {
639 : : public:
640 : : root_region (symbol::id_t id);
641 : :
642 : 4895502 : enum region_kind get_kind () const final override { return RK_ROOT; }
643 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
644 : : void print_dump_widget_label (pretty_printer *pp) const final override;
645 : : };
646 : :
647 : : } // namespace ana
648 : :
649 : : template <>
650 : : template <>
651 : : inline bool
652 : : is_a_helper <const root_region *>::test (const region *reg)
653 : : {
654 : : return reg->get_kind () == RK_ROOT;
655 : : }
656 : :
657 : : namespace ana {
658 : :
659 : : /* Concrete region subclass: a region to use when dereferencing an unknown
660 : : pointer. */
661 : :
662 : : class symbolic_region : public region
663 : : {
664 : : public:
665 : : /* A support class for uniquifying instances of symbolic_region. */
666 : : struct key_t
667 : : {
668 : 91226 : key_t (const region *parent, const svalue *sval_ptr)
669 : 91226 : : m_parent (parent), m_sval_ptr (sval_ptr)
670 : : {
671 : 91226 : gcc_assert (sval_ptr);
672 : : }
673 : :
674 : 541800 : hashval_t hash () const
675 : : {
676 : 541800 : inchash::hash hstate;
677 : 541800 : hstate.add_ptr (m_parent);
678 : 541800 : hstate.add_ptr (m_sval_ptr);
679 : 541800 : return hstate.end ();
680 : : }
681 : :
682 : 527362 : bool operator== (const key_t &other) const
683 : : {
684 : 527362 : return (m_parent == other.m_parent && m_sval_ptr == other.m_sval_ptr);
685 : : }
686 : :
687 : : void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
688 : 0 : void mark_empty () { m_sval_ptr = NULL; }
689 : 583717 : bool is_deleted () const
690 : : {
691 : 583717 : return m_sval_ptr == reinterpret_cast<const svalue *> (1);
692 : : }
693 : 1944891 : bool is_empty () const { return m_sval_ptr == NULL; }
694 : :
695 : : const region *m_parent;
696 : : const svalue *m_sval_ptr;
697 : : };
698 : :
699 : : symbolic_region (symbol::id_t id, region *parent, const svalue *sval_ptr);
700 : :
701 : : const symbolic_region *
702 : 2229917 : dyn_cast_symbolic_region () const final override { return this; }
703 : :
704 : 15145176 : enum region_kind get_kind () const final override { return RK_SYMBOLIC; }
705 : : void accept (visitor *v) const final override;
706 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
707 : : void print_dump_widget_label (pretty_printer *pp) const final override;
708 : : void
709 : : add_dump_widget_children (text_art::tree_widget &w,
710 : : const text_art::dump_widget_info &dwi)
711 : : const final override;
712 : :
713 : 2236366 : const svalue *get_pointer () const { return m_sval_ptr; }
714 : :
715 : : private:
716 : : const svalue *m_sval_ptr;
717 : : };
718 : :
719 : : } // namespace ana
720 : :
721 : : template <>
722 : : template <>
723 : : inline bool
724 : 6449 : is_a_helper <const symbolic_region *>::test (const region *reg)
725 : : {
726 : 6449 : return reg->get_kind () == RK_SYMBOLIC;
727 : : }
728 : :
729 : : template <> struct default_hash_traits<symbolic_region::key_t>
730 : : : public member_function_hash_traits<symbolic_region::key_t>
731 : : {
732 : : static const bool empty_zero_p = true;
733 : : };
734 : :
735 : : namespace ana {
736 : :
737 : : /* Concrete region subclass representing the memory occupied by a
738 : : variable (whether for a global or a local).
739 : : Also used for representing SSA names, as if they were locals. */
740 : :
741 : : class decl_region : public region
742 : : {
743 : : public:
744 : 102452 : decl_region (symbol::id_t id, const region *parent, tree decl)
745 : 307356 : : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
746 : 204904 : m_tracked (calc_tracked_p (decl)),
747 : 102452 : m_ctor_svalue (NULL)
748 : 102452 : {}
749 : :
750 : 56944209 : enum region_kind get_kind () const final override { return RK_DECL; }
751 : : const decl_region *
752 : 7007527 : dyn_cast_decl_region () const final override { return this; }
753 : :
754 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
755 : :
756 : : void
757 : : print_dump_widget_label (pretty_printer *pp) const final override;
758 : :
759 : 89 : bool tracked_p () const final override { return m_tracked; }
760 : :
761 : 4885227 : tree get_decl () const { return m_decl; }
762 : : int get_stack_depth () const;
763 : :
764 : : const svalue *maybe_get_constant_value (region_model_manager *mgr) const;
765 : : const svalue *get_svalue_for_constructor (tree ctor,
766 : : region_model_manager *mgr) const;
767 : : const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
768 : :
769 : : private:
770 : : const svalue *calc_svalue_for_constructor (tree ctor,
771 : : region_model_manager *mgr) const;
772 : : static bool calc_tracked_p (tree decl);
773 : :
774 : : tree m_decl;
775 : :
776 : : /* Cached result of calc_tracked_p, so that we can quickly determine when
777 : : we don't to track a binding_cluster for this decl (to avoid bloating
778 : : store objects).
779 : : This can be debugged using -fdump-analyzer-untracked. */
780 : : bool m_tracked;
781 : :
782 : : /* Cached result of get_svalue_for_constructor. */
783 : : mutable const svalue *m_ctor_svalue;
784 : : };
785 : :
786 : : } // namespace ana
787 : :
788 : : template <>
789 : : template <>
790 : : inline bool
791 : 833450 : is_a_helper <const decl_region *>::test (const region *reg)
792 : : {
793 : 833450 : return reg->get_kind () == RK_DECL;
794 : : }
795 : :
796 : : namespace ana {
797 : :
798 : : /* Concrete region subclass representing the memory occupied by a
799 : : field within a struct or union. */
800 : :
801 : : class field_region : public region
802 : : {
803 : : public:
804 : : /* A support class for uniquifying instances of field_region. */
805 : : struct key_t
806 : : {
807 : 53154 : key_t (const region *parent, tree field)
808 : 53154 : : m_parent (parent), m_field (field)
809 : : {
810 : 53154 : gcc_assert (field);
811 : : }
812 : :
813 : 317184 : hashval_t hash () const
814 : : {
815 : 317184 : inchash::hash hstate;
816 : 317184 : hstate.add_ptr (m_parent);
817 : 317184 : hstate.add_ptr (m_field);
818 : 317184 : return hstate.end ();
819 : : }
820 : :
821 : 307505 : bool operator== (const key_t &other) const
822 : : {
823 : 307505 : return (m_parent == other.m_parent && m_field == other.m_field);
824 : : }
825 : :
826 : : void mark_deleted () { m_field = reinterpret_cast<tree> (1); }
827 : 0 : void mark_empty () { m_field = NULL_TREE; }
828 : 346159 : bool is_deleted () const { return m_field == reinterpret_cast<tree> (1); }
829 : 1234662 : bool is_empty () const { return m_field == NULL_TREE; }
830 : :
831 : : const region *m_parent;
832 : : tree m_field;
833 : : };
834 : :
835 : 7273 : field_region (symbol::id_t id, const region *parent, tree field)
836 : 14546 : : region (complexity (parent), id, parent, TREE_TYPE (field)),
837 : 7273 : m_field (field)
838 : 7273 : {}
839 : :
840 : 1240049 : enum region_kind get_kind () const final override { return RK_FIELD; }
841 : :
842 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
843 : : void print_dump_widget_label (pretty_printer *pp) const final override;
844 : :
845 : : const field_region *
846 : 598 : dyn_cast_field_region () const final override { return this; }
847 : :
848 : 2187 : tree get_field () const { return m_field; }
849 : :
850 : : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
851 : : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
852 : : const final override;
853 : :
854 : : private:
855 : : tree m_field;
856 : : };
857 : :
858 : : } // namespace ana
859 : :
860 : : template <>
861 : : template <>
862 : : inline bool
863 : 1651 : is_a_helper <const field_region *>::test (const region *reg)
864 : : {
865 : 1651 : return reg->get_kind () == RK_FIELD;
866 : : }
867 : :
868 : : template <> struct default_hash_traits<field_region::key_t>
869 : : : public member_function_hash_traits<field_region::key_t>
870 : : {
871 : : static const bool empty_zero_p = true;
872 : : };
873 : :
874 : : namespace ana {
875 : :
876 : : /* An element within an array. */
877 : :
878 : : class element_region : public region
879 : : {
880 : : public:
881 : : /* A support class for uniquifying instances of element_region. */
882 : : struct key_t
883 : : {
884 : 15936 : key_t (const region *parent, tree element_type, const svalue *index)
885 : 15936 : : m_parent (parent), m_element_type (element_type), m_index (index)
886 : : {
887 : 15936 : gcc_assert (index);
888 : : }
889 : :
890 : 103266 : hashval_t hash () const
891 : : {
892 : 103266 : inchash::hash hstate;
893 : 103266 : hstate.add_ptr (m_parent);
894 : 103266 : hstate.add_ptr (m_element_type);
895 : 103266 : hstate.add_ptr (m_index);
896 : 103266 : return hstate.end ();
897 : : }
898 : :
899 : 98272 : bool operator== (const key_t &other) const
900 : : {
901 : 98272 : return (m_parent == other.m_parent
902 : 49952 : && m_element_type == other.m_element_type
903 : 148224 : && m_index == other.m_index);
904 : : }
905 : :
906 : : void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
907 : 0 : void mark_empty () { m_index = NULL; }
908 : 113391 : bool is_deleted () const
909 : : {
910 : 113391 : return m_index == reinterpret_cast<const svalue *> (1);
911 : : }
912 : 475475 : bool is_empty () const { return m_index == NULL; }
913 : :
914 : : const region *m_parent;
915 : : tree m_element_type;
916 : : const svalue *m_index;
917 : : };
918 : :
919 : 3692 : element_region (symbol::id_t id, const region *parent, tree element_type,
920 : : const svalue *index)
921 : 3692 : : region (complexity::from_pair (parent, index), id, parent, element_type),
922 : 7384 : m_index (index)
923 : 3692 : {}
924 : :
925 : 124208 : enum region_kind get_kind () const final override { return RK_ELEMENT; }
926 : : const element_region *
927 : 13007 : dyn_cast_element_region () const final override { return this; }
928 : :
929 : : void accept (visitor *v) const final override;
930 : :
931 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
932 : :
933 : : void
934 : : print_dump_widget_label (pretty_printer *pp) const final override;
935 : : void
936 : : add_dump_widget_children (text_art::tree_widget &,
937 : : const text_art::dump_widget_info &dwi)
938 : : const final override;
939 : :
940 : 22012 : const svalue *get_index () const { return m_index; }
941 : :
942 : : virtual bool
943 : : get_relative_concrete_offset (bit_offset_t *out) const final override;
944 : : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
945 : : const final override;
946 : :
947 : : private:
948 : : const svalue *m_index;
949 : : };
950 : :
951 : : } // namespace ana
952 : :
953 : : template <>
954 : : template <>
955 : : inline bool
956 : 262 : is_a_helper <const element_region *>::test (const region *reg)
957 : : {
958 : 262 : return reg->get_kind () == RK_ELEMENT;
959 : : }
960 : :
961 : : template <> struct default_hash_traits<element_region::key_t>
962 : : : public member_function_hash_traits<element_region::key_t>
963 : : {
964 : : static const bool empty_zero_p = true;
965 : : };
966 : :
967 : : namespace ana {
968 : :
969 : : /* A byte-offset within another region, for handling pointer arithmetic
970 : : as a region. */
971 : :
972 : : class offset_region : public region
973 : : {
974 : : public:
975 : : /* A support class for uniquifying instances of offset_region. */
976 : : struct key_t
977 : : {
978 : 18172 : key_t (const region *parent, tree element_type, const svalue *byte_offset)
979 : 18172 : : m_parent (parent), m_element_type (element_type), m_byte_offset (byte_offset)
980 : : {
981 : 18172 : gcc_assert (byte_offset);
982 : : }
983 : :
984 : 114113 : hashval_t hash () const
985 : : {
986 : 114113 : inchash::hash hstate;
987 : 114113 : hstate.add_ptr (m_parent);
988 : 114113 : hstate.add_ptr (m_element_type);
989 : 114113 : hstate.add_ptr (m_byte_offset);
990 : 114113 : return hstate.end ();
991 : : }
992 : :
993 : 107897 : bool operator== (const key_t &other) const
994 : : {
995 : 107897 : return (m_parent == other.m_parent
996 : 45085 : && m_element_type == other.m_element_type
997 : 150393 : && m_byte_offset == other.m_byte_offset);
998 : : }
999 : :
1000 : : void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
1001 : 0 : void mark_empty () { m_byte_offset = NULL; }
1002 : 124892 : bool is_deleted () const
1003 : : {
1004 : 124892 : return m_byte_offset == reinterpret_cast<const svalue *> (1);
1005 : : }
1006 : 514860 : bool is_empty () const { return m_byte_offset == NULL; }
1007 : :
1008 : : const region *m_parent;
1009 : : tree m_element_type;
1010 : : const svalue *m_byte_offset;
1011 : : };
1012 : :
1013 : 3731 : offset_region (symbol::id_t id, const region *parent, tree type,
1014 : : const svalue *byte_offset)
1015 : 3731 : : region (complexity::from_pair (parent, byte_offset), id, parent, type),
1016 : 7462 : m_byte_offset (byte_offset)
1017 : 3731 : {}
1018 : :
1019 : 658980 : enum region_kind get_kind () const final override { return RK_OFFSET; }
1020 : : const offset_region *
1021 : 173026 : dyn_cast_offset_region () const final override { return this; }
1022 : :
1023 : : void accept (visitor *v) const final override;
1024 : :
1025 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1026 : :
1027 : : void
1028 : : print_dump_widget_label (pretty_printer *pp) const final override;
1029 : : void
1030 : : add_dump_widget_children (text_art::tree_widget &,
1031 : : const text_art::dump_widget_info &dwi)
1032 : : const final override;
1033 : :
1034 : 186148 : const svalue *get_byte_offset () const { return m_byte_offset; }
1035 : : const svalue *get_bit_offset (region_model_manager *mgr) const;
1036 : :
1037 : : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1038 : : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
1039 : : const final override;
1040 : :
1041 : : private:
1042 : : const svalue *m_byte_offset;
1043 : : };
1044 : :
1045 : : } // namespace ana
1046 : :
1047 : : template <>
1048 : : template <>
1049 : : inline bool
1050 : 668 : is_a_helper <const offset_region *>::test (const region *reg)
1051 : : {
1052 : 668 : return reg->get_kind () == RK_OFFSET;
1053 : : }
1054 : :
1055 : : template <> struct default_hash_traits<offset_region::key_t>
1056 : : : public member_function_hash_traits<offset_region::key_t>
1057 : : {
1058 : : static const bool empty_zero_p = true;
1059 : : };
1060 : :
1061 : : namespace ana {
1062 : :
1063 : : /* A region that is size BYTES_SIZE_SVAL in size within its parent
1064 : : region (or possibly larger, which would lead to an overflow. */
1065 : :
1066 : : class sized_region : public region
1067 : : {
1068 : : public:
1069 : : /* A support class for uniquifying instances of sized_region. */
1070 : : struct key_t
1071 : : {
1072 : 7321 : key_t (const region *parent, tree element_type,
1073 : : const svalue *byte_size_sval)
1074 : 7321 : : m_parent (parent), m_element_type (element_type),
1075 : 7321 : m_byte_size_sval (byte_size_sval)
1076 : : {
1077 : 7321 : gcc_assert (byte_size_sval);
1078 : : }
1079 : :
1080 : 48284 : hashval_t hash () const
1081 : : {
1082 : 48284 : inchash::hash hstate;
1083 : 48284 : hstate.add_ptr (m_parent);
1084 : 48284 : hstate.add_ptr (m_element_type);
1085 : 48284 : hstate.add_ptr (m_byte_size_sval);
1086 : 48284 : return hstate.end ();
1087 : : }
1088 : :
1089 : 43340 : bool operator== (const key_t &other) const
1090 : : {
1091 : 43340 : return (m_parent == other.m_parent
1092 : 7625 : && m_element_type == other.m_element_type
1093 : 50963 : && m_byte_size_sval == other.m_byte_size_sval);
1094 : : }
1095 : :
1096 : : void mark_deleted () { m_byte_size_sval = reinterpret_cast<const svalue *> (1); }
1097 : 0 : void mark_empty () { m_byte_size_sval = NULL; }
1098 : 53881 : bool is_deleted () const
1099 : : {
1100 : 53881 : return m_byte_size_sval == reinterpret_cast<const svalue *> (1);
1101 : : }
1102 : 297136 : bool is_empty () const { return m_byte_size_sval == NULL; }
1103 : :
1104 : : const region *m_parent;
1105 : : tree m_element_type;
1106 : : const svalue *m_byte_size_sval;
1107 : : const svalue *m_end_offset;
1108 : : };
1109 : :
1110 : 3128 : sized_region (symbol::id_t id, const region *parent, tree type,
1111 : : const svalue *byte_size_sval)
1112 : 3128 : : region (complexity::from_pair (parent, byte_size_sval),
1113 : : id, parent, type),
1114 : 6256 : m_byte_size_sval (byte_size_sval)
1115 : 3128 : {}
1116 : :
1117 : 39611 : enum region_kind get_kind () const final override { return RK_SIZED; }
1118 : : const sized_region *
1119 : 0 : dyn_cast_sized_region () const final override { return this; }
1120 : :
1121 : : void accept (visitor *v) const final override;
1122 : :
1123 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1124 : : void
1125 : : print_dump_widget_label (pretty_printer *pp) const final override;
1126 : : void
1127 : : add_dump_widget_children (text_art::tree_widget &,
1128 : : const text_art::dump_widget_info &dwi)
1129 : : const final override;
1130 : :
1131 : : bool get_byte_size (byte_size_t *out) const final override;
1132 : : bool get_bit_size (bit_size_t *out) const final override;
1133 : :
1134 : : const svalue *
1135 : 9295 : get_byte_size_sval (region_model_manager *) const final override
1136 : : {
1137 : 9295 : return m_byte_size_sval;
1138 : : }
1139 : :
1140 : : const svalue *
1141 : : get_bit_size_sval (region_model_manager *) const final override;
1142 : :
1143 : : private:
1144 : : const svalue *m_byte_size_sval;
1145 : : };
1146 : :
1147 : : } // namespace ana
1148 : :
1149 : : template <>
1150 : : template <>
1151 : : inline bool
1152 : 0 : is_a_helper <const sized_region *>::test (const region *reg)
1153 : : {
1154 : 0 : return reg->get_kind () == RK_SIZED;
1155 : : }
1156 : :
1157 : : template <> struct default_hash_traits<sized_region::key_t>
1158 : : : public member_function_hash_traits<sized_region::key_t>
1159 : : {
1160 : : static const bool empty_zero_p = true;
1161 : : };
1162 : :
1163 : : namespace ana {
1164 : :
1165 : : /* A region that views another region using a different type. */
1166 : :
1167 : : class cast_region : public region
1168 : : {
1169 : : public:
1170 : : /* A support class for uniquifying instances of cast_region. */
1171 : : struct key_t
1172 : : {
1173 : 19912 : key_t (const region *parent, tree type)
1174 : 19912 : : m_parent (parent), m_type (type)
1175 : : {
1176 : 19912 : gcc_assert (parent);
1177 : : }
1178 : :
1179 : 87125 : hashval_t hash () const
1180 : : {
1181 : 87125 : inchash::hash hstate;
1182 : 87125 : hstate.add_ptr (m_parent);
1183 : 87125 : hstate.add_ptr (m_type);
1184 : 87125 : return hstate.end ();
1185 : : }
1186 : :
1187 : 72978 : bool operator== (const key_t &other) const
1188 : : {
1189 : 72978 : return (m_parent == other.m_parent
1190 : 72978 : && m_type == other.m_type);
1191 : : }
1192 : :
1193 : : void mark_deleted ()
1194 : : {
1195 : : m_parent = reinterpret_cast<const region *> (1);
1196 : : }
1197 : 0 : void mark_empty () { m_parent = nullptr; }
1198 : 91154 : bool is_deleted () const
1199 : : {
1200 : 91154 : return m_parent == reinterpret_cast<const region *> (1);
1201 : : }
1202 : 467226 : bool is_empty () const { return m_parent == nullptr; }
1203 : :
1204 : : const region *m_parent;
1205 : : tree m_type;
1206 : : };
1207 : :
1208 : 2392 : cast_region (symbol::id_t id, const region *parent, tree type)
1209 : 2392 : : region (complexity (parent), id,
1210 : 2392 : parent, type)
1211 : 2392 : {}
1212 : :
1213 : 106412 : enum region_kind get_kind () const final override { return RK_CAST; }
1214 : : const cast_region *
1215 : 5452 : dyn_cast_cast_region () const final override { return this; }
1216 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1217 : : void
1218 : : print_dump_widget_label (pretty_printer *pp) const final override;
1219 : :
1220 : : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1221 : : };
1222 : :
1223 : : } // namespace ana
1224 : :
1225 : : template <>
1226 : : template <>
1227 : : inline bool
1228 : : is_a_helper <const cast_region *>::test (const region *reg)
1229 : : {
1230 : : return reg->get_kind () == RK_CAST;
1231 : : }
1232 : :
1233 : : template <> struct default_hash_traits<cast_region::key_t>
1234 : : : public member_function_hash_traits<cast_region::key_t>
1235 : : {
1236 : : static const bool empty_zero_p = true;
1237 : : };
1238 : :
1239 : : namespace ana {
1240 : :
1241 : : /* An untyped region dynamically allocated on the heap via "malloc"
1242 : : or similar. */
1243 : :
1244 : : class heap_allocated_region : public region
1245 : : {
1246 : : public:
1247 : 1262 : heap_allocated_region (symbol::id_t id, const region *parent)
1248 : 1262 : : region (complexity (parent), id, parent, NULL_TREE)
1249 : 1262 : {}
1250 : :
1251 : : enum region_kind
1252 : 6484858 : get_kind () const final override { return RK_HEAP_ALLOCATED; }
1253 : :
1254 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1255 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1256 : : };
1257 : :
1258 : : /* An untyped region dynamically allocated on the stack via "alloca". */
1259 : :
1260 : : class alloca_region : public region
1261 : : {
1262 : : public:
1263 : 1105 : alloca_region (symbol::id_t id, const frame_region *parent)
1264 : 1105 : : region (complexity (parent), id, parent, NULL_TREE)
1265 : 1105 : {}
1266 : :
1267 : 370888 : enum region_kind get_kind () const final override { return RK_ALLOCA; }
1268 : :
1269 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1270 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1271 : : };
1272 : :
1273 : : /* A region for a STRING_CST. */
1274 : :
1275 : : class string_region : public region
1276 : : {
1277 : : public:
1278 : 3725 : string_region (symbol::id_t id, const region *parent, tree string_cst)
1279 : 7450 : : region (complexity (parent), id, parent, TREE_TYPE (string_cst)),
1280 : 3725 : m_string_cst (string_cst)
1281 : 3725 : {}
1282 : :
1283 : : const string_region *
1284 : 10229 : dyn_cast_string_region () const final override { return this; }
1285 : :
1286 : 237844 : enum region_kind get_kind () const final override { return RK_STRING; }
1287 : :
1288 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1289 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1290 : :
1291 : : /* We assume string literals are immutable, so we don't track them in
1292 : : the store. */
1293 : 1111 : bool tracked_p () const final override { return false; }
1294 : :
1295 : 11056 : tree get_string_cst () const { return m_string_cst; }
1296 : :
1297 : : private:
1298 : : tree m_string_cst;
1299 : : };
1300 : :
1301 : : } // namespace ana
1302 : :
1303 : : template <>
1304 : : template <>
1305 : : inline bool
1306 : 468 : is_a_helper <const string_region *>::test (const region *reg)
1307 : : {
1308 : 468 : return reg->get_kind () == RK_STRING;
1309 : : }
1310 : :
1311 : : namespace ana {
1312 : :
1313 : : /* A region for a specific range of bits within another region. */
1314 : :
1315 : : class bit_range_region : public region
1316 : : {
1317 : : public:
1318 : : /* A support class for uniquifying instances of bit_range_region. */
1319 : : struct key_t
1320 : : {
1321 : 192 : key_t (const region *parent, tree type, const bit_range &bits)
1322 : 192 : : m_parent (parent), m_type (type), m_bits (bits)
1323 : : {
1324 : 192 : gcc_assert (parent);
1325 : 192 : }
1326 : :
1327 : 1626 : hashval_t hash () const
1328 : : {
1329 : 1626 : inchash::hash hstate;
1330 : 1626 : hstate.add_ptr (m_parent);
1331 : 1626 : hstate.add_ptr (m_type);
1332 : 1626 : hstate.add_wide_int (m_bits.m_start_bit_offset);
1333 : 1626 : hstate.add_wide_int (m_bits.m_size_in_bits);
1334 : 1626 : return hstate.end ();
1335 : : }
1336 : :
1337 : 1443 : bool operator== (const key_t &other) const
1338 : : {
1339 : 1443 : return (m_parent == other.m_parent
1340 : 993 : && m_type == other.m_type
1341 : 2436 : && m_bits == other.m_bits);
1342 : : }
1343 : :
1344 : : void mark_deleted () { m_parent = reinterpret_cast<const region *> (1); }
1345 : 0 : void mark_empty () { m_parent = NULL; }
1346 : 1844 : bool is_deleted () const
1347 : : {
1348 : 1844 : return m_parent == reinterpret_cast<const region *> (1);
1349 : : }
1350 : 104812 : bool is_empty () const { return m_parent == NULL; }
1351 : :
1352 : : const region *m_parent;
1353 : : tree m_type;
1354 : : bit_range m_bits;
1355 : : };
1356 : :
1357 : 148 : bit_range_region (symbol::id_t id, const region *parent, tree type,
1358 : : const bit_range &bits)
1359 : 148 : : region (complexity (parent), id, parent, type),
1360 : 148 : m_bits (bits)
1361 : 148 : {}
1362 : :
1363 : : const bit_range_region *
1364 : 0 : dyn_cast_bit_range_region () const final override { return this; }
1365 : :
1366 : 989 : enum region_kind get_kind () const final override { return RK_BIT_RANGE; }
1367 : :
1368 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1369 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1370 : :
1371 : 0 : const bit_range &get_bits () const { return m_bits; }
1372 : :
1373 : : bool get_byte_size (byte_size_t *out) const final override;
1374 : : bool get_bit_size (bit_size_t *out) const final override;
1375 : : const svalue *get_byte_size_sval (region_model_manager *mgr) const final override;
1376 : : const svalue *get_bit_size_sval (region_model_manager *mgr) const final override;
1377 : : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1378 : : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
1379 : : const final override;
1380 : :
1381 : : private:
1382 : : bit_range m_bits;
1383 : : };
1384 : :
1385 : : } // namespace ana
1386 : :
1387 : : template <>
1388 : : template <>
1389 : : inline bool
1390 : 0 : is_a_helper <const bit_range_region *>::test (const region *reg)
1391 : : {
1392 : 0 : return reg->get_kind () == RK_BIT_RANGE;
1393 : : }
1394 : :
1395 : : template <> struct default_hash_traits<bit_range_region::key_t>
1396 : : : public member_function_hash_traits<bit_range_region::key_t>
1397 : : {
1398 : : static const bool empty_zero_p = true;
1399 : : };
1400 : :
1401 : : namespace ana {
1402 : :
1403 : : /* A region for the N-th vararg within a frame_region for a variadic call. */
1404 : :
1405 : : class var_arg_region : public region
1406 : : {
1407 : : public:
1408 : : /* A support class for uniquifying instances of var_arg_region. */
1409 : : struct key_t
1410 : : {
1411 : 1123 : key_t (const frame_region *parent, unsigned idx)
1412 : 1123 : : m_parent (parent), m_idx (idx)
1413 : : {
1414 : 1123 : gcc_assert (parent);
1415 : : }
1416 : :
1417 : 8114 : hashval_t hash () const
1418 : : {
1419 : 8114 : inchash::hash hstate;
1420 : 8114 : hstate.add_ptr (m_parent);
1421 : 8114 : hstate.add_int (m_idx);
1422 : 8114 : return hstate.end ();
1423 : : }
1424 : :
1425 : 7409 : bool operator== (const key_t &other) const
1426 : : {
1427 : 7409 : return (m_parent == other.m_parent
1428 : 7409 : && m_idx == other.m_idx);
1429 : : }
1430 : :
1431 : : void mark_deleted ()
1432 : : {
1433 : : m_parent = reinterpret_cast<const frame_region *> (1);
1434 : : }
1435 : 0 : void mark_empty () { m_parent = NULL; }
1436 : 9012 : bool is_deleted () const
1437 : : {
1438 : 9012 : return m_parent == reinterpret_cast<const frame_region *> (1);
1439 : : }
1440 : 129471 : bool is_empty () const { return m_parent == NULL; }
1441 : :
1442 : : const frame_region *m_parent;
1443 : : unsigned m_idx;
1444 : : };
1445 : :
1446 : 480 : var_arg_region (symbol::id_t id, const frame_region *parent,
1447 : : unsigned idx)
1448 : 480 : : region (complexity (parent), id, parent, NULL_TREE),
1449 : 480 : m_idx (idx)
1450 : 480 : {}
1451 : :
1452 : : const var_arg_region *
1453 : 481 : dyn_cast_var_arg_region () const final override { return this; }
1454 : :
1455 : 245534 : enum region_kind get_kind () const final override { return RK_VAR_ARG; }
1456 : :
1457 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1458 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1459 : :
1460 : : const frame_region *get_frame_region () const;
1461 : 605 : unsigned get_index () const { return m_idx; }
1462 : :
1463 : : private:
1464 : : unsigned m_idx;
1465 : : };
1466 : :
1467 : : } // namespace ana
1468 : :
1469 : : template <>
1470 : : template <>
1471 : : inline bool
1472 : : is_a_helper <const var_arg_region *>::test (const region *reg)
1473 : : {
1474 : : return reg->get_kind () == RK_VAR_ARG;
1475 : : }
1476 : :
1477 : : template <> struct default_hash_traits<var_arg_region::key_t>
1478 : : : public member_function_hash_traits<var_arg_region::key_t>
1479 : : {
1480 : : static const bool empty_zero_p = true;
1481 : : };
1482 : :
1483 : : namespace ana {
1484 : :
1485 : : /* A region for errno for the current thread. */
1486 : :
1487 : 3769 : class errno_region : public region
1488 : : {
1489 : : public:
1490 : 3769 : errno_region (symbol::id_t id, const thread_local_region *parent)
1491 : 3769 : : region (complexity (parent), id, parent, integer_type_node)
1492 : 3769 : {}
1493 : :
1494 : 721218 : enum region_kind get_kind () const final override { return RK_ERRNO; }
1495 : :
1496 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1497 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1498 : : };
1499 : :
1500 : : } // namespace ana
1501 : :
1502 : : template <>
1503 : : template <>
1504 : : inline bool
1505 : : is_a_helper <const errno_region *>::test (const region *reg)
1506 : : {
1507 : : return reg->get_kind () == RK_ERRNO;
1508 : : }
1509 : :
1510 : : namespace ana {
1511 : :
1512 : : /* Similar to a decl region, but we don't have the decl.
1513 : : For implementing e.g. static buffers of known_functions,
1514 : : or other internal state of an API.
1515 : :
1516 : : These are owned by known_function instances, rather than the
1517 : : region_model_manager. */
1518 : :
1519 : : class private_region : public region
1520 : : {
1521 : : public:
1522 : 6394 : private_region (unsigned id, const region *parent, tree type,
1523 : : const char *desc)
1524 : 6394 : : region (complexity (parent), id, parent, type),
1525 : 6394 : m_desc (desc)
1526 : 6394 : {}
1527 : :
1528 : 35352 : enum region_kind get_kind () const final override { return RK_PRIVATE; }
1529 : :
1530 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1531 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1532 : :
1533 : : private:
1534 : : const char *m_desc;
1535 : : };
1536 : :
1537 : : } // namespace ana
1538 : :
1539 : : template <>
1540 : : template <>
1541 : : inline bool
1542 : : is_a_helper <const private_region *>::test (const region *reg)
1543 : : {
1544 : : return reg->get_kind () == RK_PRIVATE;
1545 : : }
1546 : :
1547 : : namespace ana {
1548 : :
1549 : : /* An unknown region, for handling unimplemented tree codes. */
1550 : :
1551 : : class unknown_region : public region
1552 : : {
1553 : : public:
1554 : 54 : unknown_region (symbol::id_t id, const region *parent, tree type)
1555 : 54 : : region (complexity (parent), id, parent, type)
1556 : 54 : {}
1557 : :
1558 : 1754 : enum region_kind get_kind () const final override { return RK_UNKNOWN; }
1559 : :
1560 : : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1561 : : void print_dump_widget_label (pretty_printer *pp) const final override;
1562 : : };
1563 : :
1564 : : } // namespace ana
1565 : :
1566 : : #endif /* GCC_ANALYZER_REGION_H */
|