template<typename T>
struct is_a_helper< T >
Dynamic testing for abstract is-a relationships. Copyright (C) 2012-2013 Free Software Foundation, Inc. Contributed by Lawrence Crowl.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/. This header generic type query and conversion functions.
USING THE GENERIC TYPE FACILITY
The user functions are:
bool is_a <TYPE> (pointer)
Tests whether the pointer actually points to a more derived TYPE.
Suppose you have a symtab_node_base *ptr, AKA symtab_node ptr. You can test
whether it points to a 'derived' cgraph_node as follows.
if (is_a <cgraph_node> (ptr))
....
TYPE *as_a <TYPE> (pointer)
Converts pointer to a TYPE*.
You can just assume that it is such a node.
do_something_with (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
generic item as a more specific item.
You can test and obtain a pointer to the 'derived' type in one indivisible
operation.
if (cgraph_node *cptr = dyn_cast <cgraph_node> (ptr))
....
As an example, the code change is from
if (symtab_function_p (node))
{
struct cgraph_node *cnode = cgraph (node);
....
}
to
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
{
....
}
The necessary conditional test defines a variable that holds a known good
pointer to the specific item and avoids subsequent conversion calls and
the assertion checks that may come with them.
When, the property test is embedded within a larger condition, the
variable declaration gets pulled out of the condition. (This approach
leaves some room for using the variable inappropriately.)
if (symtab_variable_p (node) && varpool (node)->finalized)
varpool_analyze_node (varpool (node));
becomes
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.
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 the connection between the types has not been made. See below.
EXTENDING THE GENERIC TYPE FACILITY
Each connection between types must be made by defining a specialization of the template member function 'test' of the template class 'is_a_helper'. For example,
template <> template <> inline bool is_a_helper <cgraph_node>::test (symtab_node_base *p) { return p->type == SYMTAB_FUNCTION; }
If a simple reinterpret_cast between the pointer types is incorrect, then you must also specialize the template member function 'cast'. Failure to do so when needed may result in a crash. For example,
template <> template <> inline bool is_a_helper <cgraph_node>::cast (symtab_node_base *p) { return &p->x_function; } A generic type conversion internal helper class.