clang 22.0.0git
clang::ObjCInterfaceType Class Reference

Represents typeof(type), a C23 feature and GCC extension, or `typeof_unqual(type), a C23 feature. More...

#include "clang/AST/TypeBase.h"

Inheritance diagram for clang::ObjCInterfaceType:
[legend]

Public Types

enum  {
  qual_iterator , qual_begin , qual_end , getNumProtocols ,
  getProtocol
}

Public Member Functions

ObjCInterfaceDeclgetDecl () const
 Get the declaration of this interface.
bool isSugared () const
QualType desugar () const

Static Public Member Functions

static bool classof (const Type *T)

Friends

class ASTContext
class ASTReader
template<class T>
class serialization::AbstractTypeReader

Detailed Description

Represents typeof(type), a C23 feature and GCC extension, or `typeof_unqual(type), a C23 feature.

class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these.

QualType TOType; const ASTContext &Context;

TypeOfType(const ASTContext &Context, QualType T, QualType Can, TypeOfKind Kind);

public: QualType getUnmodifiedType() const { return TOType; }

/ Remove a single level of sugar. QualType desugar() const;

/ Returns whether this type directly provides sugar. bool isSugared() const { return true; }

/ Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { return static_cast<TypeOfKind>(TypeOfBits.Kind); }

static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } };

/ Represents the type decltype(expr) (C++11). class DecltypeType : public Type { Expr *E; QualType UnderlyingType;

protected: friend class ASTContext; // ASTContext creates these.

DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType());

public: Expr *getUnderlyingExpr() const { return E; } QualType getUnderlyingType() const { return UnderlyingType; }

/ Remove a single level of sugar. QualType desugar() const;

/ Returns whether this type directly provides sugar. bool isSugared() const;

static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } };

/ 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 { public: DependentDecltypeType(Expr *E);

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getUnderlyingExpr()); }

static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E); };

class PackIndexingType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<PackIndexingType, QualType> { friend TrailingObjects;

QualType Pattern; Expr *IndexExpr;

unsigned Size : 31;

unsigned FullySubstituted : 1;

protected: friend class ASTContext; // ASTContext creates these. PackIndexingType(QualType Canonical, QualType Pattern, Expr *IndexExpr, bool FullySubstituted, ArrayRef<QualType> Expansions = {});

public: Expr *getIndexExpr() const { return IndexExpr; } QualType getPattern() const { return Pattern; }

bool isSugared() const { return hasSelectedType(); }

QualType desugar() const { if (hasSelectedType()) return getSelectedType(); return QualType(this, 0); }

QualType getSelectedType() const { assert(hasSelectedType() && "Type is dependant"); return *(getExpansionsPtr() + *getSelectedIndex()); }

UnsignedOrNone getSelectedIndex() const;

bool hasSelectedType() const { return getSelectedIndex() != std::nullopt; }

bool isFullySubstituted() const { return FullySubstituted; }

bool expandsToEmptyPack() const { return isFullySubstituted() && Size == 0; }

ArrayRef<QualType> getExpansions() const { return {getExpansionsPtr(), Size}; }

static bool classof(const Type *T) { return T->getTypeClass() == PackIndexing; }

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context); static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType Pattern, Expr *E, bool FullySubstituted, ArrayRef<QualType> Expansions);

private: const QualType *getExpansionsPtr() const { return getTrailingObjects(); }

static TypeDependence computeDependence(QualType Pattern, Expr *IndexExpr, ArrayRef<QualType> Expansions = {}); };

/ A unary type transform, which is a type constructed from another. class UnaryTransformType : public Type, public llvm::FoldingSetNode { public: enum UTTKind { #define TRANSFORM_TYPE_TRAIT_DEF(Enum, _)

};

private: / The untransformed type. QualType BaseType;

/ The transformed type if not dependent, otherwise the same as BaseType. QualType UnderlyingType;

UTTKind UKind;

protected: friend class ASTContext;

UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind, QualType CanonicalTy);

public: bool isSugared() const { return !isDependentType(); } QualType desugar() const { return UnderlyingType; }

QualType getUnderlyingType() const { return UnderlyingType; } QualType getBaseType() const { return BaseType; }

UTTKind getUTTKind() const { return UKind; }

static bool classof(const Type *T) { return T->getTypeClass() == UnaryTransform; }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getBaseType(), getUnderlyingType(), getUTTKind()); }

static void Profile(llvm::FoldingSetNodeID &ID, QualType BaseType, QualType UnderlyingType, UTTKind UKind) { BaseType.Profile(ID); UnderlyingType.Profile(ID); ID.AddInteger(UKind); } };

class TagType : public TypeWithKeyword { friend class ASTContext; // ASTContext creates these.

/ Stores the TagDecl associated with this type. The decl may point to any / TagDecl that declares the entity. TagDecl *decl;

void *getTrailingPointer() const; NestedNameSpecifier &getTrailingQualifier() const;

protected: TagType(TypeClass TC, ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool OwnsTag, bool IsInjected, const Type *CanonicalType);

public: FIXME: Temporarily renamed from getDecl in order to facilitate rebasing, due to change in behaviour. This should be renamed back to getDecl once the change is settled. TagDecl *getOriginalDecl() const { return decl; }

NestedNameSpecifier getQualifier() const;

/ Does the TagType own this declaration of the Tag? bool isTagOwned() const { return TagTypeBits.OwnsTag; }

bool isInjected() const { return TagTypeBits.IsInjected; }

ClassTemplateDecl *getTemplateDecl() const; TemplateName getTemplateName(const ASTContext &Ctx) const; ArrayRef<TemplateArgument> getTemplateArgs(const ASTContext &Ctx) const;

bool isSugared() const { return false; } QualType desugar() const { return getCanonicalTypeInternal(); }

static bool classof(const Type *T) { return T->getTypeClass() == Enum || T->getTypeClass() == Record || T->getTypeClass() == InjectedClassName; } };

struct TagTypeFoldingSetPlaceholder : public llvm::FoldingSetNode { static constexpr size_t getOffset() { return alignof(TagType) - (sizeof(TagTypeFoldingSetPlaceholder) % alignof(TagType)); }

static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *Tag, bool OwnsTag, bool IsInjected) { ID.AddInteger(uintptr_t(Tag) | OwnsTag | (IsInjected << 1) | ((Keyword != ElaboratedTypeKeyword::None) << 2)); if (Keyword != ElaboratedTypeKeyword::None) ID.AddInteger(llvm::to_underlying(Keyword)); if (Qualifier) Qualifier.Profile(ID); }

void Profile(llvm::FoldingSetNodeID &ID) const { const TagType *T = getTagType(); Profile(ID, T->getKeyword(), T->getQualifier(), T->getOriginalDecl(), T->isTagOwned(), T->isInjected()); }

TagType *getTagType() { return reinterpret_cast<TagType *>(reinterpret_cast<char *>(this + 1) + getOffset()); } const TagType *getTagType() const { return const_cast<TagTypeFoldingSetPlaceholder *>(this)->getTagType(); } static TagTypeFoldingSetPlaceholder *fromTagType(TagType *T) { return reinterpret_cast<TagTypeFoldingSetPlaceholder *>( reinterpret_cast<char *>(T) - getOffset()) - 1; } };

/ A helper class that allows the use of isa/cast/dyncast / to detect TagType objects of structs/unions/classes. class RecordType final : public TagType { using TagType::TagType;

public: FIXME: Temporarily renamed from getDecl in order to facilitate rebasing, due to change in behaviour. This should be renamed back to getDecl once the change is settled. RecordDecl *getOriginalDecl() const { return reinterpret_cast<RecordDecl *>(TagType::getOriginalDecl()); }

/ Recursively check all fields in the record for const-ness. If any field / is declared const, return true. Otherwise, return false. bool hasConstFields() const;

static bool classof(const Type *T) { return T->getTypeClass() == Record; } };

/ A helper class that allows the use of isa/cast/dyncast / to detect TagType objects of enums. class EnumType final : public TagType { using TagType::TagType;

public: FIXME: Temporarily renamed from getDecl in order to facilitate rebasing, due to change in behaviour. This should be renamed back to getDecl once the change is settled. EnumDecl *getOriginalDecl() const { return reinterpret_cast<EnumDecl *>(TagType::getOriginalDecl()); }

static bool classof(const Type *T) { return T->getTypeClass() == Enum; } };

/ 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 final : public TagType { friend class ASTContext; // ASTContext creates these.

InjectedClassNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool IsInjected, const Type *CanonicalType);

public: FIXME: Temporarily renamed from getDecl in order to facilitate rebasing, due to change in behaviour. This should be renamed back to getDecl once the change is settled. CXXRecordDecl *getOriginalDecl() const { return reinterpret_cast<CXXRecordDecl *>(TagType::getOriginalDecl()); }

static bool classof(const Type *T) { return T->getTypeClass() == InjectedClassName; } };

/ 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 { public: using Kind = attr::Kind;

private: friend class ASTContext; // ASTContext creates these

const Attr *Attribute;

QualType ModifiedType; QualType EquivalentType;

AttributedType(QualType canon, attr::Kind attrKind, QualType modified, QualType equivalent) : AttributedType(canon, attrKind, nullptr, modified, equivalent) {}

AttributedType(QualType canon, const Attr *attr, QualType modified, QualType equivalent);

private: AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr, QualType modified, QualType equivalent);

public: Kind getAttrKind() const { return static_cast<Kind>(AttributedTypeBits.AttrKind); }

const Attr *getAttr() const { return Attribute; }

QualType getModifiedType() const { return ModifiedType; } QualType getEquivalentType() const { return EquivalentType; }

bool isSugared() const { return true; } QualType desugar() const { return getEquivalentType(); }

/ Does this attribute behave like a type qualifier? / / A type qualifier adjusts a type to provide specialized rules for / a specific object, like the standard const and volatile qualifiers. / This includes attributes controlling things like nullability, / address spaces, and ARC ownership. The value of the object is still / largely described by the modified type. / / In contrast, many type attributes "rewrite" their modified type to / produce a fundamentally different type, not necessarily related in any / formalizable way to the original type. For example, calling convention / and vector attributes are not simple type qualifiers. / / Type qualifiers are often, but not always, reflected in the canonical / type. bool isQualifier() const;

bool isMSTypeSpec() const;

bool isWebAssemblyFuncrefSpec() const;

bool isCallingConv() const;

std::optional<NullabilityKind> getImmediateNullability() const;

/ Strip off the top-level nullability annotation on the given / type, if it's there. / /

Parameters
TThe type to strip. If the type is exactly an / AttributedType specifying nullability (without looking through / type sugar), the nullability is returned and this type changed / to the underlying modified type. / /
Returns
the top-level nullability, if present. static std::optional<NullabilityKind> stripOuterNullability(QualType &T);

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAttrKind(), ModifiedType, EquivalentType, Attribute); }

static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind, QualType modified, QualType equivalent, const Attr *attr) { ID.AddInteger(attrKind); ID.AddPointer(modified.getAsOpaquePtr()); ID.AddPointer(equivalent.getAsOpaquePtr()); ID.AddPointer(attr); }

static bool classof(const Type *T) { return T->getTypeClass() == Attributed; } };

class BTFTagAttributedType : public Type, public llvm::FoldingSetNode { private: friend class ASTContext; // ASTContext creates these

QualType WrappedType; const BTFTypeTagAttr *BTFAttr;

BTFTagAttributedType(QualType Canon, QualType Wrapped, const BTFTypeTagAttr *BTFAttr) : Type(BTFTagAttributed, Canon, Wrapped->getDependence()), WrappedType(Wrapped), BTFAttr(BTFAttr) {}

public: QualType getWrappedType() const { return WrappedType; } const BTFTypeTagAttr *getAttr() const { return BTFAttr; }

bool isSugared() const { return true; } QualType desugar() const { return getWrappedType(); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, WrappedType, BTFAttr); }

static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped, const BTFTypeTagAttr *BTFAttr) { ID.AddPointer(Wrapped.getAsOpaquePtr()); ID.AddPointer(BTFAttr); }

static bool classof(const Type *T) { return T->getTypeClass() == BTFTagAttributed; } };

class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode { public: struct Attributes { Data gathered from HLSL resource attributes llvm::dxil::ResourceClass ResourceClass;

uint8_t IsROV : 1;


uint8_t RawBuffer : 1;

Attributes(llvm::dxil::ResourceClass ResourceClass, bool IsROV = false,
           bool RawBuffer = false)
    : ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer) {}

Attributes() : Attributes(llvm::dxil::ResourceClass::UAV, false, false) {}

friend bool operator==(const Attributes &LHS, const Attributes &RHS) {
  return std::tie(LHS.ResourceClass, LHS.IsROV, LHS.RawBuffer) ==
         std::tie(RHS.ResourceClass, RHS.IsROV, RHS.RawBuffer);
}
friend bool operator!=(const Attributes &LHS, const Attributes &RHS) {
  return !(LHS == RHS);
}

};

private: friend class ASTContext; // ASTContext creates these

QualType WrappedType; QualType ContainedType; const Attributes Attrs;

HLSLAttributedResourceType(QualType Wrapped, QualType Contained, const Attributes &Attrs) : Type(HLSLAttributedResource, QualType(), Contained.isNull() ? TypeDependence::None : Contained->getDependence()), WrappedType(Wrapped), ContainedType(Contained), Attrs(Attrs) {}

public: QualType getWrappedType() const { return WrappedType; } QualType getContainedType() const { return ContainedType; } bool hasContainedType() const { return !ContainedType.isNull(); } const Attributes &getAttrs() const { return Attrs; }

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, WrappedType, ContainedType, Attrs); }

static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped, QualType Contained, const Attributes &Attrs) { ID.AddPointer(Wrapped.getAsOpaquePtr()); ID.AddPointer(Contained.getAsOpaquePtr()); ID.AddInteger(static_cast<uint32_t>(Attrs.ResourceClass)); ID.AddBoolean(Attrs.IsROV); ID.AddBoolean(Attrs.RawBuffer); }

static bool classof(const Type *T) { return T->getTypeClass() == HLSLAttributedResource; }

Returns handle type from HLSL resource, if the type is a resource static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT); };

