Introduce frame_info_ptr smart pointer class
[binutils-gdb.git] / gdb / frame-info.h
1 /* Frame info pointer
2
3 Copyright (C) 2022 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #ifndef GDB_FRAME_INFO_H
21 #define GDB_FRAME_INFO_H
22
23 #include "gdbsupport/intrusive_list.h"
24
25 struct frame_info;
26
27 extern void reinit_frame_cache ();
28
29 /* A wrapper for "frame_info *". frame_info objects are invalidated
30 whenever reinit_frame_cache is called. This class arranges to
31 invalidate the pointer when appropriate. This is done to help
32 detect a GDB bug that was relatively common.
33
34 A small amount of code must still operate on raw pointers, so a
35 "get" method is provided. However, you should normally not use
36 this in new code. */
37
38 class frame_info_ptr : public intrusive_list_node<frame_info_ptr>
39 {
40 public:
41 /* Create a frame_info_ptr from a raw pointer. */
42 explicit frame_info_ptr (struct frame_info *ptr)
43 : m_ptr (ptr)
44 {
45 frame_list.push_back (*this);
46 }
47
48 /* Create a null frame_info_ptr. */
49 frame_info_ptr ()
50 {
51 frame_list.push_back (*this);
52 }
53
54 frame_info_ptr (std::nullptr_t)
55 {
56 frame_list.push_back (*this);
57 }
58
59 frame_info_ptr (const frame_info_ptr &other)
60 : m_ptr (other.m_ptr)
61 {
62 frame_list.push_back (*this);
63 }
64
65 frame_info_ptr (frame_info_ptr &&other)
66 : m_ptr (other.m_ptr)
67 {
68 other.m_ptr = nullptr;
69 frame_list.push_back (*this);
70 }
71
72 ~frame_info_ptr ()
73 {
74 frame_list.erase (frame_list.iterator_to (*this));
75 }
76
77 frame_info_ptr &operator= (const frame_info_ptr &other)
78 {
79 m_ptr = other.m_ptr;
80 return *this;
81 }
82
83 frame_info_ptr &operator= (std::nullptr_t)
84 {
85 m_ptr = nullptr;
86 return *this;
87 }
88
89 frame_info_ptr &operator= (frame_info_ptr &&other)
90 {
91 m_ptr = other.m_ptr;
92 other.m_ptr = nullptr;
93 return *this;
94 }
95
96 frame_info *operator-> () const
97 {
98 return m_ptr;
99 }
100
101 /* Fetch the underlying pointer. Note that new code should
102 generally not use this -- avoid it if at all possible. */
103 frame_info *get () const
104 {
105 return m_ptr;
106 }
107
108 /* This exists for compatibility with pre-existing code that checked
109 a "frame_info *" using "!". */
110 bool operator! () const
111 {
112 return m_ptr == nullptr;
113 }
114
115 /* This exists for compatibility with pre-existing code that checked
116 a "frame_info *" like "if (ptr)". */
117 explicit operator bool () const
118 {
119 return m_ptr != nullptr;
120 }
121
122 /* Invalidate this pointer. */
123 void invalidate ()
124 {
125 m_ptr = nullptr;
126 }
127
128 private:
129
130 /* The underlying pointer. */
131 frame_info *m_ptr = nullptr;
132
133
134 /* All frame_info_ptr objects are kept on an intrusive list.
135 This keeps their construction and destruction costs
136 reasonably small. */
137 static intrusive_list<frame_info_ptr> frame_list;
138
139 /* A friend so it can invalidate the pointers. */
140 friend void reinit_frame_cache ();
141 };
142
143 static inline bool
144 operator== (const frame_info *self, const frame_info_ptr &other)
145 {
146 return self == other.get ();
147 }
148
149 static inline bool
150 operator== (const frame_info_ptr &self, const frame_info_ptr &other)
151 {
152 return self.get () == other.get ();
153 }
154
155 static inline bool
156 operator== (const frame_info_ptr &self, const frame_info *other)
157 {
158 return self.get () == other;
159 }
160
161 static inline bool
162 operator!= (const frame_info *self, const frame_info_ptr &other)
163 {
164 return self != other.get ();
165 }
166
167 static inline bool
168 operator!= (const frame_info_ptr &self, const frame_info_ptr &other)
169 {
170 return self.get () != other.get ();
171 }
172
173 static inline bool
174 operator!= (const frame_info_ptr &self, const frame_info *other)
175 {
176 return self.get () != other;
177 }
178
179 #endif /* GDB_FRAME_INFO_H */