/* Dynamic testing for abstract is-a relationships.
- Copyright (C) 2012 Free Software Foundation, Inc.
+ Copyright (C) 2012-2019 Free Software Foundation, Inc.
Contributed by Lawrence Crowl.
This file is part of GCC.
Tests whether the pointer actually points to a more derived TYPE.
- Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr. You can test
+ Suppose you have a symtab_node *ptr, AKA symtab_node *ptr. You can test
whether it points to a 'derived' cgraph_node as follows.
- if (is_a <cgraph_node> (ptr))
+ if (is_a <cgraph_node *> (ptr))
....
-TYPE *as_a <TYPE> (pointer)
+TYPE as_a <TYPE> (pointer)
- Converts pointer to a TYPE*.
+ Converts pointer to a TYPE.
You can just assume that it is such a node.
- do_something_with (as_a <cgraph_node> *ptr);
+ do_something_with (as_a <cgraph_node *> *ptr);
-TYPE *dyn_cast <TYPE> (pointer)
+TYPE safe_as_a <TYPE> (pointer)
- Converts pointer to TYPE* if and only if "is_a <TYPE> pointer". Otherwise,
+ Like as_a <TYPE> (pointer), but where pointer could be NULL. This
+ adds a check against NULL where the regular is_a_helper hook for TYPE
+ assumes non-NULL.
+
+ do_something_with (safe_as_a <cgraph_node *> *ptr);
+
+TYPE dyn_cast <TYPE> (pointer)
+
+ Converts pointer to TYPE if and only if "is_a <TYPE> pointer". Otherwise,
returns NULL. This function is essentially a checked down cast.
This functions reduce compile time and increase type safety when treating a
You can test and obtain a pointer to the 'derived' type in one indivisible
operation.
- if (cgraph_node *cptr = dyn_cast <cgraph_node> (ptr))
+ if (cgraph_node *cptr = dyn_cast <cgraph_node *> (ptr))
....
As an example, the code change is from
to
- if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
+ if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
{
....
}
becomes
- varpool_node *vnode = dyn_cast <varpool_node> (node);
+ varpool_node *vnode = dyn_cast <varpool_node *> (node);
if (vnode && vnode->finalized)
varpool_analyze_node (vnode);
Note that we have converted two sets of assertions in the calls to varpool
into safe and efficient use of a variable.
+TYPE safe_dyn_cast <TYPE> (pointer)
+
+ Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
+ and returns null results for them.
+
If you use these functions and get a 'inline function not defined' or a
'missing symbol' error message for 'is_a_helper<....>::test', it means that
template <>
template <>
inline bool
- is_a_helper <cgraph_node>::test (symtab_node_def *p)
+ is_a_helper <cgraph_node *>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_FUNCTION;
+ return p->type == SYMTAB_FUNCTION;
}
If a simple reinterpret_cast between the pointer types is incorrect, then you
template <>
template <>
inline bool
- is_a_helper <cgraph_node>::cast (symtab_node_def *p)
+ is_a_helper <cgraph_node *>::cast (symtab_node *p)
{
return &p->x_function;
}
template <typename U>
static inline bool test (U *p);
template <typename U>
- static inline T *cast (U *p);
+ static inline T cast (U *p);
};
/* Note that we deliberately do not define the 'test' member template. Not
template <typename T>
template <typename U>
-inline T *
+inline T
is_a_helper <T>::cast (U *p)
{
- return reinterpret_cast <T *> (p);
+ return reinterpret_cast <T> (p);
}
discussion above for when to use this function. */
template <typename T, typename U>
-inline T *
+inline T
as_a (U *p)
{
- gcc_assert (is_a <T> (p));
+ gcc_checking_assert (is_a <T> (p));
return is_a_helper <T>::cast (p);
}
+/* Similar to as_a<>, but where the pointer can be NULL, even if
+ is_a_helper<T> doesn't check for NULL. */
+
+template <typename T, typename U>
+inline T
+safe_as_a (U *p)
+{
+ if (p)
+ {
+ gcc_checking_assert (is_a <T> (p));
+ return is_a_helper <T>::cast (p);
+ }
+ else
+ return NULL;
+}
+
/* A generic checked conversion from a base type U to a derived type T. See
the discussion above for when to use this function. */
template <typename T, typename U>
-inline T *
+inline T
dyn_cast (U *p)
{
if (is_a <T> (p))
return is_a_helper <T>::cast (p);
else
- return static_cast <T *> (0);
+ return static_cast <T> (0);
+}
+
+/* Similar to dyn_cast, except that the pointer may be null. */
+
+template <typename T, typename U>
+inline T
+safe_dyn_cast (U *p)
+{
+ return p ? dyn_cast <T> (p) : 0;
}
#endif /* GCC_IS_A_H */