/ Instances of this class represent operands to a SPIR-V type instruction. class SpirvOperand { public: enum SpirvOperandKind : unsigned char { Invalid, ///< Uninitialized. ConstantId, ///< Integral value to represent as a SPIR-V OpConstant /< instruction ID. Literal, ///< Integral value to represent as an immediate literal. TypeId, ///< Type to represent as a SPIR-V type ID.

Max, };

private: SpirvOperandKind Kind = Invalid;

QualType ResultType; llvm::APInt Value; // Signedness of constants is represented by ResultType.

public: SpirvOperand() : Kind(Invalid), ResultType(), Value() {}

SpirvOperand(SpirvOperandKind Kind, QualType ResultType, llvm::APInt Value) : Kind(Kind), ResultType(ResultType), Value(std::move(Value)) {}

SpirvOperand(const SpirvOperand &Other) { *this = Other; } ~SpirvOperand() {}

SpirvOperand &operator=(const SpirvOperand &Other) = default;

bool operator==(const SpirvOperand &Other) const { return Kind == Other.Kind && ResultType == Other.ResultType && Value == Other.Value; }

bool operator!=(const SpirvOperand &Other) const { return !(*this == Other); }

SpirvOperandKind getKind() const { return Kind; }

bool isValid() const { return Kind != Invalid && Kind < Max; } bool isConstant() const { return Kind == ConstantId; } bool isLiteral() const { return Kind == Literal; } bool isType() const { return Kind == TypeId; }

llvm::APInt getValue() const { assert((isConstant() || isLiteral()) && "This is not an operand with a value!"); return Value; }

QualType getResultType() const { assert((isConstant() || isType()) && "This is not an operand with a result type!"); return ResultType; }

static SpirvOperand createConstant(QualType ResultType, llvm::APInt Val) { return SpirvOperand(ConstantId, ResultType, std::move(Val)); }

static SpirvOperand createLiteral(llvm::APInt Val) { return SpirvOperand(Literal, QualType(), std::move(Val)); }

static SpirvOperand createType(QualType T) { return SpirvOperand(TypeId, T, llvm::APSInt()); }

void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Kind); ID.AddPointer(ResultType.getAsOpaquePtr()); Value.Profile(ID); } };

/ Represents an arbitrary, user-specified SPIR-V type instruction. class HLSLInlineSpirvType final : public Type, public llvm::FoldingSetNode, private llvm::TrailingObjects<HLSLInlineSpirvType, SpirvOperand> { friend class ASTContext; // ASTContext creates these friend TrailingObjects;

private: uint32_t Opcode; uint32_t Size; uint32_t Alignment; size_t NumOperands;

HLSLInlineSpirvType(uint32_t Opcode, uint32_t Size, uint32_t Alignment, ArrayRef<SpirvOperand> Operands) : Type(HLSLInlineSpirv, QualType(), TypeDependence::None), Opcode(Opcode), Size(Size), Alignment(Alignment), NumOperands(Operands.size()) { for (size_t I = 0; I < NumOperands; I++) { Since Operands are stored as a trailing object, they have not been initialized yet. Call the constructor manually. auto *Operand = new (&getTrailingObjects()[I]) SpirvOperand(); Operand = Operands[I]; } }

public: uint32_t getOpcode() const { return Opcode; } uint32_t getSize() const { return Size; } uint32_t getAlignment() const { return Alignment; } ArrayRef<SpirvOperand> getOperands() const { return getTrailingObjects(NumOperands); }

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Opcode, Size, Alignment, getOperands()); }

static void Profile(llvm::FoldingSetNodeID &ID, uint32_t Opcode, uint32_t Size, uint32_t Alignment, ArrayRef<SpirvOperand> Operands) { ID.AddInteger(Opcode); ID.AddInteger(Size); ID.AddInteger(Alignment); for (auto &Operand : Operands) Operand.Profile(ID); }

static bool classof(const Type *T) { return T->getTypeClass() == HLSLInlineSpirv; } };

class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these

The associated TemplateTypeParmDecl for the non-canonical type. TemplateTypeParmDecl *TTPDecl;

TemplateTypeParmType(unsigned D, unsigned I, bool PP, TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, TypeDependence::DependentInstantiation | (PP ? TypeDependence::UnexpandedPack : TypeDependence::None)), TTPDecl(TTPDecl) { assert(!TTPDecl == Canon.isNull()); TemplateTypeParmTypeBits.Depth = D; TemplateTypeParmTypeBits.Index = I; TemplateTypeParmTypeBits.ParameterPack = PP; }

public: unsigned getDepth() const { return TemplateTypeParmTypeBits.Depth; } unsigned getIndex() const { return TemplateTypeParmTypeBits.Index; } bool isParameterPack() const { return TemplateTypeParmTypeBits.ParameterPack; }

TemplateTypeParmDecl *getDecl() const { return TTPDecl; }

IdentifierInfo *getIdentifier() const;

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); }

static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, unsigned Index, bool ParameterPack, TemplateTypeParmDecl *TTPDecl) { ID.AddInteger(Depth); ID.AddInteger(Index); ID.AddBoolean(ParameterPack); ID.AddPointer(TTPDecl); }

static bool classof(const Type *T) { return T->getTypeClass() == TemplateTypeParm; } };

/ 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> { friend class ASTContext; friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;

Decl *AssociatedDecl;

SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex, bool Final);

public: / Gets the type that was substituted for the template / parameter. QualType getReplacementType() const { return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType ? *getTrailingObjects() : getCanonicalTypeInternal(); }

/ A template-like entity which owns the whole pattern being substituted. / This will usually own a set of template parameters, or in some / cases might even be a template parameter itself. Decl *getAssociatedDecl() const { return AssociatedDecl; }

