Types#
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
use an ARRAY_TYPE
code.) However, pointers to member functions
use the 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:
- TYPE_MAIN_VARIANT#
This macro returns the unqualified version of a type. It may be applied to an unqualified type, but it is not always the identity function in that case.
A few other macros and functions are usable with all types:
- TYPE_SIZE#
The number of bits required to represent the type, represented as an
INTEGER_CST
. For an incomplete type,TYPE_SIZE
will beNULL_TREE
.
- TYPE_ALIGN#
The alignment of the type, in bits, represented as an
int
.
- TYPE_NAME#
This macro returns a declaration (in the form of a
TYPE_DECL
) for the type. (Note this macro does not return anIDENTIFIER_NODE
, as you might expect, given its name!) You can look at theDECL_NAME
of theTYPE_DECL
to obtain the actual name of the type. TheTYPE_NAME
will beNULL_TREE
for a type that is not a built-in type, the result of a typedef, or a named class type.
- TYPE_CANONICAL#
This macro returns the ‘canonical’ type for the given type node. Canonical types are used to improve performance in the C++ and Objective-C++ front ends by allowing efficient comparison between two type nodes in
same_type_p
: if theTYPE_CANONICAL
values 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,When
TYPE_CANONICAL
isNULL_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 typedefI
ofint
will haveint
as its canonical type. Similarly,I*``and a typedef ``IP``(defined to ``I*
) will hasint*
as their canonical type. When building a new type node, be sure to setTYPE_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, useSET_TYPE_STRUCTURAL_EQUALITY
to ensure that the new type also requires structural equality. Finally, if for some reason you cannot guarantee thatTYPE_CANONICAL
will point to the canonical type, useSET_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.
- TYPE_STRUCTURAL_EQUALITY_P#
This predicate holds when the node requires structural equality checks, e.g., when
TYPE_CANONICAL
isNULL_TREE
.
- SET_TYPE_STRUCTURAL_EQUALITY#
This macro states that the type node it is given requires structural equality checks, e.g., it sets
TYPE_CANONICAL
toNULL_TREE
.
same_type_p
This predicate takes two types as input, and holds if they are the same type. For example, if one type is a
typedef
for the other, or both aretypedef
s 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 usesame_type_p
instead.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.
- VOID_TYPE#
Used to represent the
void
type.
- INTEGER_TYPE#
Used to represent the various integral types, including
char
,short
,int
,long
, andlong long
. This code is not used for enumeration types, nor for thebool
type. TheTYPE_PRECISION
is the number of bits used in the representation, represented as anunsigned int
. (Note that in the general case this is not the same value asTYPE_SIZE
; suppose that there were a 24-bit integer type, but that alignment requirements for the ABI required 32-bit alignment. Then,TYPE_SIZE
would be anINTEGER_CST
for 32, whileTYPE_PRECISION
would be 24.) The integer type is unsigned ifTYPE_UNSIGNED
holds; otherwise, it is signed.The
TYPE_MIN_VALUE
is anINTEGER_CST
for the smallest integer that may be represented by this type. Similarly, theTYPE_MAX_VALUE
is anINTEGER_CST
for the largest integer that may be represented by this type.
- REAL_TYPE#
Used to represent the
float
,double
, andlong double
types. The number of bits in the floating-point representation is given byTYPE_PRECISION
, as in theINTEGER_TYPE
case.
- FIXED_POINT_TYPE#
Used to represent the
short _Fract
,_Fract
,long _Fract
,long long _Fract
,short _Accum
,_Accum
,long _Accum
, andlong long _Accum
types. The number of bits in the fixed-point representation is given byTYPE_PRECISION
, as in theINTEGER_TYPE
case. There may be padding bits, fractional bits and integral bits. The number of fractional bits is given byTYPE_FBIT
, and the number of integral bits is given byTYPE_IBIT
. The fixed-point type is unsigned ifTYPE_UNSIGNED
holds; otherwise, it is signed. The fixed-point type is saturating ifTYPE_SATURATING
holds; otherwise, it is not saturating.
- COMPLEX_TYPE#
Used to represent GCC built-in
__complex__
data types. TheTREE_TYPE
is the type of the real and imaginary parts.
- ENUMERAL_TYPE#
Used to represent an enumeration type. The
TYPE_PRECISION
gives (as anint
), the number of bits used to represent the type. If there are no negative enumeration constants,TYPE_UNSIGNED
will hold. The minimum and maximum enumeration constants may be obtained withTYPE_MIN_VALUE
andTYPE_MAX_VALUE
, respectively; each of these macros returns anINTEGER_CST
.The actual enumeration constants themselves may be obtained by looking at the
TYPE_VALUES
. This macro will return aTREE_LIST
, containing the constants. TheTREE_PURPOSE
of each node will be anIDENTIFIER_NODE
giving the name of the constant; theTREE_VALUE
will be anINTEGER_CST
giving the value assigned to that constant. These constants will appear in the order in which they were declared. TheTREE_TYPE
of each of these constants will be the type of enumeration type itself.
- OPAQUE_TYPE#
Used for things that have a
MODE_OPAQUE
mode class in the backend. Opaque types have a size and precision, and can be held in memory or registers. They are used when we do not want the compiler to make assumptions about the availability of other operations as would happen with integer types.
- BOOLEAN_TYPE#
Used to represent the
bool
type.
- POINTER_TYPE#
Used to represent pointer types, and pointer to data member types. The
TREE_TYPE
gives the type to which this type points.
- REFERENCE_TYPE#
Used to represent reference types. The
TREE_TYPE
gives the type to which this type refers.
- FUNCTION_TYPE#
Used to represent the type of non-member functions and of static member functions. The
TREE_TYPE
gives the return type of the function. TheTYPE_ARG_TYPES
are aTREE_LIST
of the argument types. TheTREE_VALUE
of each node in this list is the type of the corresponding argument; theTREE_PURPOSE
is an expression for the default argument value, if any. If the last node in the list isvoid_list_node
(aTREE_LIST
node whoseTREE_VALUE
is thevoid_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
void f()
is an unprototyped function taking a variable number of arguments; theTYPE_ARG_TYPES
of such a function will beNULL
.
- METHOD_TYPE#
Used to represent the type of a non-static member function. Like a
FUNCTION_TYPE
, the return type is given by theTREE_TYPE
. The type of*this
, i.e., the class of which functions of this type are a member, is given by theTYPE_METHOD_BASETYPE
. TheTYPE_ARG_TYPES
is the parameter list, as for aFUNCTION_TYPE
, and includes thethis
argument.
- ARRAY_TYPE#
Used to represent array types. The
TREE_TYPE
gives the type of the elements in the array. If the array-bound is present in the type, theTYPE_DOMAIN
is anINTEGER_TYPE
whoseTYPE_MIN_VALUE
andTYPE_MAX_VALUE
will be the lower and upper bounds of the array, respectively. TheTYPE_MIN_VALUE
will always be anINTEGER_CST
for zero, while theTYPE_MAX_VALUE
will 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.
- RECORD_TYPE#
Used to represent
struct
andclass
types, as well as pointers to member functions and similar constructs in other languages.TYPE_FIELDS
contains the items contained in this type, each of which can be aFIELD_DECL
,VAR_DECL
,CONST_DECL
, orTYPE_DECL
. You may not make any assumptions about the ordering of the fields in the type or whether one or more of them overlap.
- UNION_TYPE#
Used to represent
union
types. Similar toRECORD_TYPE
except that allFIELD_DECL
nodes inTYPE_FIELD
start at bit position zero.
- QUAL_UNION_TYPE#
Used to represent part of a variant record in Ada. Similar to
UNION_TYPE
except that eachFIELD_DECL
has aDECL_QUALIFIER
field, 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’sDECL_QUALIFIER
is only evaluated if none of the expressions in the previous fields inTYPE_FIELDS
are nonzero. Normally these expressions will reference a field in the outer object using aPLACEHOLDER_EXPR
.
- LANG_TYPE#
This node is used to represent a language-specific type. The front end must handle it.
- OFFSET_TYPE#
This node is used to represent a pointer-to-data member. For a data member
X::m
theTYPE_OFFSET_BASETYPE
isX
and theTREE_TYPE
is the type ofm
.
There are variables whose values represent some of the basic types. These include:
void_type_node
A node for
void
.integer_type_node
A node for
int
.unsigned_type_node.
A node for
unsigned int
.char_type_node.
A node for
char
.It may sometimes be useful to compare one of these variables with a type in hand, using
same_type_p
.