All types have corresponding tree nodes. However, you should not assume that there is exactly one tree node corresponding to each type. There are often multiple nodes corresponding to the same type.
For the most part, different kinds of types have different tree codes.
(For example, pointer types use a
POINTER_TYPE code while arrays
ARRAY_TYPE code.) However, pointers to member functions
RECORD_TYPE code. Therefore, when writing a
switch statement that depends on the code associated with a
particular type, you should take care to handle pointers to member
functions under the
RECORD_TYPE case label.
The following functions and macros deal with cv-qualification of types:
A few other macros and functions are usable with all types:
INTEGER_CST. For an incomplete type,
TYPE_DECL) for the type. (Note this macro does not return an
IDENTIFIER_NODE, as you might expect, given its name!) You can look at the
TYPE_DECLto obtain the actual name of the type. The
NULL_TREEfor a type that is not a built-in type, the result of a typedef, or a named class type.
same_type_p: if the
TYPE_CANONICALvalues of the types are equal, the types are equivalent; otherwise, the types are not equivalent. The notion of equivalence for canonical types is the same as the notion of type equivalence in the language itself. For instance,
NULL_TREE, there is no canonical
type for the given type node. In this case, comparison between this
type and any other type requires the compiler to perform a deep,
“structural” comparison to see if the two type nodes have the same
form and properties.
The canonical type for a node is always the most fundamental type in
the equivalence class of types. For instance,
int is its own
canonical type. A typedef
int will have
as its canonical type. Similarly,
I* and a typedef
IP (defined to
I*) will has
int* as their canonical
type. When building a new type node, be sure to set
TYPE_CANONICAL to the appropriate canonical type. If the new
type is a compound type (built from other types), and any of those
other types require structural equality, use
SET_TYPE_STRUCTURAL_EQUALITY to ensure that the new type also
requires structural equality. Finally, if for some reason you cannot
TYPE_CANONICAL will point to the canonical type,
SET_TYPE_STRUCTURAL_EQUALITY to make sure that the new
type–and any type constructed based on it–requires structural
equality. If you suspect that the canonical type system is
miscomparing types, pass
--param verify-canonical-types=1 to
the compiler or configure with
--enable-checking to force the
compiler to verify its canonical-type comparisons against the
structural comparisons; the compiler will then print any warnings if
the canonical types miscompare.
typedeffor the other, or both are
typedefs for the same type. This predicate also holds if the two trees given as input are simply copies of one another; i.e., there is no difference between them at the source level, but, for whatever reason, a duplicate has been made in the representation. You should never use
==(pointer equality) to compare types; always use
Detailed below are the various kinds of types, and the macros that can be used to access them. Although other kinds of types are used elsewhere in G++, the types described here are the only ones that you will encounter while examining the intermediate representation.
long long. This code is not used for enumeration types, nor for the
TYPE_PRECISIONis the number of bits used in the representation, represented as an
unsigned int. (Note that in the general case this is not the same value as
TYPE_SIZE; suppose that there were a 24-bit integer type, but that alignment requirements for the ABI required 32-bit alignment. Then,
TYPE_SIZEwould be an
INTEGER_CSTfor 32, while
TYPE_PRECISIONwould be 24.) The integer type is unsigned if
TYPE_UNSIGNEDholds; otherwise, it is signed.
TYPE_MIN_VALUE is an
INTEGER_CST for the smallest
integer that may be represented by this type. Similarly, the
TYPE_MAX_VALUE is an
INTEGER_CST for the largest integer
that may be represented by this type.
long doubletypes. The number of bits in the floating-point representation is given by
TYPE_PRECISION, as in the
long long _Fract,
long _Accum, and
long long _Accumtypes. The number of bits in the fixed-point representation is given by
TYPE_PRECISION, as in the
INTEGER_TYPEcase. There may be padding bits, fractional bits and integral bits. The number of fractional bits is given by
TYPE_FBIT, and the number of integral bits is given by
TYPE_IBIT. The fixed-point type is unsigned if
TYPE_UNSIGNEDholds; otherwise, it is signed. The fixed-point type is saturating if
TYPE_SATURATINGholds; otherwise, it is not saturating.
__complex__data types. The
TREE_TYPEis the type of the real and imaginary parts.
TYPE_PRECISIONgives (as an
int), the number of bits used to represent the type. If there are no negative enumeration constants,
TYPE_UNSIGNEDwill hold. The minimum and maximum enumeration constants may be obtained with
TYPE_MAX_VALUE, respectively; each of these macros returns an
The actual enumeration constants themselves may be obtained by looking
TYPE_VALUES. This macro will return a
containing the constants. The
TREE_PURPOSE of each node will be
IDENTIFIER_NODE giving the name of the constant; the
TREE_VALUE will be an
INTEGER_CST giving the value
assigned to that constant. These constants will appear in the order in
which they were declared. The
TREE_TYPE of each of these
constants will be the type of enumeration type itself.
TREE_TYPEgives the type to which this type points.
TREE_TYPEgives the type to which this type refers.
TREE_TYPEgives the return type of the function. The
TREE_LISTof the argument types. The
TREE_VALUEof each node in this list is the type of the corresponding argument; the
TREE_PURPOSEis an expression for the default argument value, if any. If the last node in the list is
void_type_node), then functions of this type do not take variable arguments. Otherwise, they do take a variable number of arguments.
Note that in C (but not in C++) a function declared like
is an unprototyped function taking a variable number of arguments; the
TYPE_ARG_TYPES of such a function will be
FUNCTION_TYPE, the return type is given by the
TREE_TYPE. The type of
*this, i.e., the class of which functions of this type are a member, is given by the
TYPE_ARG_TYPESis the parameter list, as for a
FUNCTION_TYPE, and includes the
TREE_TYPEgives the type of the elements in the array. If the array-bound is present in the type, the
TYPE_MAX_VALUEwill be the lower and upper bounds of the array, respectively. The
TYPE_MIN_VALUEwill always be an
INTEGER_CSTfor zero, while the
TYPE_MAX_VALUEwill be one less than the number of elements in the array, i.e., the highest value which may be used to index an element in the array.
classtypes, as well as pointers to member functions and similar constructs in other languages.
TYPE_FIELDScontains the items contained in this type, each of which can be a
TYPE_DECL. You may not make any assumptions about the ordering of the fields in the type or whether one or more of them overlap.
uniontypes. Similar to
RECORD_TYPEexcept that all
TYPE_FIELDstart at bit position zero.
UNION_TYPEexcept that each
DECL_QUALIFIERfield, which contains a boolean expression that indicates whether the field is present in the object. The type will only have one field, so each field's
DECL_QUALIFIERis only evaluated if none of the expressions in the previous fields in
TYPE_FIELDSare nonzero. Normally these expressions will reference a field in the outer object using a
TREE_TYPEis the type of
There are variables whose values represent some of the basic types. These include: