3 Copyright (C) 2022-2023 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #ifndef GDB_FRAME_INFO_H
21 #define GDB_FRAME_INFO_H
23 #include "gdbsupport/intrusive_list.h"
28 /* A wrapper for "frame_info *". frame_info objects are invalidated
29 whenever reinit_frame_cache is called. This class arranges to
30 invalidate the pointer when appropriate. This is done to help
31 detect a GDB bug that was relatively common.
33 A small amount of code must still operate on raw pointers, so a
34 "get" method is provided. However, you should normally not use
37 class frame_info_ptr
: public intrusive_list_node
<frame_info_ptr
>
40 /* Create a frame_info_ptr from a raw pointer. */
41 explicit frame_info_ptr (struct frame_info
*ptr
)
44 frame_list
.push_back (*this);
47 /* Create a null frame_info_ptr. */
50 frame_list
.push_back (*this);
53 frame_info_ptr (std::nullptr_t
)
55 frame_list
.push_back (*this);
58 frame_info_ptr (const frame_info_ptr
&other
)
59 : m_ptr (other
.m_ptr
),
60 m_cached_id (other
.m_cached_id
),
61 m_cached_level (other
.m_cached_level
)
63 frame_list
.push_back (*this);
66 frame_info_ptr (frame_info_ptr
&&other
)
67 : m_ptr (other
.m_ptr
),
68 m_cached_id (other
.m_cached_id
),
69 m_cached_level (other
.m_cached_level
)
71 other
.m_ptr
= nullptr;
72 other
.m_cached_id
= null_frame_id
;
73 other
.m_cached_level
= invalid_level
;
74 frame_list
.push_back (*this);
79 /* If this node has static storage, it may be deleted after
80 frame_list. Attempting to erase ourselves would then trigger
81 internal errors, so make sure we are still linked first. */
83 frame_list
.erase (frame_list
.iterator_to (*this));
86 frame_info_ptr
&operator= (const frame_info_ptr
&other
)
89 m_cached_id
= other
.m_cached_id
;
90 m_cached_level
= other
.m_cached_level
;
94 frame_info_ptr
&operator= (std::nullptr_t
)
97 m_cached_id
= null_frame_id
;
98 m_cached_level
= invalid_level
;
102 frame_info_ptr
&operator= (frame_info_ptr
&&other
)
105 m_cached_id
= other
.m_cached_id
;
106 m_cached_level
= other
.m_cached_level
;
107 other
.m_ptr
= nullptr;
108 other
.m_cached_id
= null_frame_id
;
109 other
.m_cached_level
= invalid_level
;
113 frame_info
*operator-> () const
118 /* Fetch the underlying pointer. Note that new code should
119 generally not use this -- avoid it if at all possible. */
120 frame_info
*get () const
125 /* This exists for compatibility with pre-existing code that checked
126 a "frame_info *" using "!". */
127 bool operator! () const
129 return m_ptr
== nullptr;
132 /* This exists for compatibility with pre-existing code that checked
133 a "frame_info *" like "if (ptr)". */
134 explicit operator bool () const
136 return m_ptr
!= nullptr;
139 /* Invalidate this pointer. */
145 /* Cache the frame_id that the pointer will use to reinflate. */
146 void prepare_reinflate ();
148 /* Use the cached frame_id to reinflate the pointer. */
152 /* We sometimes need to construct frame_info_ptr objects around the
153 sentinel_frame, which has level -1. Therefore, make the invalid frame
155 static constexpr int invalid_level
= -2;
157 /* The underlying pointer. */
158 frame_info
*m_ptr
= nullptr;
160 /* The frame_id of the underlying pointer. */
161 frame_id m_cached_id
= null_frame_id
;
163 /* The frame level of the underlying pointer. */
164 int m_cached_level
= invalid_level
;
166 /* All frame_info_ptr objects are kept on an intrusive list.
167 This keeps their construction and destruction costs
169 static intrusive_list
<frame_info_ptr
> frame_list
;
171 /* A friend so it can invalidate the pointers. */
172 friend void reinit_frame_cache ();
176 operator== (const frame_info
*self
, const frame_info_ptr
&other
)
178 return self
== other
.get ();
182 operator== (const frame_info_ptr
&self
, const frame_info_ptr
&other
)
184 return self
.get () == other
.get ();
188 operator== (const frame_info_ptr
&self
, const frame_info
*other
)
190 return self
.get () == other
;
194 operator!= (const frame_info
*self
, const frame_info_ptr
&other
)
196 return self
!= other
.get ();
200 operator!= (const frame_info_ptr
&self
, const frame_info_ptr
&other
)
202 return self
.get () != other
.get ();
206 operator!= (const frame_info_ptr
&self
, const frame_info
*other
)
208 return self
.get () != other
;
211 #endif /* GDB_FRAME_INFO_H */