/ Gets the template parameter declaration that was substituted for. const TemplateTypeParmDecl *getReplacedParameter() const;

/ Returns the index of the replaced parameter in the associated declaration. / This should match the result of getReplacedParameter()->getIndex(). unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }

This substitution is Final, which means the substitution is fully sugared: it doesn't need to be resugared later. unsigned getFinal() const { return SubstTemplateTypeParmTypeBits.Final; }

UnsignedOrNone getPackIndex() const { return UnsignedOrNone::fromInternalRepresentation( SubstTemplateTypeParmTypeBits.PackIndex); }

bool isSugared() const { return true; } QualType desugar() const { return getReplacementType(); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(), getPackIndex(), getFinal()); }

static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement, const Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex, bool Final);

static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParm; } };

/ Represents the result of substituting a set of types as a template argument / that needs to be expanded later. / / These types are always dependent and produced depending on the situations: / - SubstTemplateTypeParmPack is an expansion that had to be delayed, / - SubstBuiltinTemplatePackType is an expansion from a builtin. class SubstPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext;

/ A pointer to the set of template arguments that this / parameter pack is instantiated with. const TemplateArgument *Arguments;

protected: SubstPackType(TypeClass Derived, QualType Canon, const TemplateArgument &ArgPack);

public: unsigned getNumArgs() const { return SubstPackTypeBits.NumArgs; }

TemplateArgument getArgumentPack() const;

void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument &ArgPack);

static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParmPack || T->getTypeClass() == SubstBuiltinTemplatePack; } };

/ Represents the result of substituting a builtin template as a pack. class SubstBuiltinTemplatePackType : public SubstPackType { friend class ASTContext;

SubstBuiltinTemplatePackType(QualType Canon, const TemplateArgument &ArgPack);

public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

/ Mark that we reuse the Profile. We do not introduce new fields. using SubstPackType::Profile;

static bool classof(const Type *T) { return T->getTypeClass() == SubstBuiltinTemplatePack; } };

/ 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 SubstTemplateTypeParmType / at the current pack substitution index. class SubstTemplateTypeParmPackType : public SubstPackType { friend class ASTContext;

/ A pointer to the set of template arguments that this / parameter pack is instantiated with. const TemplateArgument *Arguments;

llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;

SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final, const TemplateArgument &ArgPack);

public: IdentifierInfo *getIdentifier() const;

/ A template-like entity which owns the whole pattern being substituted. / This will usually own a set of template parameters, or in some / cases might even be a template parameter itself. Decl *getAssociatedDecl() const;

/ Gets the template parameter declaration that was substituted for. const TemplateTypeParmDecl *getReplacedParameter() const;

/ Returns the index of the replaced parameter in the associated declaration. / This should match the result of getReplacedParameter()->getIndex(). unsigned getIndex() const { return SubstPackTypeBits.SubstTemplTypeParmPackIndex; }

This substitution will be Final, which means the substitution will be fully sugared: it doesn't need to be resugared later. bool getFinal() const;

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl, unsigned Index, bool Final, const TemplateArgument &ArgPack);

static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParmPack; } };

/ 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 { QualType DeducedAsType;

protected: DeducedType(TypeClass TC, QualType DeducedAsType, TypeDependence ExtraDependence, QualType Canon) : Type(TC, Canon, ExtraDependence | (DeducedAsType.isNull() ? TypeDependence::None : DeducedAsType->getDependence() & ~TypeDependence::VariablyModified)), DeducedAsType(DeducedAsType) {}

public: bool isSugared() const { return !DeducedAsType.isNull(); } QualType desugar() const { return isSugared() ? DeducedAsType : QualType(this, 0); }

/ Get the type deduced for this placeholder type, or null if it / has not been deduced. QualType getDeducedType() const { return DeducedAsType; } bool isDeduced() const { return !DeducedAsType.isNull() || isDependentType(); }

static bool classof(const Type *T) { return T->getTypeClass() == Auto || T->getTypeClass() == DeducedTemplateSpecialization; } };

/ Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained / by a type-constraint. class AutoType : public DeducedType { friend class ASTContext; // ASTContext creates these

TemplateDecl *TypeConstraintConcept;

AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, TypeDependence ExtraDependence, QualType Canon, TemplateDecl *CD, ArrayRef<TemplateArgument> TypeConstraintArgs);

public: ArrayRef<TemplateArgument> getTypeConstraintArguments() const { return {reinterpret_cast<const TemplateArgument *>(this + 1), AutoTypeBits.NumArgs}; }

TemplateDecl *getTypeConstraintConcept() const { return TypeConstraintConcept; }

bool isConstrained() const { return TypeConstraintConcept != nullptr; }

bool isDecltypeAuto() const { return getKeyword() == AutoTypeKeyword::DecltypeAuto; }

bool isGNUAutoType() const { return getKeyword() == AutoTypeKeyword::GNUAutoType; }

AutoTypeKeyword getKeyword() const { return (AutoTypeKeyword)AutoTypeBits.Keyword; }

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context); static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType Deduced, AutoTypeKeyword Keyword, bool IsDependent, TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments);

