annotate gcc/is-a.h @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Dynamic testing for abstract is-a relationships.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Lawrence Crowl.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 /* This header generic type query and conversion functions.
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 USING THE GENERIC TYPE FACILITY
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 The user functions are:
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 bool is_a <TYPE> (pointer)
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 Tests whether the pointer actually points to a more derived TYPE.
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 Suppose you have a symtab_node *ptr, AKA symtab_node *ptr. You can test
kono
parents:
diff changeset
35 whether it points to a 'derived' cgraph_node as follows.
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 if (is_a <cgraph_node *> (ptr))
kono
parents:
diff changeset
38 ....
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 TYPE as_a <TYPE> (pointer)
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 Converts pointer to a TYPE.
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 You can just assume that it is such a node.
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 do_something_with (as_a <cgraph_node *> *ptr);
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 TYPE safe_as_a <TYPE> (pointer)
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 Like as_a <TYPE> (pointer), but where pointer could be NULL. This
kono
parents:
diff changeset
52 adds a check against NULL where the regular is_a_helper hook for TYPE
kono
parents:
diff changeset
53 assumes non-NULL.
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 do_something_with (safe_as_a <cgraph_node *> *ptr);
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 TYPE dyn_cast <TYPE> (pointer)
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 Converts pointer to TYPE if and only if "is_a <TYPE> pointer". Otherwise,
kono
parents:
diff changeset
60 returns NULL. This function is essentially a checked down cast.
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 This functions reduce compile time and increase type safety when treating a
kono
parents:
diff changeset
63 generic item as a more specific item.
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 You can test and obtain a pointer to the 'derived' type in one indivisible
kono
parents:
diff changeset
66 operation.
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 if (cgraph_node *cptr = dyn_cast <cgraph_node *> (ptr))
kono
parents:
diff changeset
69 ....
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 As an example, the code change is from
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 if (symtab_function_p (node))
kono
parents:
diff changeset
74 {
kono
parents:
diff changeset
75 struct cgraph_node *cnode = cgraph (node);
kono
parents:
diff changeset
76 ....
kono
parents:
diff changeset
77 }
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 to
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
kono
parents:
diff changeset
82 {
kono
parents:
diff changeset
83 ....
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 The necessary conditional test defines a variable that holds a known good
kono
parents:
diff changeset
87 pointer to the specific item and avoids subsequent conversion calls and
kono
parents:
diff changeset
88 the assertion checks that may come with them.
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 When, the property test is embedded within a larger condition, the
kono
parents:
diff changeset
91 variable declaration gets pulled out of the condition. (This approach
kono
parents:
diff changeset
92 leaves some room for using the variable inappropriately.)
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 if (symtab_variable_p (node) && varpool (node)->finalized)
kono
parents:
diff changeset
95 varpool_analyze_node (varpool (node));
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 becomes
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 varpool_node *vnode = dyn_cast <varpool_node *> (node);
kono
parents:
diff changeset
100 if (vnode && vnode->finalized)
kono
parents:
diff changeset
101 varpool_analyze_node (vnode);
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 Note that we have converted two sets of assertions in the calls to varpool
kono
parents:
diff changeset
104 into safe and efficient use of a variable.
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 TYPE safe_dyn_cast <TYPE> (pointer)
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
kono
parents:
diff changeset
109 and returns null results for them.
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 If you use these functions and get a 'inline function not defined' or a
kono
parents:
diff changeset
113 'missing symbol' error message for 'is_a_helper<....>::test', it means that
kono
parents:
diff changeset
114 the connection between the types has not been made. See below.
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 EXTENDING THE GENERIC TYPE FACILITY
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 Each connection between types must be made by defining a specialization of the
kono
parents:
diff changeset
120 template member function 'test' of the template class 'is_a_helper'. For
kono
parents:
diff changeset
121 example,
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 template <>
kono
parents:
diff changeset
124 template <>
kono
parents:
diff changeset
125 inline bool
kono
parents:
diff changeset
126 is_a_helper <cgraph_node *>::test (symtab_node *p)
kono
parents:
diff changeset
127 {
kono
parents:
diff changeset
128 return p->type == SYMTAB_FUNCTION;
kono
parents:
diff changeset
129 }
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 If a simple reinterpret_cast between the pointer types is incorrect, then you
kono
parents:
diff changeset
132 must also specialize the template member function 'cast'. Failure to do so
kono
parents:
diff changeset
133 when needed may result in a crash. For example,
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 template <>
kono
parents:
diff changeset
136 template <>
kono
parents:
diff changeset
137 inline bool
kono
parents:
diff changeset
138 is_a_helper <cgraph_node *>::cast (symtab_node *p)
kono
parents:
diff changeset
139 {
kono
parents:
diff changeset
140 return &p->x_function;
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 */
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 #ifndef GCC_IS_A_H
kono
parents:
diff changeset
146 #define GCC_IS_A_H
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 /* A generic type conversion internal helper class. */
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 template <typename T>
kono
parents:
diff changeset
151 struct is_a_helper
kono
parents:
diff changeset
152 {
kono
parents:
diff changeset
153 template <typename U>
kono
parents:
diff changeset
154 static inline bool test (U *p);
kono
parents:
diff changeset
155 template <typename U>
kono
parents:
diff changeset
156 static inline T cast (U *p);
kono
parents:
diff changeset
157 };
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 /* Note that we deliberately do not define the 'test' member template. Not
kono
parents:
diff changeset
160 doing so will result in a build-time error for type relationships that have
kono
parents:
diff changeset
161 not been defined, rather than a run-time error. See the discussion above
kono
parents:
diff changeset
162 for when to define this member. */
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 /* This is the generic implementation for casting from one type to another.
kono
parents:
diff changeset
165 Do not use this routine directly; it is an internal function. See the
kono
parents:
diff changeset
166 discussion above for when to define this member. */
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 template <typename T>
kono
parents:
diff changeset
169 template <typename U>
kono
parents:
diff changeset
170 inline T
kono
parents:
diff changeset
171 is_a_helper <T>::cast (U *p)
kono
parents:
diff changeset
172 {
kono
parents:
diff changeset
173 return reinterpret_cast <T> (p);
kono
parents:
diff changeset
174 }
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 /* The public interface. */
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 /* A generic test for a type relationship. See the discussion above for when
kono
parents:
diff changeset
180 to use this function. The question answered is "Is type T a derived type of
kono
parents:
diff changeset
181 type U?". */
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 template <typename T, typename U>
kono
parents:
diff changeset
184 inline bool
kono
parents:
diff changeset
185 is_a (U *p)
kono
parents:
diff changeset
186 {
kono
parents:
diff changeset
187 return is_a_helper<T>::test (p);
kono
parents:
diff changeset
188 }
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 /* A generic conversion from a base type U to a derived type T. See the
kono
parents:
diff changeset
191 discussion above for when to use this function. */
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 template <typename T, typename U>
kono
parents:
diff changeset
194 inline T
kono
parents:
diff changeset
195 as_a (U *p)
kono
parents:
diff changeset
196 {
kono
parents:
diff changeset
197 gcc_checking_assert (is_a <T> (p));
kono
parents:
diff changeset
198 return is_a_helper <T>::cast (p);
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 /* Similar to as_a<>, but where the pointer can be NULL, even if
kono
parents:
diff changeset
202 is_a_helper<T> doesn't check for NULL. */
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 template <typename T, typename U>
kono
parents:
diff changeset
205 inline T
kono
parents:
diff changeset
206 safe_as_a (U *p)
kono
parents:
diff changeset
207 {
kono
parents:
diff changeset
208 if (p)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 gcc_checking_assert (is_a <T> (p));
kono
parents:
diff changeset
211 return is_a_helper <T>::cast (p);
kono
parents:
diff changeset
212 }
kono
parents:
diff changeset
213 else
kono
parents:
diff changeset
214 return NULL;
kono
parents:
diff changeset
215 }
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 /* A generic checked conversion from a base type U to a derived type T. See
kono
parents:
diff changeset
218 the discussion above for when to use this function. */
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 template <typename T, typename U>
kono
parents:
diff changeset
221 inline T
kono
parents:
diff changeset
222 dyn_cast (U *p)
kono
parents:
diff changeset
223 {
kono
parents:
diff changeset
224 if (is_a <T> (p))
kono
parents:
diff changeset
225 return is_a_helper <T>::cast (p);
kono
parents:
diff changeset
226 else
kono
parents:
diff changeset
227 return static_cast <T> (0);
kono
parents:
diff changeset
228 }
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 /* Similar to dyn_cast, except that the pointer may be null. */
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 template <typename T, typename U>
kono
parents:
diff changeset
233 inline T
kono
parents:
diff changeset
234 safe_dyn_cast (U *p)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 return p ? dyn_cast <T> (p) : 0;
kono
parents:
diff changeset
237 }
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 #endif /* GCC_IS_A_H */