//===- Type.h - C Language Family Type Representation -----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// C Language Family Type Representation /// /// This file defines the clang::Type interface and subclasses, used to /// represent types for languages in the C family. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_TYPE_H #define LLVM_CLANG_AST_TYPE_H #include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PointerAuthOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/TrailingObjects.h" #include "llvm/Support/type_traits.h" #include <bitset> #include <cassert> #include <cstddef> #include <cstdint> #include <cstring> #include <optional> #include <string> #include <type_traits> #include <utility> namespace clang { class BTFTypeTagAttr; class ExtQuals; class QualType; class ConceptDecl; class ValueDecl; class TagDecl; class TemplateParameterList; class Type; enum { … }; namespace serialization { template <class T> class AbstractTypeReader; template <class T> class AbstractTypeWriter; } } // namespace clang namespace llvm { template <typename T> struct PointerLikeTypeTraits; template<> struct PointerLikeTypeTraits< ::clang::Type*> { … }; template<> struct PointerLikeTypeTraits< ::clang::ExtQuals*> { … }; } // namespace llvm namespace clang { class ASTContext; template <typename> class CanQual; class CXXRecordDecl; class DeclContext; class EnumDecl; class Expr; class ExtQualsTypeCommonBase; class FunctionDecl; class FunctionEffectsRef; class FunctionEffectKindSet; class FunctionEffectSet; class IdentifierInfo; class NamedDecl; class ObjCInterfaceDecl; class ObjCProtocolDecl; class ObjCTypeParamDecl; struct PrintingPolicy; class RecordDecl; class Stmt; class TagDecl; class TemplateArgument; class TemplateArgumentListInfo; class TemplateArgumentLoc; class TemplateTypeParmDecl; class TypedefNameDecl; class UnresolvedUsingTypenameDecl; class UsingShadowDecl; CanQualType; // Provide forward declarations for all of the *Type classes. #define TYPE … #include "clang/AST/TypeNodes.inc" /// Pointer-authentication qualifiers. class PointerAuthQualifier { … }; /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict /// * MS: __unaligned /// * Embedded C (TR18037): address spaces /// * Objective C: the GC attributes (none, weak, or strong) class Qualifiers { … }; class QualifiersAndAtomic { … }; /// A std::pair-like structure for storing a qualified type split /// into its local qualifiers and its locally-unqualified type. struct SplitQualType { … }; /// The kind of type we are substituting Objective-C type arguments into. /// /// The kind of substitution affects the replacement of type parameters when /// no concrete type information is provided, e.g., when dealing with an /// unspecialized type. enum class ObjCSubstitutionContext { … }; /// The kind of 'typeof' expression we're after. enum class TypeOfKind : uint8_t { … }; /// A (possibly-)qualified type. /// /// For efficiency, we don't store CV-qualified types as nodes on their /// own: instead each reference to a type stores the qualifiers. This /// greatly reduces the number of nodes we need to allocate for types (for /// example we only need one for 'int', 'const int', 'volatile int', /// 'const volatile int', etc). /// /// As an added efficiency bonus, instead of making this a pair, we /// just store the two bits we care about in the low bits of the /// pointer. To handle the packing/unpacking, we make QualType be a /// simple wrapper class that acts like a smart pointer. A third bit /// indicates whether there are extended qualifiers present, in which /// case the pointer points to a special structure. class QualType { … }; raw_ostream &operator<<(raw_ostream &OS, QualType QT); } // namespace clang namespace llvm { /// Implement simplify_type for QualType, so that we can dyn_cast from QualType /// to a specific Type class. template<> struct simplify_type< ::clang::QualType> { … }; // Teach SmallPtrSet that QualType is "basically a pointer". template<> struct PointerLikeTypeTraits<clang::QualType> { … }; } // namespace llvm namespace clang { /// Base class that is common to both the \c ExtQuals and \c Type /// classes, which allows \c QualType to access the common fields between the /// two. class ExtQualsTypeCommonBase { … }; /// We can encode up to four bits in the low bits of a /// type pointer, but there are many more type qualifiers that we want /// to be able to apply to an arbitrary type. Therefore we have this /// struct, intended to be heap-allocated and used by QualType to /// store qualifiers. /// /// The current design tags the 'const', 'restrict', and 'volatile' qualifiers /// in three low bits on the QualType pointer; a fourth bit records whether /// the pointer is an ExtQuals node. The extended qualifiers (address spaces, /// Objective-C GC attributes) are much more rare. class alignas(TypeAlignment) ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { … }; /// The kind of C++11 ref-qualifier associated with a function type. /// This determines whether a member function's "this" object can be an /// lvalue, rvalue, or neither. enum RefQualifierKind { … }; /// Which keyword(s) were used to create an AutoType. enum class AutoTypeKeyword { … }; enum class ArraySizeModifier; enum class ElaboratedTypeKeyword; enum class VectorKind; /// The base class of the type hierarchy. /// /// A central concept with types is that each type always has a canonical /// type. A canonical type is the type with any typedef names stripped out /// of it or the types it references. For example, consider: /// /// typedef int foo; /// typedef foo* bar; /// 'int *' 'foo *' 'bar' /// /// There will be a Type object created for 'int'. Since int is canonical, its /// CanonicalType pointer points to itself. There is also a Type for 'foo' (a /// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next /// there is a PointerType that represents 'int*', which, like 'int', is /// canonical. Finally, there is a PointerType type for 'foo*' whose canonical /// type is 'int*', and there is a TypedefType for 'bar', whose canonical type /// is also 'int*'. /// /// Non-canonical types are useful for emitting diagnostics, without losing /// information about typedefs being used. Canonical types are useful for type /// comparisons (they allow by-pointer equality tests) and useful for reasoning /// about whether something has a particular form (e.g. is a function type), /// because they implicitly, recursively, strip all typedefs out of a type. /// /// Types, once created, are immutable. /// class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { … }; /// This will check for a TypedefType by removing any existing sugar /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; template <> const UsingType *Type::getAs() const; /// This will check for a TemplateSpecializationType by removing any /// existing sugar until it reaches a TemplateSpecializationType or a /// non-sugared type. template <> const TemplateSpecializationType *Type::getAs() const; /// This will check for an AttributedType by removing any existing sugar /// until it reaches an AttributedType or a non-sugared type. template <> const AttributedType *Type::getAs() const; /// This will check for a BoundsAttributedType by removing any existing /// sugar until it reaches an BoundsAttributedType or a non-sugared type. template <> const BoundsAttributedType *Type::getAs() const; /// This will check for a CountAttributedType by removing any existing /// sugar until it reaches an CountAttributedType or a non-sugared type. template <> const CountAttributedType *Type::getAs() const; // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. #define TYPE … #define LEAF_TYPE … #include "clang/AST/TypeNodes.inc" /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { … }; /// Complex values, per C99 6.2.5p11. This supports the C99 complex /// types (_Complex float etc) as well as the GCC integer complex extensions. class ComplexType : public Type, public llvm::FoldingSetNode { … }; /// Sugar for parentheses used when specifying types. class ParenType : public Type, public llvm::FoldingSetNode { … }; /// PointerType - C99 6.7.5.1 - Pointer Declarators. class PointerType : public Type, public llvm::FoldingSetNode { … }; /// [BoundsSafety] Represents information of declarations referenced by the /// arguments of the `counted_by` attribute and the likes. class TypeCoupledDeclRefInfo { … }; /// [BoundsSafety] Represents a parent type class for CountAttributedType and /// similar sugar types that will be introduced to represent a type with a /// bounds attribute. /// /// Provides a common interface to navigate declarations referred to by the /// bounds expression. class BoundsAttributedType : public Type, public llvm::FoldingSetNode { … }; /// Represents a sugar type with `__counted_by` or `__sized_by` annotations, /// including their `_or_null` variants. class CountAttributedType final : public BoundsAttributedType, public llvm::TrailingObjects<CountAttributedType, TypeCoupledDeclRefInfo> { … }; /// Represents a type which was implicitly adjusted by the semantic /// engine for arbitrary reasons. For example, array and function types can /// decay, and function types can have their calling conventions adjusted. class AdjustedType : public Type, public llvm::FoldingSetNode { … }; /// Represents a pointer type decayed from an array or function type. class DecayedType : public AdjustedType { … }; /// Pointer to a block type. /// This type is to represent types syntactically represented as /// "void (^)(int)", etc. Pointee is required to always be a function type. class BlockPointerType : public Type, public llvm::FoldingSetNode { … }; /// Base for LValueReferenceType and RValueReferenceType class ReferenceType : public Type, public llvm::FoldingSetNode { … }; /// An lvalue reference type, per C++11 [dcl.ref]. class LValueReferenceType : public ReferenceType { … }; /// An rvalue reference type, per C++11 [dcl.ref]. class RValueReferenceType : public ReferenceType { … }; /// A pointer to member type per C++ 8.3.3 - Pointers to members. /// /// This includes both pointers to data members and pointer to member functions. class MemberPointerType : public Type, public llvm::FoldingSetNode { … }; /// Capture whether this is a normal array (e.g. int X[4]) /// an array with a static size (e.g. int X[static 4]), or an array /// with a star size (e.g. int X[*]). /// 'static' is only allowed on function parameters. enum class ArraySizeModifier { … }; /// Represents an array type, per C99 6.7.5.2 - Array Declarators. class ArrayType : public Type, public llvm::FoldingSetNode { … }; /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. class ConstantArrayType : public ArrayType { … }; /// Represents a constant array type that does not decay to a pointer when used /// as a function parameter. class ArrayParameterType : public ConstantArrayType { … }; /// Represents a C array with an unspecified size. For example 'int A[]' has /// an IncompleteArrayType where the element type is 'int' and the size is /// unspecified. class IncompleteArrayType : public ArrayType { … }; /// Represents a C array with a specified size that is not an /// integer-constant-expression. For example, 'int s[x+foo()]'. /// Since the size expression is an arbitrary expression, we store it as such. /// /// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and /// should not be: two lexically equivalent variable array types could mean /// different things, for example, these variables do not have the same type /// dynamically: /// /// void foo(int x) { /// int Y[x]; /// ++x; /// int Z[x]; /// } class VariableArrayType : public ArrayType { … }; /// Represents an array type in C++ whose size is a value-dependent expression. /// /// For example: /// \code /// template<typename T, int Size> /// class array { /// T data[Size]; /// }; /// \endcode /// /// For these types, we won't actually know what the array bound is /// until template instantiation occurs, at which point this will /// become either a ConstantArrayType or a VariableArrayType. class DependentSizedArrayType : public ArrayType { … }; /// Represents an extended address space qualifier where the input address space /// value is dependent. Non-dependent address spaces are not represented with a /// special Type subclass; they are stored on an ExtQuals node as part of a QualType. /// /// For example: /// \code /// template<typename T, int AddrSpace> /// class AddressSpace { /// typedef T __attribute__((address_space(AddrSpace))) type; /// } /// \endcode class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { … }; /// Represents an extended vector type where either the type or size is /// dependent. /// /// For example: /// \code /// template<typename T, int Size> /// class vector { /// typedef T __attribute__((ext_vector_type(Size))) type; /// } /// \endcode class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { … }; enum class VectorKind { … }; /// Represents a GCC generic vector type. This type is created using /// __attribute__((vector_size(n)), where "n" specifies the vector size in /// bytes; or from an Altivec __vector or vector declaration. /// Since the constructor takes the number of vector elements, the /// client is responsible for converting the size into the number of elements. class VectorType : public Type, public llvm::FoldingSetNode { … }; /// Represents a vector type where either the type or size is dependent. //// /// For example: /// \code /// template<typename T, int Size> /// class vector { /// typedef T __attribute__((vector_size(Size))) type; /// } /// \endcode class DependentVectorType : public Type, public llvm::FoldingSetNode { … }; /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This /// class enables syntactic extensions, like Vector Components for accessing /// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL /// Shading Language). class ExtVectorType : public VectorType { … }; /// Represents a matrix type, as defined in the Matrix Types clang extensions. /// __attribute__((matrix_type(rows, columns))), where "rows" specifies /// number of rows and "columns" specifies the number of columns. class MatrixType : public Type, public llvm::FoldingSetNode { … }; /// Represents a concrete matrix type with constant number of rows and columns class ConstantMatrixType final : public MatrixType { … }; /// Represents a matrix type where the type and the number of rows and columns /// is dependent on a template. class DependentSizedMatrixType final : public MatrixType { … }; /// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base /// class of FunctionNoProtoType and FunctionProtoType. class FunctionType : public Type { … }; /// Represents a K&R-style 'int foo()' function, which has /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { … }; // ------------------------------------------------------------------------------ /// Represents an abstract function effect, using just an enumeration describing /// its kind. class FunctionEffect { … }; /// Wrap a function effect's condition expression in another struct so /// that FunctionProtoType's TrailingObjects can treat it separately. class EffectConditionExpr { … }; /// A FunctionEffect plus a potential boolean expression determining whether /// the effect is declared (e.g. nonblocking(expr)). Generally the condition /// expression when present, is dependent. struct FunctionEffectWithCondition { … }; /// Support iteration in parallel through a pair of FunctionEffect and /// EffectConditionExpr containers. template <typename Container> class FunctionEffectIterator { … }; /// An immutable set of FunctionEffects and possibly conditions attached to /// them. The effects and conditions reside in memory not managed by this object /// (typically, trailing objects in FunctionProtoType, or borrowed references /// from a FunctionEffectSet). /// /// Invariants: /// - there is never more than one instance of any given effect. /// - the array of conditions is either empty or has the same size as the /// array of effects. /// - some conditions may be null expressions; each condition pertains to /// the effect at the same array index. /// /// Also, if there are any conditions, at least one of those expressions will be /// dependent, but this is only asserted in the constructor of /// FunctionProtoType. /// /// See also FunctionEffectSet, in Sema, which provides a mutable set. class FunctionEffectsRef { … }; /// A mutable set of FunctionEffect::Kind. class FunctionEffectKindSet { … }; /// A mutable set of FunctionEffects and possibly conditions attached to them. /// Used to compare and merge effects on declarations. /// /// Has the same invariants as FunctionEffectsRef. class FunctionEffectSet { … }; /// Represents a prototype with parameter type info, e.g. /// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no /// parameters, not as having a single void parameter. Such a type can have /// an exception specification, but this specification is not part of the /// canonical type. FunctionProtoType has several trailing objects, some of /// which optional. For more information about the trailing objects see /// the first comment inside FunctionProtoType. class FunctionProtoType final : public FunctionType, public llvm::FoldingSetNode, private llvm::TrailingObjects< FunctionProtoType, QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields, FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType, Expr *, FunctionDecl *, FunctionType::ExtParameterInfo, Qualifiers, FunctionEffect, EffectConditionExpr> { … }; /// Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. /// using typename Base<T>::foo; /// /// Template instantiation turns these into the underlying type. class UnresolvedUsingType : public Type { … }; class UsingType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<UsingType, QualType> { … }; class TypedefType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<TypedefType, QualType> { … }; /// Sugar type that represents a type that was qualified by a qualifier written /// as a macro invocation. class MacroQualifiedType : public Type { … }; /// Represents a `typeof` (or __typeof__) expression (a C23 feature and GCC /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { … }; /// Internal representation of canonical, dependent /// `typeof(expr)` types. /// /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances /// of this class via TypeOfExprType nodes. class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { … }; /// Represents `typeof(type)`, a C23 feature and GCC extension, or /// `typeof_unqual(type), a C23 feature. class TypeOfType : public Type { … }; /// Represents the type `decltype(expr)` (C++11). class DecltypeType : public Type { … }; /// Internal representation of canonical, dependent /// decltype(expr) types. /// /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances /// of this class via DecltypeType nodes. class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { … }; class PackIndexingType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<PackIndexingType, QualType> { … }; /// A unary type transform, which is a type constructed from another. class UnaryTransformType : public Type { … }; /// Internal representation of canonical, dependent /// __underlying_type(type) types. /// /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances /// of this class via UnaryTransformType nodes. class DependentUnaryTransformType : public UnaryTransformType, public llvm::FoldingSetNode { … }; class TagType : public Type { … }; /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { … }; /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { … }; /// An attributed type is a type to which a type attribute has been applied. /// /// The "modified type" is the fully-sugared type to which the attributed /// type was applied; generally it is not canonically equivalent to the /// attributed type. The "equivalent type" is the minimally-desugared type /// which the type is canonically equivalent to. /// /// For example, in the following attributed type: /// int32_t __attribute__((vector_size(16))) /// - the modified type is the TypedefType for int32_t /// - the equivalent type is VectorType(16, int32_t) /// - the canonical type is VectorType(16, int) class AttributedType : public Type, public llvm::FoldingSetNode { … }; class BTFTagAttributedType : public Type, public llvm::FoldingSetNode { … }; class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode { … }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { … }; /// Represents the result of substituting a type for a template /// type parameter. /// /// Within an instantiated template, all template type parameters have /// been replaced with these. They are used solely to record that a /// type was originally written as a template type parameter; /// therefore they are never canonical. class SubstTemplateTypeParmType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<SubstTemplateTypeParmType, QualType> { … }; /// Represents the result of substituting a set of types for a template /// type parameter pack. /// /// When a pack expansion in the source code contains multiple parameter packs /// and those parameter packs correspond to different levels of template /// parameter lists, this type node is used to represent a template type /// parameter pack from an outer level, which has already had its argument pack /// substituted but that still lives within a pack expansion that itself /// could not be instantiated. When actually performing a substitution into /// that pack expansion (e.g., when all template parameters have corresponding /// arguments), this type will be replaced with the \c SubstTemplateTypeParmType /// at the current pack substitution index. class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { … }; /// Common base class for placeholders for types that get replaced by /// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced /// class template types, and constrained type names. /// /// These types are usually a placeholder for a deduced type. However, before /// the initializer is attached, or (usually) if the initializer is /// type-dependent, there is no deduced type and the type is canonical. In /// the latter case, it is also a dependent type. class DeducedType : public Type { … }; /// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained /// by a type-constraint. class AutoType : public DeducedType, public llvm::FoldingSetNode { … }; /// Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public DeducedType, public llvm::FoldingSetNode { … }; /// Represents a type template specialization; the template /// must be a class template, a type alias template, or a template /// template parameter. A template which cannot be resolved to one of /// these, e.g. because it is written with a dependent scope /// specifier, is instead represented as a /// @c DependentTemplateSpecializationType. /// /// A non-dependent template specialization type is always "sugar", /// typically for a \c RecordType. For example, a class template /// specialization type of \c vector<int> will refer to a tag type for /// the instantiation \c std::vector<int, std::allocator<int>> /// /// Template specializations are dependent if either the template or /// any of the template arguments are dependent, in which case the /// type may also be canonical. /// /// Instances of this type are allocated with a trailing array of /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { … }; /// Print a template argument list, including the '<' and '>' /// enclosing the template arguments. void printTemplateArgumentList(raw_ostream &OS, ArrayRef<TemplateArgument> Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL = nullptr); void printTemplateArgumentList(raw_ostream &OS, ArrayRef<TemplateArgumentLoc> Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL = nullptr); void printTemplateArgumentList(raw_ostream &OS, const TemplateArgumentListInfo &Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL = nullptr); /// Make a best-effort determination of whether the type T can be produced by /// substituting Args into the default argument of Param. bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg, const NamedDecl *Param, ArrayRef<TemplateArgument> Args, unsigned Depth); /// The injected class name of a C++ class template or class /// template partial specialization. Used to record that a type was /// spelled with a bare identifier rather than as a template-id; the /// equivalent for non-templated classes is just RecordType. /// /// Injected class name types are always dependent. Template /// instantiation turns these into RecordTypes. /// /// Injected class name types are always canonical. This works /// because it is impossible to compare an injected class name type /// with the corresponding non-injected template type, for the same /// reason that it is impossible to directly compare template /// parameters from different dependent contexts: injected class name /// types can only occur within the scope of a particular templated /// declaration, and within that scope every template specialization /// will canonicalize to the injected class name (when appropriate /// according to the rules of the language). class InjectedClassNameType : public Type { … }; /// The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. enum class ElaboratedTypeKeyword { … }; /// The kind of a tag type. enum class TagTypeKind { … }; /// A helper class for Type nodes having an ElaboratedTypeKeyword. /// The keyword in stored in the free bits of the base class. /// Also provides a few static helpers for converting and printing /// elaborated type keyword and tag type kind enumerations. class TypeWithKeyword : public Type { … }; /// Represents a type that was referred to using an elaborated type /// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, /// or both. /// /// This type is used to keep track of a type name as written in the /// source code, including tag keywords and any nested-name-specifiers. /// The type itself is always "sugar", used to express what was written /// in the source code but containing no additional semantic information. class ElaboratedType final : public TypeWithKeyword, public llvm::FoldingSetNode, private llvm::TrailingObjects<ElaboratedType, TagDecl *> { … }; /// Represents a qualified type name for which the type name is /// dependent. /// /// DependentNameType represents a class of dependent types that involve a /// possibly dependent nested-name-specifier (e.g., "T::") followed by a /// name of a type. The DependentNameType may start with a "typename" (for a /// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). /// Typically the nested-name-specifier is dependent, but in MSVC compatibility /// mode, this type is used with non-dependent names to delay name lookup until /// instantiation. class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { … }; /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A<T>::template B<T> class DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { … }; /// Represents a pack expansion of types. /// /// Pack expansions are part of C++11 variadic templates. A pack /// expansion contains a pattern, which itself contains one or more /// "unexpanded" parameter packs. When instantiated, a pack expansion /// produces a series of types, each instantiated from the pattern of /// the expansion, where the Ith instantiation of the pattern uses the /// Ith arguments bound to each of the unexpanded parameter packs. The /// pack expansion is considered to "expand" these unexpanded /// parameter packs. /// /// \code /// template<typename ...Types> struct tuple; /// /// template<typename ...Types> /// struct tuple_of_references { /// typedef tuple<Types&...> type; /// }; /// \endcode /// /// Here, the pack expansion \c Types&... is represented via a /// PackExpansionType whose pattern is Types&. class PackExpansionType : public Type, public llvm::FoldingSetNode { … }; /// This class wraps the list of protocol qualifiers. For types that can /// take ObjC protocol qualifers, they can subclass this class. template <class T> class ObjCProtocolQualifiers { … }; /// Represents a type parameter type in Objective C. It can take /// a list of protocols. class ObjCTypeParamType : public Type, public ObjCProtocolQualifiers<ObjCTypeParamType>, public llvm::FoldingSetNode { … }; /// Represents a class type in Objective C. /// /// Every Objective C type is a combination of a base type, a set of /// type arguments (optional, for parameterized classes) and a list of /// protocols. /// /// Given the following declarations: /// \code /// \@class C<T>; /// \@protocol P; /// \endcode /// /// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType /// with base C and no protocols. /// /// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P]. /// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no /// protocol list. /// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*', /// and protocol list [P]. /// /// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose /// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType /// and no protocols. /// /// 'id<P>' is an ObjCObjectPointerType whose pointee is an ObjCObjectType /// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually /// this should get its own sugar class to better represent the source. class ObjCObjectType : public Type, public ObjCProtocolQualifiers<ObjCObjectType> { … }; /// A class providing a concrete implementation /// of ObjCObjectType, so as to not increase the footprint of /// ObjCInterfaceType. Code outside of ASTContext and the core type /// system should not reference this type. class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { … }; inline QualType *ObjCObjectType::getTypeArgStorage() { … } inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorageImpl() { … } inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { … } /// Interfaces are the core concept in Objective-C for object oriented design. /// They basically correspond to C++ classes. There are two kinds of interface /// types: normal interfaces like `NSString`, and qualified interfaces, which /// are qualified with a protocol list like `NSString<NSCopyable, NSAmazing>`. /// /// ObjCInterfaceType guarantees the following properties when considered /// as a subtype of its superclass, ObjCObjectType: /// - There are no protocol qualifiers. To reinforce this, code which /// tries to invoke the protocol methods via an ObjCInterfaceType will /// fail to compile. /// - It is its own base type. That is, if T is an ObjCInterfaceType*, /// T->getBaseType() == QualType(T, 0). class ObjCInterfaceType : public ObjCObjectType { … }; inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { … } /// Represents a pointer to an Objective C object. /// /// These are constructed from pointer declarators when the pointee type is /// an ObjCObjectType (or sugar for one). In addition, the 'id' and 'Class' /// types are typedefs for these, and the protocol-qualified types 'id<P>' /// and 'Class<P>' are translated into these. /// /// Pointers to pointers to Objective C objects are still PointerTypes; /// only the first level of pointer gets it own type implementation. class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { … }; class AtomicType : public Type, public llvm::FoldingSetNode { … }; /// PipeType - OpenCL20. class PipeType : public Type, public llvm::FoldingSetNode { … }; /// A fixed int type of a specified bitwidth. class BitIntType final : public Type, public llvm::FoldingSetNode { … }; class DependentBitIntType final : public Type, public llvm::FoldingSetNode { … }; /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { … }; /// A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: /// @code /// TypeLoc TL = TypeSourceInfo->getTypeLoc(); /// TL.getBeginLoc().print(OS, SrcMgr); /// @endcode class alignas(8) TypeSourceInfo { … }; // Inline function definitions. inline SplitQualType SplitQualType::getSingleStepDesugaredType() const { … } inline const Type *QualType::getTypePtr() const { … } inline const Type *QualType::getTypePtrOrNull() const { … } inline bool QualType::isReferenceable() const { … } inline SplitQualType QualType::split() const { … } inline Qualifiers QualType::getLocalQualifiers() const { … } inline Qualifiers QualType::getQualifiers() const { … } inline unsigned QualType::getCVRQualifiers() const { … } inline QualType QualType::getCanonicalType() const { … } inline bool QualType::isCanonical() const { … } inline bool QualType::isCanonicalAsParam() const { … } inline bool QualType::isConstQualified() const { … } inline bool QualType::isRestrictQualified() const { … } inline bool QualType::isVolatileQualified() const { … } inline bool QualType::hasQualifiers() const { … } inline QualType QualType::getUnqualifiedType() const { … } inline SplitQualType QualType::getSplitUnqualifiedType() const { … } inline void QualType::removeLocalConst() { … } inline void QualType::removeLocalRestrict() { … } inline void QualType::removeLocalVolatile() { … } /// Check if this type has any address space qualifier. inline bool QualType::hasAddressSpace() const { … } /// Return the address space of this type. inline LangAS QualType::getAddressSpace() const { … } /// Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { … } inline bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion() const { … } inline bool QualType::hasNonTrivialToPrimitiveDestructCUnion() const { … } inline bool QualType::hasNonTrivialToPrimitiveCopyCUnion() const { … } inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { … } inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { … } /// Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and /// "int". However, it is not more qualified than "const volatile /// int". inline bool QualType::isMoreQualifiedThan(QualType other) const { … } /// Determine whether this type is at last /// as qualified as the Other type. For example, "const volatile /// int" is at least as qualified as "const int", "volatile int", /// "int", and "const volatile int". inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { … } /// If Type is a reference type (e.g., const /// int&), returns the type that the reference refers to ("const /// int"). Otherwise, returns the type itself. This routine is used /// throughout Sema to implement C++ 5p6: /// /// If an expression initially has the type "reference to T" (8.3.2, /// 8.5.3), the type is adjusted to "T" prior to any further /// analysis, the expression designates the object or function /// denoted by the reference, and the expression is an lvalue. inline QualType QualType::getNonReferenceType() const { … } inline bool QualType::isCForbiddenLValueType() const { … } /// Tests whether the type is categorized as a fundamental type. /// /// \returns True for types specified in C++0x [basic.fundamental]. inline bool Type::isFundamentalType() const { … } /// Tests whether the type is categorized as a compound type. /// /// \returns True for types specified in C++0x [basic.compound]. inline bool Type::isCompoundType() const { … } inline bool Type::isFunctionType() const { … } inline bool Type::isPointerType() const { … } inline bool Type::isPointerOrReferenceType() const { … } inline bool Type::isAnyPointerType() const { … } inline bool Type::isSignableType() const { … } inline bool Type::isBlockPointerType() const { … } inline bool Type::isReferenceType() const { … } inline bool Type::isLValueReferenceType() const { … } inline bool Type::isRValueReferenceType() const { … } inline bool Type::isObjectPointerType() const { … } inline bool Type::isFunctionPointerType() const { … } inline bool Type::isFunctionReferenceType() const { … } inline bool Type::isMemberPointerType() const { … } inline bool Type::isMemberFunctionPointerType() const { … } inline bool Type::isMemberDataPointerType() const { … } inline bool Type::isArrayType() const { … } inline bool Type::isConstantArrayType() const { … } inline bool Type::isIncompleteArrayType() const { … } inline bool Type::isVariableArrayType() const { … } inline bool Type::isArrayParameterType() const { … } inline bool Type::isDependentSizedArrayType() const { … } inline bool Type::isBuiltinType() const { … } inline bool Type::isRecordType() const { … } inline bool Type::isEnumeralType() const { … } inline bool Type::isAnyComplexType() const { … } inline bool Type::isVectorType() const { … } inline bool Type::isExtVectorType() const { … } inline bool Type::isExtVectorBoolType() const { … } inline bool Type::isSubscriptableVectorType() const { … } inline bool Type::isMatrixType() const { … } inline bool Type::isConstantMatrixType() const { … } inline bool Type::isDependentAddressSpaceType() const { … } inline bool Type::isObjCObjectPointerType() const { … } inline bool Type::isObjCObjectType() const { … } inline bool Type::isObjCObjectOrInterfaceType() const { … } inline bool Type::isAtomicType() const { … } inline bool Type::isUndeducedAutoType() const { … } inline bool Type::isObjCQualifiedIdType() const { … } inline bool Type::isObjCQualifiedClassType() const { … } inline bool Type::isObjCIdType() const { … } inline bool Type::isObjCClassType() const { … } inline bool Type::isObjCSelType() const { … } inline bool Type::isObjCBuiltinType() const { … } inline bool Type::isDecltypeType() const { … } #define IMAGE_TYPE … #include "clang/Basic/OpenCLImageTypes.def" inline bool Type::isSamplerT() const { … } inline bool Type::isEventT() const { … } inline bool Type::isClkEventT() const { … } inline bool Type::isQueueT() const { … } inline bool Type::isReserveIDT() const { … } inline bool Type::isImageType() const { … } inline bool Type::isPipeType() const { … } inline bool Type::isBitIntType() const { … } #define EXT_OPAQUE_TYPE … #include "clang/Basic/OpenCLExtensionTypes.def" inline bool Type::isOCLIntelSubgroupAVCType() const { … } inline bool Type::isOCLExtOpaqueType() const { … } inline bool Type::isOpenCLSpecificType() const { … } #define HLSL_INTANGIBLE_TYPE … #include "clang/Basic/HLSLIntangibleTypes.def" inline bool Type::isHLSLSpecificType() const { … } inline bool Type::isHLSLIntangibleType() const { … } inline bool Type::isTemplateTypeParmType() const { … } inline bool Type::isSpecificBuiltinType(unsigned K) const { … } inline bool Type::isPlaceholderType() const { … } inline const BuiltinType *Type::getAsPlaceholderType() const { … } inline bool Type::isSpecificPlaceholderType(unsigned K) const { … } inline bool Type::isNonOverloadPlaceholderType() const { … } inline bool Type::isVoidType() const { … } inline bool Type::isHalfType() const { … } inline bool Type::isFloat16Type() const { … } inline bool Type::isFloat32Type() const { … } inline bool Type::isDoubleType() const { … } inline bool Type::isBFloat16Type() const { … } inline bool Type::isFloat128Type() const { … } inline bool Type::isIbm128Type() const { … } inline bool Type::isNullPtrType() const { … } bool IsEnumDeclComplete(EnumDecl *); bool IsEnumDeclScoped(EnumDecl *); inline bool Type::isIntegerType() const { … } inline bool Type::isFixedPointType() const { … } inline bool Type::isFixedPointOrIntegerType() const { … } inline bool Type::isConvertibleToFixedPointType() const { … } inline bool Type::isSaturatedFixedPointType() const { … } inline bool Type::isUnsaturatedFixedPointType() const { … } inline bool Type::isSignedFixedPointType() const { … } inline bool Type::isUnsignedFixedPointType() const { … } inline bool Type::isScalarType() const { … } inline bool Type::isIntegralOrEnumerationType() const { … } inline bool Type::isBooleanType() const { … } inline bool Type::isUndeducedType() const { … } /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { … } /// Determines whether this type is written as a typedef-name. inline bool Type::isTypedefNameType() const { … } /// Determines whether this type can decay to a pointer type. inline bool Type::canDecayToPointerType() const { … } inline bool Type::hasPointerRepresentation() const { … } inline bool Type::hasObjCPointerRepresentation() const { … } inline const Type *Type::getBaseElementTypeUnsafe() const { … } inline const Type *Type::getPointeeOrArrayElementType() const { … } /// Insertion operator for partial diagnostics. This allows sending adress /// spaces into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, LangAS AS) { … } /// Insertion operator for partial diagnostics. This allows sending Qualifiers /// into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, Qualifiers Q) { … } /// Insertion operator for partial diagnostics. This allows sending QualType's /// into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, QualType T) { … } // Helper class template that is used by Type::getAs to ensure that one does // not try to look through a qualified type to get to an array type. TypeIsArrayType; // Member-template getAs<specific type>'. template <typename T> const T *Type::getAs() const { … } template <typename T> const T *Type::getAsAdjusted() const { … } inline const ArrayType *Type::getAsArrayTypeUnsafe() const { … } template <typename T> const T *Type::castAs() const { … } inline const ArrayType *Type::castAsArrayTypeUnsafe() const { … } DecayedType::DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr) : … { … } QualType DecayedType::getPointeeType() const { … } // Get the decimal string representation of a fixed point type, represented // as a scaled integer. // TODO: At some point, we should change the arguments to instead just accept an // APFixedPoint instead of APSInt and scale. void FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APSInt Val, unsigned Scale); inline FunctionEffectsRef FunctionEffectsRef::get(QualType QT) { … } } // namespace clang #endif // LLVM_CLANG_AST_TYPE_H