static bool classof(const Type *T) { return T->getTypeClass() == Auto; } };

/ Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public KeywordWrapper<DeducedType>, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these

/ The name of the template whose arguments will be deduced. TemplateName Template;

DeducedTemplateSpecializationType(ElaboratedTypeKeyword Keyword, TemplateName Template, QualType DeducedAsType, bool IsDeducedAsDependent, QualType Canon) : KeywordWrapper(Keyword, DeducedTemplateSpecialization, DeducedAsType, toTypeDependence(Template.getDependence()) | (IsDeducedAsDependent ? TypeDependence::DependentInstantiation : TypeDependence::None), Canon), Template(Template) {}

public: / Retrieve the name of the template that we are deducing. TemplateName getTemplateName() const { return Template; }

void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getKeyword(), getTemplateName(), getDeducedType(), isDependentType()); }

static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, TemplateName Template, QualType Deduced, bool IsDependent) { ID.AddInteger(llvm::to_underlying(Keyword)); Template.Profile(ID); Deduced.Profile(ID); ID.AddBoolean(IsDependent || Template.isDependent()); }

static bool classof(const Type *T) { return T->getTypeClass() == DeducedTemplateSpecialization; } };

/ 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 / DependentTemplateSpecializationType. / / A non-dependent template specialization type is always "sugar", / typically for a RecordType. For example, a class template / specialization type of vector<int> will refer to a tag type for / the instantiation 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 TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these

/ The name of the template being specialized. This is / either a TemplateName::Template (in which case it is a / ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a / TypeAliasTemplateDecl*), a / TemplateName::SubstTemplateTemplateParmPack, or a / TemplateName::SubstTemplateTemplateParm (in which case the / replacement must, recursively, be one of these). TemplateName Template;

TemplateSpecializationType(ElaboratedTypeKeyword Keyword, TemplateName T, bool IsAlias, ArrayRef<TemplateArgument> Args, QualType Underlying);

public: / Determine whether any of the given template arguments are dependent. / / The converted arguments should be supplied when known; whether an / argument is dependent can depend on the conversions performed on it / (for example, a 'const int' passed as a template argument might be / dependent if the parameter is a reference but non-dependent if the / parameter is an int). / / Note that the Args parameter is unused: this is intentional, to remind / the caller that they need to pass in the converted arguments, not the / specified arguments. static bool anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, ArrayRef<TemplateArgument> Converted); static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, ArrayRef<TemplateArgument> Converted); static bool anyInstantiationDependentTemplateArguments( ArrayRef<TemplateArgumentLoc> Args);

/ True if this template specialization type matches a current / instantiation in the context in which it is found. bool isCurrentInstantiation() const { return isa<InjectedClassNameType>(getCanonicalTypeInternal()); }

/ Determine if this template specialization type is for a type alias / template that has been substituted. / / Nearly every template specialization type whose template is an alias / template will be substituted. However, this is not the case when / the specialization contains a pack expansion but the template alias / does not have a corresponding parameter pack, e.g., / /

/// template<typename T, typename U, typename V> struct S;
/// template<typename T, typename U> using A = S<T, int, U>;
/// template<typename... Ts> struct X {
/// typedef A<Ts...> type; // not a type alias
/// };
///

bool isTypeAlias() const { return TemplateSpecializationTypeBits.TypeAlias; }

/ Get the aliased type, if this is a specialization of a type alias / template. QualType getAliasedType() const;

/ Retrieve the name of the template that we are specializing. TemplateName getTemplateName() const { return Template; }

ArrayRef<TemplateArgument> template_arguments() const { return {reinterpret_cast<const TemplateArgument *>(this + 1), TemplateSpecializationTypeBits.NumArgs}; }

bool isSugared() const;

QualType desugar() const { return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal(); }

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, TemplateName T, ArrayRef<TemplateArgument> Args, QualType Underlying, const ASTContext &Context);

static bool classof(const Type *T) { return T->getTypeClass() == TemplateSpecialization; } };

/ 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);

/ 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 { friend class ASTContext; // ASTContext creates these

/ The nested name specifier containing the qualifier. NestedNameSpecifier NNS;

/ The type that this typename specifier refers to. const IdentifierInfo *Name;

DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier NNS, const IdentifierInfo *Name, QualType CanonType) : TypeWithKeyword(Keyword, DependentName, CanonType, TypeDependence::DependentInstantiation | (NNS ? toTypeDependence(NNS.getDependence()) : TypeDependence::Dependent)), NNS(NNS), Name(Name) { assert(Name); }

public: / Retrieve the qualification on this type. NestedNameSpecifier getQualifier() const { return NNS; }

/ Retrieve the identifier that terminates this type name. / For example, "type" in "typename T::type". const IdentifierInfo *getIdentifier() const { return Name; }

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getKeyword(), NNS, Name); }

static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, NestedNameSpecifier NNS, const IdentifierInfo *Name) { ID.AddInteger(llvm::to_underlying(Keyword)); NNS.Profile(ID); ID.AddPointer(Name); }

