aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/checker-path.h
blob: 1aa56d27927e0e950bcea721b6c58c0732be1279 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* Subclass of diagnostic_path for analyzer diagnostics.
   Copyright (C) 2019-2024 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#ifndef GCC_ANALYZER_CHECKER_PATH_H
#define GCC_ANALYZER_CHECKER_PATH_H

#include "analyzer/checker-event.h"
#include "simple-diagnostic-path.h"

namespace ana {

/* Subclass of diagnostic_path for analyzer diagnostics.  */

class checker_path : public diagnostic_path
{
public:
  checker_path (logger *logger)
  : diagnostic_path (),
    m_thread ("main"),
    m_logger (logger)
  {}

  /* Implementation of diagnostic_path vfuncs.  */

  unsigned num_events () const final override
  {
    return m_events.length ();
  }

  const diagnostic_event & get_event (int idx) const final override
  {
    return *m_events[idx];
  }
  unsigned num_threads () const final override
  {
    return 1;
  }
  const diagnostic_thread &
  get_thread (diagnostic_thread_id_t) const final override
  {
    return m_thread;
  }

  checker_event *get_checker_event (int idx)
  {
    return m_events[idx];
  }

  bool
  same_function_p (int event_idx_a,
		   int event_idx_b) const final override;

  void dump (pretty_printer *pp) const;
  void debug () const;

  logger *get_logger () const { return m_logger; }
  void maybe_log (logger *logger, const char *desc) const;

  void add_event (std::unique_ptr<checker_event> event);

  void delete_event (int idx)
  {
    checker_event *event = m_events[idx];
    m_events.ordered_remove (idx);
    delete event;
  }

  void delete_events (unsigned start_idx, unsigned len)
  {
    for (unsigned i = start_idx; i < start_idx + len; i++)
      delete m_events[i];
    m_events.block_remove (start_idx, len);
  }

  void replace_event (unsigned idx, checker_event *new_event)
  {
    delete m_events[idx];
    m_events[idx] = new_event;
  }

  void add_region_creation_events (pending_diagnostic *pd,
				   const region *reg,
				   const region_model *model,
				   const event_loc_info &loc_info,
				   bool debug);

  /* After all event-pruning, a hook for notifying each event what
     its ID will be.  The events are notified in order, allowing
     for later events to refer to the IDs of earlier events in
     their descriptions.  */
  void prepare_for_emission (pending_diagnostic *pd)
  {
    checker_event *e;
    int i;
    FOR_EACH_VEC_ELT (m_events, i, e)
      e->prepare_for_emission (this, pd, diagnostic_event_id_t (i));
  }

  void fixup_locations (pending_diagnostic *pd);

  void record_setjmp_event (const exploded_node *enode,
			    diagnostic_event_id_t setjmp_emission_id)
  {
    m_setjmp_event_ids.put (enode, setjmp_emission_id);
  }

  bool get_setjmp_event (const exploded_node *enode,
			 diagnostic_event_id_t *out_emission_id)
  {
    if (diagnostic_event_id_t *emission_id = m_setjmp_event_ids.get (enode))
      {
	*out_emission_id = *emission_id;
	return true;
      }
    return false;
  }

  bool cfg_edge_pair_at_p (unsigned idx) const;

  void inject_any_inlined_call_events (logger *logger);

private:
  DISABLE_COPY_AND_ASSIGN(checker_path);

  simple_diagnostic_thread m_thread;

  /* The events that have occurred along this path.  */
  auto_delete_vec<checker_event> m_events;

  /* During prepare_for_emission (and after), the setjmp_event for each
     exploded_node *, so that rewind events can refer to them in their
     descriptions.  */
  hash_map <const exploded_node *, diagnostic_event_id_t> m_setjmp_event_ids;

  logger *m_logger;
};

} // namespace ana

#endif /* GCC_ANALYZER_CHECKER_PATH_H */