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