static bool classof(const Type *T) { return T->getTypeClass() == DependentName; } };

/ 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. / /

/// template<typename ...Types> struct tuple;
///
/// template<typename ...Types>
/// struct tuple_of_references {
/// typedef tuple<Types&...> type;
/// };
///

/ / Here, the pack expansion Types&... is represented via a / PackExpansionType whose pattern is Types&. class PackExpansionType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these

/ The pattern of the pack expansion. QualType Pattern;

PackExpansionType(QualType Pattern, QualType Canon, UnsignedOrNone NumExpansions) : Type(PackExpansion, Canon, (Pattern->getDependence() | TypeDependence::Dependent | TypeDependence::Instantiation) & ~TypeDependence::UnexpandedPack), Pattern(Pattern) { PackExpansionTypeBits.NumExpansions = NumExpansions ? *NumExpansions + 1 : 0; }

public: / Retrieve the pattern of this pack expansion, which is the / type that will be repeatedly instantiated when instantiating the / pack expansion itself. QualType getPattern() const { return Pattern; }

/ Retrieve the number of expansions that this pack expansion will / generate, if known. UnsignedOrNone getNumExpansions() const { if (PackExpansionTypeBits.NumExpansions) return PackExpansionTypeBits.NumExpansions - 1; return std::nullopt; }

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPattern(), getNumExpansions()); }

static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern, UnsignedOrNone NumExpansions) { ID.AddPointer(Pattern.getAsOpaquePtr()); ID.AddInteger(NumExpansions.toInternalRepresentation()); }

static bool classof(const Type *T) { return T->getTypeClass() == PackExpansion; } };

/ 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 { protected: ObjCProtocolQualifiers() = default;

ObjCProtocolDecl * const getProtocolStorage() const { return const_cast<ObjCProtocolQualifiers>(this)->getProtocolStorage(); }

ObjCProtocolDecl **getProtocolStorage() { return static_cast<T*>(this)->getProtocolStorageImpl(); }

void setNumProtocols(unsigned N) { static_cast<T*>(this)->setNumProtocolsImpl(N); }

void initialize(ArrayRef<ObjCProtocolDecl *> protocols) { setNumProtocols(protocols.size()); assert(getNumProtocols() == protocols.size() && "bitfield overflow in protocol count"); if (!protocols.empty()) memcpy(getProtocolStorage(), protocols.data(), protocols.size() * sizeof(ObjCProtocolDecl*)); }

public: using qual_iterator = ObjCProtocolDecl * const *; using qual_range = llvm::iterator_range<qual_iterator>;

qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getProtocolStorage(); } qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); }

bool qual_empty() const { return getNumProtocols() == 0; }

/ Return the number of qualifying protocols in this type, or 0 if / there are none. unsigned getNumProtocols() const { return static_cast<const T*>(this)->getNumProtocolsImpl(); }

/ Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; }

/ Retrieve all of the protocol qualifiers. ArrayRef<ObjCProtocolDecl *> getProtocols() const { return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols()); } };

/ 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 { friend class ASTContext; friend class ObjCProtocolQualifiers<ObjCTypeParamType>;

/ The number of protocols stored on this type. unsigned NumProtocols : 6;

ObjCTypeParamDecl *OTPDecl;

/ The protocols are stored after the ObjCTypeParamType node. In the / canonical type, the list of protocols are sorted alphabetically / and uniqued. ObjCProtocolDecl **getProtocolStorageImpl();

/ Return the number of qualifying protocols in this interface type, / or 0 if there are none. unsigned getNumProtocolsImpl() const { return NumProtocols; }

void setNumProtocolsImpl(unsigned N) { NumProtocols = N; }

ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols);

public: bool isSugared() const { return true; } QualType desugar() const { return getCanonicalTypeInternal(); }

static bool classof(const Type *T) { return T->getTypeClass() == ObjCTypeParam; }

void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const ObjCTypeParamDecl *OTPDecl, QualType CanonicalType, ArrayRef<ObjCProtocolDecl *> protocols);

ObjCTypeParamDecl *getDecl() const { return OTPDecl; } };

/ 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: /

/// \@class C<T>;
/// \@protocol P;
///

/ / 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType / with base C and no protocols. / / 'C

' 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*>

' 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

' 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> { friend class ObjCProtocolQualifiers<ObjCObjectType>;

ObjCObjectType.NumTypeArgs - the number of type arguments stored after the ObjCObjectPointerType node. ObjCObjectType.NumProtocols - the number of protocols stored after the type arguments of ObjCObjectPointerType node.

These protocols are those written directly on the type. If protocol qualifiers ever become additive, the iterators will need to get kindof complicated.

In the canonical object type, these are sorted alphabetically and uniqued.

/ Either a BuiltinType or an InterfaceType or sugar for either. QualType BaseType;

/ Cached superclass type. mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool> CachedSuperClassType;

QualType *getTypeArgStorage(); const QualType *getTypeArgStorage() const { return const_cast<ObjCObjectType *>(this)->getTypeArgStorage(); }

ObjCProtocolDecl **getProtocolStorageImpl(); / Return the number of qualifying protocols in this interface type, / or 0 if there are none. unsigned getNumProtocolsImpl() const { return ObjCObjectTypeBits.NumProtocols; } void setNumProtocolsImpl(unsigned N) { ObjCObjectTypeBits.NumProtocols = N; }

protected: enum Nonce_ObjCInterface { Nonce_ObjCInterface };

ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf);

ObjCObjectType(enum Nonce_ObjCInterface) : Type(ObjCInterface, QualType(), TypeDependence::None), BaseType(QualType(this_(), 0)) { ObjCObjectTypeBits.NumProtocols = 0; ObjCObjectTypeBits.NumTypeArgs = 0; ObjCObjectTypeBits.IsKindOf = 0; }

void computeSuperClassTypeSlow() const;

public: / Gets the base type of this object type. This is always (possibly / sugar for) one of: / - the 'id' builtin type (as opposed to the 'id' type visible to the / user, which is a typedef for an ObjCObjectPointerType) / - the 'Class' builtin type (same caveat) / - an ObjCObjectType (currently always an ObjCInterfaceType) QualType getBaseType() const { return BaseType; }

bool isObjCId() const { return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); }

bool isObjCClass() const { return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); }

bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } bool isObjCUnqualifiedIdOrClass() const { if (!qual_empty()) return false; if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>()) return T->getKind() == BuiltinType::ObjCId || T->getKind() == BuiltinType::ObjCClass; return false; } bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); }

/ Gets the interface declaration for this object type, if the base type / really is an interface. ObjCInterfaceDecl *getInterface() const;

/ Determine whether this object type is "specialized", meaning / that it has type arguments. bool isSpecialized() const;

/ Determine whether this object type was written with type arguments. bool isSpecializedAsWritten() const { return ObjCObjectTypeBits.NumTypeArgs > 0; }

/ Determine whether this object type is "unspecialized", meaning / that it has no type arguments. bool isUnspecialized() const { return !isSpecialized(); }

/ Determine whether this object type is "unspecialized" as / written, meaning that it has no type arguments. bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }

/ Retrieve the type arguments of this object type (semantically). ArrayRef<QualType> getTypeArgs() const;

/ Retrieve the type arguments of this object type as they were / written. ArrayRef<QualType> getTypeArgsAsWritten() const { return {getTypeArgStorage(), ObjCObjectTypeBits.NumTypeArgs}; }

/ Whether this is a "__kindof" type as written. bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }

/ Whether this ia a "__kindof" type (semantically). bool isKindOfType() const;

/ Retrieve the type of the superclass of this object type. / / This operation substitutes any type arguments into the / superclass of the current class type, potentially producing a / specialization of the superclass type. Produces a null type if / there is no superclass. QualType getSuperClassType() const { if (!CachedSuperClassType.getInt()) computeSuperClassTypeSlow();

assert(CachedSuperClassType.getInt() && "Superclass not set?"); return QualType(CachedSuperClassType.getPointer(), 0); }

/ Strip off the Objective-C "kindof" type and (with it) any / protocol qualifiers. QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const;

bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); }

static bool classof(const Type *T) { return T->getTypeClass() == ObjCObject || T->getTypeClass() == ObjCInterface; } };

/ 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 { friend class ASTContext;

If anyone adds fields here, ObjCObjectType::getProtocolStorage() will need to be modified.

ObjCObjectTypeImpl(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}

public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf); };

inline QualType ObjCObjectType::getTypeArgStorage() { return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl>(this)+1); }

inline ObjCProtocolDecl ObjCObjectType::getProtocolStorageImpl() { return reinterpret_cast<ObjCProtocolDecl>( getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); }

inline ObjCProtocolDecl ObjCTypeParamType::getProtocolStorageImpl() { return reinterpret_cast<ObjCProtocolDecl>( static_cast<ObjCTypeParamType*>(this)+1); }

/ 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). 

Definition at line 7847 of file TypeBase.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
qual_iterator 
qual_begin 
qual_end 
getNumProtocols 
getProtocol 

Definition at line 7873 of file TypeBase.h.

Member Function Documentation

◆ classof()

bool clang::ObjCInterfaceType::classof ( const Type * T)
inlinestatic

Definition at line 7865 of file TypeBase.h.

References clang::T.

◆ desugar()

QualType clang::ObjCInterfaceType::desugar ( ) const
inline

Definition at line 7863 of file TypeBase.h.

◆ getDecl()

◆ isSugared()

bool clang::ObjCInterfaceType::isSugared ( ) const
inline

Definition at line 7862 of file TypeBase.h.

◆ ASTContext

friend class ASTContext
friend

Definition at line 7848 of file TypeBase.h.

References ASTContext.

Referenced by ASTContext.

◆ ASTReader

friend class ASTReader
friend

Definition at line 7849 of file TypeBase.h.

References ASTReader.

Referenced by ASTReader.

◆ serialization::AbstractTypeReader

template<class T>
friend class serialization::AbstractTypeReader
friend

Definition at line 7850 of file TypeBase.h.


The documentation for this class was generated from the following files: