diff options
Diffstat (limited to 'include/clang/AST/Type.h')
| -rw-r--r-- | include/clang/AST/Type.h | 1152 |
1 files changed, 708 insertions, 444 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 984096ffa9877..7247838947a2e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1,4 +1,4 @@ -//===--- Type.h - C Language Family Type Representation ---------*- C++ -*-===// +//===- Type.h - C Language Family Type Representation -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,12 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file /// \brief 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 @@ -25,85 +26,118 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.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/ErrorHandling.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <string> +#include <type_traits> +#include <utility> namespace clang { - enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits - }; - class Type; - class ExtQuals; - class QualType; -} + +class ExtQuals; +class QualType; +class Type; + +enum { + TypeAlignmentInBits = 4, + TypeAlignment = 1 << TypeAlignmentInBits +}; + +} // namespace clang namespace llvm { + template <typename T> - class PointerLikeTypeTraits; + struct PointerLikeTypeTraits; template<> - class PointerLikeTypeTraits< ::clang::Type*> { - public: + struct PointerLikeTypeTraits< ::clang::Type*> { static inline void *getAsVoidPointer(::clang::Type *P) { return P; } + static inline ::clang::Type *getFromVoidPointer(void *P) { return static_cast< ::clang::Type*>(P); } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; + template<> - class PointerLikeTypeTraits< ::clang::ExtQuals*> { - public: + struct PointerLikeTypeTraits< ::clang::ExtQuals*> { static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } + static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { return static_cast< ::clang::ExtQuals*>(P); } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; template <> struct isPodLike<clang::QualType> { static const bool value = true; }; -} + +} // namespace llvm namespace clang { - class ASTContext; - class TypedefNameDecl; - class TemplateDecl; - class TemplateTypeParmDecl; - class NonTypeTemplateParmDecl; - class TemplateTemplateParmDecl; - class TagDecl; - class RecordDecl; - class CXXRecordDecl; - class EnumDecl; - class FieldDecl; - class FunctionDecl; - class ObjCInterfaceDecl; - class ObjCProtocolDecl; - class ObjCMethodDecl; - class ObjCTypeParamDecl; - class UnresolvedUsingTypenameDecl; - class Expr; - class Stmt; - class SourceLocation; - class StmtIteratorBase; - class TemplateArgument; - class TemplateArgumentLoc; - class TemplateArgumentListInfo; - class ElaboratedType; - class ExtQuals; - class ExtQualsTypeCommonBase; - struct PrintingPolicy; - template <typename> class CanQual; - typedef CanQual<Type> CanQualType; +class ArrayType; +class ASTContext; +class AttributedType; +class AutoType; +class BuiltinType; +template <typename> class CanQual; +class ComplexType; +class CXXRecordDecl; +class DeclContext; +class DeducedType; +class EnumDecl; +class Expr; +class ExtQualsTypeCommonBase; +class FunctionDecl; +class FunctionNoProtoType; +class FunctionProtoType; +class IdentifierInfo; +class InjectedClassNameType; +class NamedDecl; +class ObjCInterfaceDecl; +class ObjCObjectPointerType; +class ObjCObjectType; +class ObjCProtocolDecl; +class ObjCTypeParamDecl; +class ParenType; +struct PrintingPolicy; +class RecordDecl; +class RecordType; +class Stmt; +class TagDecl; +class TemplateArgument; +class TemplateArgumentListInfo; +class TemplateArgumentLoc; +class TemplateSpecializationType; +class TemplateTypeParmDecl; +class TypedefNameDecl; +class TypedefType; +class UnresolvedUsingTypenameDecl; + +using CanQualType = CanQual<Type>; // Provide forward declarations for all of the *Type classes #define TYPE(Class, Base) class Class##Type; @@ -164,8 +198,6 @@ public: FastMask = (1 << FastWidth) - 1 }; - Qualifiers() : Mask(0) {} - /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { @@ -332,9 +364,11 @@ public: } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } - unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + LangAS getAddressSpace() const { + return static_cast<LangAS>(Mask >> AddressSpaceShift); + } bool hasTargetSpecificAddressSpace() const { - return getAddressSpace() >= LangAS::FirstTargetAddressSpace; + return isTargetAddressSpace(getAddressSpace()); } /// Get the address space attribute value to be printed by diagnostics. unsigned getAddressSpaceAttributePrintValue() const { @@ -342,22 +376,22 @@ public: // This function is not supposed to be used with language specific // address spaces. If that happens, the diagnostic message should consider // printing the QualType instead of the address space value. - assert(Addr == 0 || hasTargetSpecificAddressSpace()); - if (Addr) - return Addr - LangAS::FirstTargetAddressSpace; + assert(Addr == LangAS::Default || hasTargetSpecificAddressSpace()); + if (Addr != LangAS::Default) + return toTargetAddressSpace(Addr); // TODO: The diagnostic messages where Addr may be 0 should be fixed // since it cannot differentiate the situation where 0 denotes the default // address space or user specified __attribute__((address_space(0))). return 0; } - void setAddressSpace(unsigned space) { - assert(space <= MaxAddressSpace); + void setAddressSpace(LangAS space) { + assert((unsigned)space <= MaxAddressSpace); Mask = (Mask & ~AddressSpaceMask) | (((uint32_t) space) << AddressSpaceShift); } - void removeAddressSpace() { setAddressSpace(0); } - void addAddressSpace(unsigned space) { - assert(space); + void removeAddressSpace() { setAddressSpace(LangAS::Default); } + void addAddressSpace(LangAS space) { + assert(space != LangAS::Default); setAddressSpace(space); } @@ -538,10 +572,9 @@ public: } private: - // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| // |C R V|U|GCAttr|Lifetime|AddressSpace| - uint32_t Mask; + uint32_t Mask = 0; static const uint32_t UMask = 0x8; static const uint32_t UShift = 3; @@ -558,12 +591,12 @@ private: /// into its local qualifiers and its locally-unqualified type. struct SplitQualType { /// The locally-unqualified type. - const Type *Ty; + const Type *Ty = nullptr; /// The local qualifiers. Qualifiers Quals; - SplitQualType() : Ty(nullptr), Quals() {} + SplitQualType() = default; SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} SplitQualType getSingleStepDesugaredType() const; // end of this file @@ -589,12 +622,16 @@ struct SplitQualType { enum class ObjCSubstitutionContext { /// An ordinary type. Ordinary, + /// The result type of a method or function. Result, + /// The parameter type of a method or function. Parameter, + /// The type of a property. Property, + /// The superclass of a type. Superclass, }; @@ -614,8 +651,10 @@ enum class ObjCSubstitutionContext { /// indicates whether there are extended qualifiers present, in which /// case the pointer points to a special structure. class QualType { + friend class QualifierCollector; + // Thankfully, these are efficiently composable. - llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, + llvm::PointerIntPair<llvm::PointerUnion<const Type *, const ExtQuals *>, Qualifiers::FastWidth> Value; const ExtQuals *getExtQualsUnsafe() const { @@ -634,14 +673,10 @@ class QualType { return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); } - friend class QualifierCollector; public: - QualType() {} - - QualType(const Type *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} - QualType(const ExtQuals *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} + QualType() = default; + QualType(const Type *Ptr, unsigned Quals) : Value(Ptr, Quals) {} + QualType(const ExtQuals *Ptr, unsigned Quals) : Value(Ptr, Quals) {} unsigned getLocalFastQualifiers() const { return Value.getInt(); } void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } @@ -662,6 +697,7 @@ public: SplitQualType split() const; void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } + static QualType getFromOpaquePtr(const void *Ptr) { QualType T; T.Value.setFromOpaqueValue(const_cast<void*>(Ptr)); @@ -939,12 +975,15 @@ public: friend bool operator!=(const QualType &LHS, const QualType &RHS) { return LHS.Value != RHS.Value; } + std::string getAsString() const { return getAsString(split()); } + static std::string getAsString(SplitQualType split) { return getAsString(split.Ty, split.Quals); } + static std::string getAsString(const Type *ty, Qualifiers qs); std::string getAsString(const PrintingPolicy &Policy) const; @@ -954,11 +993,13 @@ public: unsigned Indentation = 0) const { print(split(), OS, Policy, PlaceHolder, Indentation); } + static void print(SplitQualType split, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, unsigned Indentation = 0) { return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); } + static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, @@ -968,10 +1009,12 @@ public: const PrintingPolicy &Policy) const { return getAsStringInternal(split(), Str, Policy); } + static void getAsStringInternal(SplitQualType split, std::string &out, const PrintingPolicy &policy) { return getAsStringInternal(split.Ty, split.Quals, out, policy); } + static void getAsStringInternal(const Type *ty, Qualifiers qs, std::string &out, const PrintingPolicy &policy); @@ -981,11 +1024,12 @@ public: const PrintingPolicy &Policy; const Twine &PlaceHolder; unsigned Indentation; + public: StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, const Twine &PlaceHolder, unsigned Indentation) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder), - Indentation(Indentation) { } + : T(T), Policy(Policy), PlaceHolder(PlaceHolder), + Indentation(Indentation) {} friend raw_ostream &operator<<(raw_ostream &OS, const StreamedQualTypeHelper &SQT) { @@ -1009,7 +1053,7 @@ public: } /// Return the address space of this type. - inline unsigned getAddressSpace() const; + inline LangAS getAddressSpace() const; /// Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; @@ -1129,13 +1173,15 @@ private: static DestructionKind isDestructedTypeImpl(QualType type); }; -} // end clang. +} // 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> { - typedef const ::clang::Type *SimpleType; + using SimpleType = const ::clang::Type *; + static SimpleType getSimplifiedValue(::clang::QualType Val) { return Val.getTypePtr(); } @@ -1143,29 +1189,30 @@ template<> struct simplify_type< ::clang::QualType> { // Teach SmallPtrSet that QualType is "basically a pointer". template<> -class PointerLikeTypeTraits<clang::QualType> { -public: +struct PointerLikeTypeTraits<clang::QualType> { static inline void *getAsVoidPointer(clang::QualType P) { return P.getAsOpaquePtr(); } + static inline clang::QualType getFromVoidPointer(void *P) { return clang::QualType::getFromOpaquePtr(P); } + // Various qualifiers go in low bits. enum { NumLowBitsAvailable = 0 }; }; -} // end namespace llvm +} // namespace llvm namespace clang { /// \brief 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 { - ExtQualsTypeCommonBase(const Type *baseType, QualType canon) - : BaseType(baseType), CanonicalType(canon) {} + friend class ExtQuals; + friend class QualType; + friend class Type; /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or /// a self-referential pointer (for \c Type). @@ -1177,9 +1224,8 @@ class ExtQualsTypeCommonBase { /// \brief The canonical type of this type. A QualType. QualType CanonicalType; - friend class QualType; - friend class Type; - friend class ExtQuals; + ExtQualsTypeCommonBase(const Type *baseType, QualType canon) + : BaseType(baseType), CanonicalType(canon) {} }; /// We can encode up to four bits in the low bits of a @@ -1214,10 +1260,9 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { public: ExtQuals(const Type *baseType, QualType canon, Qualifiers quals) - : ExtQualsTypeCommonBase(baseType, - canon.isNull() ? QualType(this_(), 0) : canon), - Quals(quals) - { + : ExtQualsTypeCommonBase(baseType, + canon.isNull() ? QualType(this_(), 0) : canon), + Quals(quals) { assert(Quals.hasNonFastQualifiers() && "ExtQuals created with no fast qualifiers"); assert(!Quals.hasFastQualifiers() @@ -1235,7 +1280,7 @@ public: } bool hasAddressSpace() const { return Quals.hasAddressSpace(); } - unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + LangAS getAddressSpace() const { return Quals.getAddressSpace(); } const Type *getBaseType() const { return BaseType; } @@ -1243,6 +1288,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getBaseType(), Quals); } + static void Profile(llvm::FoldingSetNodeID &ID, const Type *BaseType, Qualifiers Quals) { @@ -1258,8 +1304,10 @@ public: enum RefQualifierKind { /// \brief No ref-qualifier was provided. RQ_None = 0, + /// \brief An lvalue ref-qualifier was provided (\c &). RQ_LValue, + /// \brief An rvalue ref-qualifier was provided (\c &&). RQ_RValue }; @@ -1268,8 +1316,10 @@ enum RefQualifierKind { enum class AutoTypeKeyword { /// \brief auto Auto, + /// \brief decltype(auto) DecltypeAuto, + /// \brief __auto_type (GNU extension) GNUAutoType }; @@ -1311,9 +1361,6 @@ public: }; private: - Type(const Type &) = delete; - void operator=(const Type &) = delete; - /// Bitfields required by the Type class. class TypeBitfields { friend class Type; @@ -1352,10 +1399,12 @@ private: bool isCacheValid() const { return CacheValid; } + Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); return static_cast<Linkage>(CachedLinkage); } + bool hasLocalOrUnnamedType() const { assert(isCacheValid() && "getting linkage from invalid cache"); return CachedLocalOrUnnamed; @@ -1392,8 +1441,8 @@ protected: }; class FunctionTypeBitfields { - friend class FunctionType; friend class FunctionProtoType; + friend class FunctionType; unsigned : NumTypeBits; @@ -1429,6 +1478,7 @@ protected: /// Whether this is a "kindof" type. unsigned IsKindOf : 1; }; + static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned"); class ReferenceTypeBitfields { @@ -1511,21 +1561,21 @@ protected: }; private: + template <class T> friend class TypePropertyCache; + /// \brief Set whether this type comes from an AST file. void setFromAST(bool V = true) const { TypeBits.FromAST = V; } - template <class T> friend class TypePropertyCache; - protected: - // silence VC++ warning C4355: 'this' : used in base member initializer list - Type *this_() { return this; } + friend class ASTContext; + Type(TypeClass tc, QualType canon, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : ExtQualsTypeCommonBase(this, - canon.isNull() ? QualType(this_(), 0) : canon) { + : ExtQualsTypeCommonBase(this, + canon.isNull() ? QualType(this_(), 0) : canon) { TypeBits.TC = tc; TypeBits.Dependent = Dependent; TypeBits.InstantiationDependent = Dependent || InstantiationDependent; @@ -1536,22 +1586,32 @@ protected: TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; } - friend class ASTContext; + + // silence VC++ warning C4355: 'this' : used in base member initializer list + Type *this_() { return this; } void setDependent(bool D = true) { TypeBits.Dependent = D; if (D) TypeBits.InstantiationDependent = true; } + void setInstantiationDependent(bool D = true) { TypeBits.InstantiationDependent = D; } - void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; - } + + void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } + void setContainsUnexpandedParameterPack(bool PP = true) { TypeBits.ContainsUnexpandedParameterPack = PP; } public: + friend class ASTReader; + friend class ASTWriter; + + Type(const Type &) = delete; + Type &operator=(const Type &) = delete; + TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); } /// \brief Whether this type comes from an AST file. @@ -1658,6 +1718,7 @@ public: /// Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; + /// Determine whether this type is an integral or unscoped enumeration type. bool isIntegralOrUnscopedEnumerationType() const; @@ -1708,6 +1769,7 @@ public: bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. + bool isDependentAddressSpaceType() const; // value-dependent address space qualifier bool isObjCObjectPointerType() const; // pointer to ObjC object bool isObjCRetainableType() const; // ObjC object or block pointer bool isObjCLifetimeType() const; // (array of)* retainable type @@ -1789,6 +1851,7 @@ public: STK_IntegralComplex, STK_FloatingComplex }; + /// Given that this is a scalar type, classify it. ScalarTypeKind getScalarTypeKind() const; @@ -1859,6 +1922,7 @@ public: const RecordType *getAsUnionType() const; const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. const ObjCObjectType *getAsObjCInterfaceType() const; + // The following is a convenience method that returns an ObjCObjectPointerType // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; @@ -2045,12 +2109,10 @@ public: QualType getCanonicalTypeInternal() const { return CanonicalType; } + CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; void dump(llvm::raw_ostream &OS) const; - - friend class ASTReader; - friend class ASTWriter; }; /// \brief This will check for a TypedefType by removing any existing sugar @@ -2078,7 +2140,6 @@ template <> inline const Class##Type *Type::castAs() const { \ } #include "clang/AST/TypeNodes.def" - /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { @@ -2095,15 +2156,16 @@ public: public: BuiltinType(Kind K) - : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), - /*InstantiationDependent=*/(K == Dependent), - /*VariablyModified=*/false, - /*Unexpanded parameter pack=*/false) { + : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), + /*InstantiationDependent=*/(K == Dependent), + /*VariablyModified=*/false, + /*Unexpanded parameter pack=*/false) { BuiltinTypeBits.Kind = K; } Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } StringRef getName(const PrintingPolicy &Policy) const; + const char *getNameAsCString(const PrintingPolicy &Policy) const { // The StringRef is null-terminated. StringRef str = getName(Policy); @@ -2160,17 +2222,17 @@ public: /// 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 { + friend class ASTContext; // ASTContext creates these. + QualType ElementType; - ComplexType(QualType Element, QualType CanonicalPtr) : - Type(Complex, CanonicalPtr, Element->isDependentType(), - Element->isInstantiationDependentType(), - Element->isVariablyModifiedType(), - Element->containsUnexpandedParameterPack()), - ElementType(Element) { - } - friend class ASTContext; // ASTContext creates these. + + ComplexType(QualType Element, QualType CanonicalPtr) + : Type(Complex, CanonicalPtr, Element->isDependentType(), + Element->isInstantiationDependentType(), + Element->isVariablyModifiedType(), + Element->containsUnexpandedParameterPack()), + ElementType(Element) {} public: QualType getElementType() const { return ElementType; } @@ -2181,6 +2243,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) { ID.AddPointer(Element.getAsOpaquePtr()); } @@ -2189,21 +2252,19 @@ public: }; /// Sugar for parentheses used when specifying types. -/// class ParenType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType Inner; - ParenType(QualType InnerType, QualType CanonType) : - Type(Paren, CanonType, InnerType->isDependentType(), - InnerType->isInstantiationDependentType(), - InnerType->isVariablyModifiedType(), - InnerType->containsUnexpandedParameterPack()), - Inner(InnerType) { - } - friend class ASTContext; // ASTContext creates these. + ParenType(QualType InnerType, QualType CanonType) + : Type(Paren, CanonType, InnerType->isDependentType(), + InnerType->isInstantiationDependentType(), + InnerType->isVariablyModifiedType(), + InnerType->containsUnexpandedParameterPack()), + Inner(InnerType) {} public: - QualType getInnerType() const { return Inner; } bool isSugared() const { return true; } @@ -2212,6 +2273,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getInnerType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) { Inner.Profile(ID); } @@ -2220,21 +2282,19 @@ public: }; /// PointerType - C99 6.7.5.1 - Pointer Declarators. -/// class PointerType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; - PointerType(QualType Pointee, QualType CanonicalPtr) : - Type(Pointer, CanonicalPtr, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. + PointerType(QualType Pointee, QualType CanonicalPtr) + : Type(Pointer, CanonicalPtr, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} public: - QualType getPointeeType() const { return PointeeType; } /// Returns true if address spaces of pointers overlap. @@ -2259,6 +2319,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { ID.AddPointer(Pointee.getAsOpaquePtr()); } @@ -2274,6 +2335,8 @@ class AdjustedType : public Type, public llvm::FoldingSetNode { QualType AdjustedTy; protected: + friend class ASTContext; // ASTContext creates these. + AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, QualType CanonicalPtr) : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), @@ -2282,8 +2345,6 @@ protected: OriginalTy->containsUnexpandedParameterPack()), OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} - friend class ASTContext; // ASTContext creates these. - public: QualType getOriginalType() const { return OriginalTy; } QualType getAdjustedType() const { return AdjustedTy; } @@ -2294,6 +2355,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, OriginalTy, AdjustedTy); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) { ID.AddPointer(Orig.getAsOpaquePtr()); ID.AddPointer(New.getAsOpaquePtr()); @@ -2306,12 +2368,11 @@ public: /// Represents a pointer type decayed from an array or function type. class DecayedType : public AdjustedType { + friend class ASTContext; // ASTContext creates these. inline DecayedType(QualType OriginalType, QualType Decayed, QualType Canonical); - friend class ASTContext; // ASTContext creates these. - public: QualType getDecayedType() const { return getAdjustedType(); } @@ -2323,20 +2384,20 @@ public: /// 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 { - QualType PointeeType; // Block is some kind of pointer type - BlockPointerType(QualType Pointee, QualType CanonicalCls) : - Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. + friend class ASTContext; // ASTContext creates these. -public: + // Block is some kind of pointer type + QualType PointeeType; + BlockPointerType(QualType Pointee, QualType CanonicalCls) + : Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} + +public: // Get the pointee type. Pointee is required to always be a function type. QualType getPointeeType() const { return PointeeType; } @@ -2346,6 +2407,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { ID.AddPointer(Pointee.getAsOpaquePtr()); } @@ -2356,19 +2418,17 @@ public: }; /// Base for LValueReferenceType and RValueReferenceType -/// class ReferenceType : public Type, public llvm::FoldingSetNode { QualType PointeeType; protected: ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - Type(tc, CanonicalRef, Referencee->isDependentType(), - Referencee->isInstantiationDependentType(), - Referencee->isVariablyModifiedType(), - Referencee->containsUnexpandedParameterPack()), - PointeeType(Referencee) - { + bool SpelledAsLValue) + : Type(tc, CanonicalRef, Referencee->isDependentType(), + Referencee->isInstantiationDependentType(), + Referencee->isVariablyModifiedType(), + Referencee->containsUnexpandedParameterPack()), + PointeeType(Referencee) { ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); } @@ -2378,6 +2438,7 @@ public: bool isInnerRef() const { return ReferenceTypeBits.InnerRef; } QualType getPointeeTypeAsWritten() const { return PointeeType; } + QualType getPointeeType() const { // FIXME: this might strip inner qualifiers; okay? const ReferenceType *T = this; @@ -2389,6 +2450,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, PointeeType, isSpelledAsLValue()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee, bool SpelledAsLValue) { @@ -2403,13 +2465,14 @@ public: }; /// An lvalue reference type, per C++11 [dcl.ref]. -/// class LValueReferenceType : public ReferenceType { - LValueReferenceType(QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) - {} friend class ASTContext; // ASTContext creates these + + LValueReferenceType(QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) + : ReferenceType(LValueReference, Referencee, CanonicalRef, + SpelledAsLValue) {} + public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2420,12 +2483,12 @@ public: }; /// An rvalue reference type, per C++11 [dcl.ref]. -/// class RValueReferenceType : public ReferenceType { - RValueReferenceType(QualType Referencee, QualType CanonicalRef) : - ReferenceType(RValueReference, Referencee, CanonicalRef, false) { - } friend class ASTContext; // ASTContext creates these + + RValueReferenceType(QualType Referencee, QualType CanonicalRef) + : ReferenceType(RValueReference, Referencee, CanonicalRef, false) {} + public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2438,24 +2501,24 @@ public: /// 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 { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; + /// The class of which the pointee is a member. Must ultimately be a /// RecordType, but could be a typedef or a template parameter too. const Type *Class; - MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : - Type(MemberPointer, CanonicalPtr, - Cls->isDependentType() || Pointee->isDependentType(), - (Cls->isInstantiationDependentType() || - Pointee->isInstantiationDependentType()), - Pointee->isVariablyModifiedType(), - (Cls->containsUnexpandedParameterPack() || - Pointee->containsUnexpandedParameterPack())), - PointeeType(Pointee), Class(Cls) { - } - friend class ASTContext; // ASTContext creates these. + MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) + : Type(MemberPointer, CanonicalPtr, + Cls->isDependentType() || Pointee->isDependentType(), + (Cls->isInstantiationDependentType() || + Pointee->isInstantiationDependentType()), + Pointee->isVariablyModifiedType(), + (Cls->containsUnexpandedParameterPack() || + Pointee->containsUnexpandedParameterPack())), + PointeeType(Pointee), Class(Cls) {} public: QualType getPointeeType() const { return PointeeType; } @@ -2481,6 +2544,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType(), getClass()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, const Type *Class) { ID.AddPointer(Pointee.getAsOpaquePtr()); @@ -2493,7 +2557,6 @@ public: }; /// Represents an array type, per C99 6.7.5.2 - Array Declarators. -/// class ArrayType : public Type, public llvm::FoldingSetNode { public: /// Capture whether this is a normal array (e.g. int X[4]) @@ -2503,11 +2566,14 @@ public: enum ArraySizeModifier { Normal, Static, Star }; + private: /// The element type of the array. QualType ElementType; protected: + friend class ASTContext; // ASTContext creates these. + // C++ [temp.dep.type]p1: // A type is dependent if it is... // - an array type constructed from any dependent type or whose @@ -2516,25 +2582,26 @@ protected: ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm, unsigned tq, bool ContainsUnexpandedParameterPack) - : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, - et->isInstantiationDependentType() || tc == DependentSizedArray, - (tc == VariableArray || et->isVariablyModifiedType()), - ContainsUnexpandedParameterPack), - ElementType(et) { + : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, + et->isInstantiationDependentType() || tc == DependentSizedArray, + (tc == VariableArray || et->isVariablyModifiedType()), + ContainsUnexpandedParameterPack), + ElementType(et) { ArrayTypeBits.IndexTypeQuals = tq; ArrayTypeBits.SizeModifier = sm; } - friend class ASTContext; // ASTContext creates these. - public: QualType getElementType() const { return ElementType; } + ArraySizeModifier getSizeModifier() const { return ArraySizeModifier(ArrayTypeBits.SizeModifier); } + Qualifiers getIndexTypeQualifiers() const { return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers()); } + unsigned getIndexTypeCVRQualifiers() const { return ArrayTypeBits.IndexTypeQuals; } @@ -2555,21 +2622,23 @@ class ConstantArrayType : public ArrayType { ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - Size(size) {} + : ArrayType(ConstantArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), + Size(size) {} + protected: + friend class ASTContext; // ASTContext creates these. + ConstantArrayType(TypeClass tc, QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), - Size(size) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), + Size(size) {} + public: const llvm::APInt &getSize() const { return Size; } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - /// \brief Determine the number of bits required to address a member of // an array with the given element type and number of elements. static unsigned getNumAddressingBits(const ASTContext &Context, @@ -2584,6 +2653,7 @@ public: Profile(ID, getElementType(), getSize(), getSizeModifier(), getIndexTypeCVRQualifiers()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, unsigned TypeQuals) { @@ -2592,6 +2662,7 @@ public: ID.AddInteger(SizeMod); ID.AddInteger(TypeQuals); } + static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; } @@ -2601,13 +2672,16 @@ public: /// an IncompleteArrayType where the element type is 'int' and the size is /// unspecified. class IncompleteArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(IncompleteArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()) {} + public: + friend class StmtIteratorBase; + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2615,8 +2689,6 @@ public: return T->getTypeClass() == IncompleteArray; } - friend class StmtIteratorBase; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers()); @@ -2644,28 +2716,32 @@ public: /// ++x; /// int Z[x]; /// } -/// class VariableArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. + /// An assignment-expression. VLA's are only permitted within /// a function block. Stmt *SizeExpr; + /// The range spanned by the left and right array brackets. SourceRange Brackets; VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - SizeExpr((Stmt*) e), Brackets(brackets) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(VariableArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), + SizeExpr((Stmt*) e), Brackets(brackets) {} public: + friend class StmtIteratorBase; + Expr *getSizeExpr() const { // We use C-style casts instead of cast<> here because we do not wish // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } @@ -2677,8 +2753,6 @@ public: return T->getTypeClass() == VariableArray; } - friend class StmtIteratorBase; - void Profile(llvm::FoldingSetNodeID &ID) { llvm_unreachable("Cannot unique VariableArrayTypes."); } @@ -2698,6 +2772,8 @@ public: /// until template instantiation occurs, at which point this will /// become either a ConstantArrayType or a VariableArrayType. class DependentSizedArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. + const ASTContext &Context; /// \brief An assignment expression that will instantiate to the @@ -2714,14 +2790,15 @@ class DependentSizedArrayType : public ArrayType { Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets); - friend class ASTContext; // ASTContext creates these. - public: + friend class StmtIteratorBase; + Expr *getSizeExpr() const { // We use C-style casts instead of cast<> here because we do not wish // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } @@ -2733,9 +2810,6 @@ public: return T->getTypeClass() == DependentSizedArray; } - friend class StmtIteratorBase; - - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); @@ -2746,6 +2820,49 @@ public: unsigned TypeQuals, Expr *E); }; +/// 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 { + friend class ASTContext; + + const ASTContext &Context; + Expr *AddrSpaceExpr; + QualType PointeeType; + SourceLocation loc; + + DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType, + QualType can, Expr *AddrSpaceExpr, + SourceLocation loc); + +public: + Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; } + QualType getPointeeType() const { return PointeeType; } + SourceLocation getAttributeLoc() const { return loc; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentAddressSpace; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getPointeeType(), getAddrSpaceExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType PointeeType, Expr *AddrSpaceExpr); +}; + /// Represents an extended vector type where either the type or size is /// dependent. /// @@ -2757,17 +2874,19 @@ public: /// } /// \endcode class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + const ASTContext &Context; Expr *SizeExpr; + /// The element type of the array. QualType ElementType; + SourceLocation loc; DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, QualType can, Expr *SizeExpr, SourceLocation loc); - friend class ASTContext; - public: Expr *getSizeExpr() const { return SizeExpr; } QualType getElementType() const { return ElementType; } @@ -2797,14 +2916,28 @@ public: class VectorType : public Type, public llvm::FoldingSetNode { public: enum VectorKind { - GenericVector, ///< not a target-specific vector type - AltiVecVector, ///< is AltiVec vector - AltiVecPixel, ///< is AltiVec 'vector Pixel' - AltiVecBool, ///< is AltiVec 'vector bool ...' - NeonVector, ///< is ARM Neon vector - NeonPolyVector ///< is ARM Neon polynomial vector + /// not a target-specific vector type + GenericVector, + + /// is AltiVec vector + AltiVecVector, + + /// is AltiVec 'vector Pixel' + AltiVecPixel, + + /// is AltiVec 'vector bool ...' + AltiVecBool, + + /// is ARM Neon vector + NeonVector, + + /// is ARM Neon polynomial vector + NeonPolyVector }; + protected: + friend class ASTContext; // ASTContext creates these. + /// The element type of the vector. QualType ElementType; @@ -2814,12 +2947,10 @@ protected: VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind); - friend class ASTContext; // ASTContext creates these. - public: - QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return VectorTypeBits.NumElements; } + static bool isVectorSizeTooLarge(unsigned NumElements) { return NumElements > VectorTypeBitfields::MaxNumElements; } @@ -2835,6 +2966,7 @@ public: Profile(ID, getElementType(), getNumElements(), getTypeClass(), getVectorKind()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, unsigned NumElements, TypeClass TypeClass, VectorKind VecKind) { @@ -2856,9 +2988,11 @@ public: /// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL /// Shading Language). class ExtVectorType : public VectorType { - ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : - VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} - friend class ASTContext; // ASTContext creates these. + friend class ASTContext; // ASTContext creates these. + + ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) + : VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} + public: static int getPointAccessorIdx(char c) { switch (c) { @@ -2869,6 +3003,7 @@ public: case 'w': case 'a': return 3; } } + static int getNumericAccessorIdx(char c) { switch (c) { default: return -1; @@ -2909,6 +3044,7 @@ public: return unsigned(idx-1) < getNumElements(); return false; } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2919,12 +3055,11 @@ public: /// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base /// class of FunctionNoProtoType and FunctionProtoType. -/// class FunctionType : public Type { // The type returned by the function. QualType ResultType; - public: +public: /// A class which abstracts out some details necessary for /// making a call. /// @@ -2946,6 +3081,8 @@ class FunctionType : public Type { // * AST read and write // * Codegen class ExtInfo { + friend class FunctionType; + // Feel free to rearrange or add bits, but if you go over 11, // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. @@ -2964,15 +3101,13 @@ class FunctionType : public Type { RegParmOffset = 8 }; // Assumed to be the last field - uint16_t Bits; + uint16_t Bits = CC_C; ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} - friend class FunctionType; - public: - // Constructor with no defaults. Use this when you know that you - // have all the elements (when reading an AST file for example). + // Constructor with no defaults. Use this when you know that you + // have all the elements (when reading an AST file for example). ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc, bool producesResult, bool noCallerSavedRegs) { assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); @@ -2984,22 +3119,24 @@ class FunctionType : public Type { // Constructor with all defaults. Use when for example creating a // function known to use defaults. - ExtInfo() : Bits(CC_C) { } + ExtInfo() = default; // Constructor with just the calling convention, which is an important part // of the canonical type. - ExtInfo(CallingConv CC) : Bits(CC) { } + ExtInfo(CallingConv CC) : Bits(CC) {} bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; } bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } + unsigned getRegParm() const { unsigned RegParm = Bits >> RegParmOffset; if (RegParm > 0) --RegParm; return RegParm; } + CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } bool operator==(ExtInfo Other) const { @@ -3054,11 +3191,12 @@ protected: bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack), - ResultType(res) { + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + ContainsUnexpandedParameterPack), + ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; } + unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: @@ -3066,10 +3204,12 @@ public: bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } + /// Determine whether this function type includes the GNU noreturn /// attribute. The C++11 [[noreturn]] attribute does not affect the function /// type. bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } + CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } bool isConst() const { return getTypeQuals() & Qualifiers::Const; } @@ -3093,13 +3233,13 @@ public: /// Represents a K&R-style 'int foo()' function, which has /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { - FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, Canonical, - /*Dependent=*/false, /*InstantiationDependent=*/false, - Result->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false, Info) {} + friend class ASTContext; // ASTContext creates these. - friend class ASTContext; // ASTContext creates these. + FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) + : FunctionType(FunctionNoProto, Result, Canonical, + /*Dependent=*/false, /*InstantiationDependent=*/false, + Result->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false, Info) {} public: // No additional state past what FunctionType provides. @@ -3110,6 +3250,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReturnType(), getExtInfo()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, ExtInfo Info) { Info.Profile(ID); @@ -3152,11 +3293,12 @@ public: ABIMask = 0x0F, IsConsumed = 0x10, HasPassObjSize = 0x20, + IsNoEscape = 0x40, }; - unsigned char Data; + unsigned char Data = 0; public: - ExtParameterInfo() : Data(0) {} + ExtParameterInfo() = default; /// Return the ABI treatment of this parameter. ParameterABI getABI() const { @@ -3192,6 +3334,19 @@ public: return Copy; } + bool isNoEscape() const { + return Data & IsNoEscape; + } + + ExtParameterInfo withIsNoEscape(bool NoEscape) const { + ExtParameterInfo Copy = *this; + if (NoEscape) + Copy.Data |= IsNoEscape; + else + Copy.Data &= ~IsNoEscape; + return Copy; + } + unsigned char getOpaqueValue() const { return Data; } static ExtParameterInfo getFromOpaqueValue(unsigned char data) { ExtParameterInfo result; @@ -3208,54 +3363,54 @@ public: }; struct ExceptionSpecInfo { - ExceptionSpecInfo() - : Type(EST_None), NoexceptExpr(nullptr), - SourceDecl(nullptr), SourceTemplate(nullptr) {} - - ExceptionSpecInfo(ExceptionSpecificationType EST) - : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), - SourceTemplate(nullptr) {} - /// The kind of exception specification this is. - ExceptionSpecificationType Type; + ExceptionSpecificationType Type = EST_None; + /// Explicitly-specified list of exception types. ArrayRef<QualType> Exceptions; + /// Noexcept expression, if this is EST_ComputedNoexcept. - Expr *NoexceptExpr; + Expr *NoexceptExpr = nullptr; + /// The function whose exception specification this is, for /// EST_Unevaluated and EST_Uninstantiated. - FunctionDecl *SourceDecl; + FunctionDecl *SourceDecl = nullptr; + /// The function template whose exception specification this is instantiated /// from, for EST_Uninstantiated. - FunctionDecl *SourceTemplate; + FunctionDecl *SourceTemplate = nullptr; + + ExceptionSpecInfo() = default; + + ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {} }; /// Extra information about a function prototype. struct ExtProtoInfo { + FunctionType::ExtInfo ExtInfo; + bool Variadic : 1; + bool HasTrailingReturn : 1; + unsigned char TypeQuals = 0; + RefQualifierKind RefQualifier = RQ_None; + ExceptionSpecInfo ExceptionSpec; + const ExtParameterInfo *ExtParameterInfos = nullptr; + ExtProtoInfo() - : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} + : Variadic(false), HasTrailingReturn(false) {} ExtProtoInfo(CallingConv CC) - : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} + : ExtInfo(CC), Variadic(false), HasTrailingReturn(false) {} ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { ExtProtoInfo Result(*this); Result.ExceptionSpec = O; return Result; } - - FunctionType::ExtInfo ExtInfo; - bool Variadic : 1; - bool HasTrailingReturn : 1; - unsigned char TypeQuals; - RefQualifierKind RefQualifier; - ExceptionSpecInfo ExceptionSpec; - const ExtParameterInfo *ExtParameterInfos; }; private: + friend class ASTContext; // ASTContext creates these. + /// \brief Determine whether there are any argument types that /// contain an unexpanded parameter pack. static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, @@ -3307,8 +3462,6 @@ private: // for each of the parameters. This only appears if HasExtParameterInfos // is true. - friend class ASTContext; // ASTContext creates these. - const ExtParameterInfo *getExtParameterInfosBuffer() const { assert(hasExtParameterInfos()); @@ -3336,10 +3489,12 @@ private: public: unsigned getNumParams() const { return NumParams; } + QualType getParamType(unsigned i) const { assert(i < NumParams && "invalid parameter index"); return param_type_begin()[i]; } + ArrayRef<QualType> getParamTypes() const { return llvm::makeArrayRef(param_type_begin(), param_type_end()); } @@ -3371,31 +3526,47 @@ public: ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); } + /// Return whether this function has any kind of exception spec. bool hasExceptionSpec() const { return getExceptionSpecType() != EST_None; } + /// Return whether this function has a dynamic (throw) exception spec. bool hasDynamicExceptionSpec() const { return isDynamicExceptionSpec(getExceptionSpecType()); } + /// Return whether this function has a noexcept exception spec. bool hasNoexceptExceptionSpec() const { return isNoexceptExceptionSpec(getExceptionSpecType()); } + /// Return whether this function has a dependent exception spec. bool hasDependentExceptionSpec() const; + /// Return whether this function has an instantiation-dependent exception /// spec. bool hasInstantiationDependentExceptionSpec() const; + /// Result type of getNoexceptSpec(). enum NoexceptResult { - NR_NoNoexcept, ///< There is no noexcept specifier. - NR_BadNoexcept, ///< The noexcept specifier has a bad expression. - NR_Dependent, ///< The noexcept specifier is dependent. - NR_Throw, ///< The noexcept specifier evaluates to false. - NR_Nothrow ///< The noexcept specifier evaluates to true. + /// There is no noexcept specifier. + NR_NoNoexcept, + + /// The noexcept specifier has a bad expression. + NR_BadNoexcept, + + /// The noexcept specifier is dependent. + NR_Dependent, + + /// The noexcept specifier evaluates to false. + NR_Throw, + + /// The noexcept specifier evaluates to true. + NR_Nothrow }; + /// Get the meaning of the noexcept spec on this function, if any. NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } @@ -3409,6 +3580,7 @@ public: // NoexceptExpr sits where the arguments end. return *reinterpret_cast<Expr *const *>(param_type_end()); } + /// \brief If this function type has an exception specification which hasn't /// been determined yet (either because it has not been evaluated or because /// it has not been instantiated), this is the function whose exception @@ -3419,6 +3591,7 @@ public: return nullptr; return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; } + /// \brief If this function type has an uninstantiated exception /// specification, this is the function whose exception specification /// should be instantiated to find the exception specification for @@ -3428,9 +3601,11 @@ public: return nullptr; return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; } + /// Determine whether this function type has a non-throwing exception /// specification. CanThrowResult canThrow(const ASTContext &Ctx) const; + /// Determine whether this function type has a non-throwing exception /// specification. If this depends on template arguments, returns /// \c ResultIfDependent. @@ -3453,34 +3628,37 @@ public: unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } - /// Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } - typedef const QualType *param_type_iterator; - typedef llvm::iterator_range<param_type_iterator> param_type_range; + using param_type_iterator = const QualType *; + using param_type_range = llvm::iterator_range<param_type_iterator>; param_type_range param_types() const { return param_type_range(param_type_begin(), param_type_end()); } + param_type_iterator param_type_begin() const { return reinterpret_cast<const QualType *>(this+1); } + param_type_iterator param_type_end() const { return param_type_begin() + NumParams; } - typedef const QualType *exception_iterator; + using exception_iterator = const QualType *; ArrayRef<QualType> exceptions() const { return llvm::makeArrayRef(exception_begin(), exception_end()); } + exception_iterator exception_begin() const { // exceptions begin where arguments end return param_type_end(); } + exception_iterator exception_end() const { if (getExceptionSpecType() != EST_Dynamic) return exception_begin(); @@ -3495,6 +3673,7 @@ public: return ArrayRef<ExtParameterInfo>(getExtParameterInfosBuffer(), getNumParams()); } + /// Return a pointer to the beginning of the array of extra parameter /// information, if present, or else null if none of the parameters /// carry it. This is equivalent to getExtProtoInfo().ExtParameterInfos. @@ -3548,15 +3727,16 @@ public: /// /// Template instantiation turns these into the underlying type. class UnresolvedUsingType : public Type { + friend class ASTContext; // ASTContext creates these. + UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, true, false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. -public: + : Type(UnresolvedUsing, QualType(), true, true, false, + /*ContainsUnexpandedParameterPack=*/false), + Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} +public: UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } bool isSugared() const { return false; } @@ -3569,27 +3749,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { return Profile(ID, Decl); } + static void Profile(llvm::FoldingSetNodeID &ID, UnresolvedUsingTypenameDecl *D) { ID.AddPointer(D); } }; - class TypedefType : public Type { TypedefNameDecl *Decl; + protected: + friend class ASTContext; // ASTContext creates these. + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefNameDecl*>(D)) { + : Type(tc, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } - friend class ASTContext; // ASTContext creates these. -public: +public: TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } @@ -3603,8 +3785,10 @@ class TypeOfExprType : public Type { Expr *TOExpr; protected: + friend class ASTContext; // ASTContext creates these. + TypeOfExprType(Expr *E, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. + public: Expr *getUnderlyingExpr() const { return TOExpr; } @@ -3629,7 +3813,7 @@ class DependentTypeOfExprType public: DependentTypeOfExprType(const ASTContext &Context, Expr *E) - : TypeOfExprType(E), Context(Context) { } + : TypeOfExprType(E), Context(Context) {} void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getUnderlyingExpr()); @@ -3641,16 +3825,19 @@ public: /// Represents `typeof(type)`, a GCC extension. class TypeOfType : public Type { + friend class ASTContext; // ASTContext creates these. + QualType TOType; + TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), - T->isInstantiationDependentType(), - T->isVariablyModifiedType(), - T->containsUnexpandedParameterPack()), - TOType(T) { + : Type(TypeOf, can, T->isDependentType(), + T->isInstantiationDependentType(), + T->isVariablyModifiedType(), + T->containsUnexpandedParameterPack()), + TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } - friend class ASTContext; // ASTContext creates these. + public: QualType getUnderlyingType() const { return TOType; } @@ -3669,8 +3856,10 @@ class DecltypeType : public Type { QualType UnderlyingType; protected: + friend class ASTContext; // ASTContext creates these. + DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. + public: Expr *getUnderlyingExpr() const { return E; } QualType getUnderlyingType() const { return UnderlyingType; } @@ -3714,14 +3903,18 @@ public: 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); - friend class ASTContext; + public: bool isSugared() const { return !isDependentType(); } QualType desugar() const { return UnderlyingType; } @@ -3747,6 +3940,7 @@ class DependentUnaryTransformType : public UnaryTransformType, public: DependentUnaryTransformType(const ASTContext &C, QualType BaseType, UTTKind UKind); + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getBaseType(), getUTTKind()); } @@ -3759,11 +3953,11 @@ public: }; class TagType : public Type { + friend class ASTReader; + /// Stores the TagDecl associated with this type. The decl may point to any /// TagDecl that declares the entity. - TagDecl * decl; - - friend class ASTReader; + TagDecl *decl; protected: TagType(TypeClass TC, const TagDecl *D, QualType can); @@ -3783,21 +3977,21 @@ public: /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { protected: + friend class ASTContext; // ASTContext creates these. + explicit RecordType(const RecordDecl *D) - : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { } + : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) {} explicit RecordType(TypeClass TC, RecordDecl *D) - : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: + : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) {} +public: RecordDecl *getDecl() const { return reinterpret_cast<RecordDecl*>(TagType::getDecl()); } - // FIXME: This predicate is a helper to QualType/Type. It needs to - // recursively check all fields for const-ness. If any field is declared - // const, it needs to return false. - bool hasConstFields() const { return false; } + /// Recursively check all fields in the record for const-ness. If any field + /// is declared const, return true. Otherwise, return false. + bool hasConstFields() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -3808,11 +4002,12 @@ public: /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { + friend class ASTContext; // ASTContext creates these. + explicit EnumType(const EnumDecl *D) - : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: + : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) {} +public: EnumDecl *getDecl() const { return reinterpret_cast<EnumDecl*>(TagType::getDecl()); } @@ -3887,11 +4082,11 @@ public: }; private: + friend class ASTContext; // ASTContext creates these + QualType ModifiedType; QualType EquivalentType; - friend class ASTContext; // creates these - AttributedType(QualType canon, Kind attrKind, QualType modified, QualType equivalent) : Type(Attributed, canon, equivalent->isDependentType(), @@ -3980,6 +4175,8 @@ public: }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + // Helper data collector for canonical types. struct CanonicalTTPTInfo { unsigned Depth : 15; @@ -3990,31 +4187,30 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { union { // Info for the canonical type. CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. TemplateTypeParmDecl *TTPDecl; }; /// Build a non-canonical type. TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) - : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - Canon->containsUnexpandedParameterPack()), - TTPDecl(TTPDecl) { } + : Type(TemplateTypeParm, Canon, /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + Canon->containsUnexpandedParameterPack()), + TTPDecl(TTPDecl) {} /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), - /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, PP) { + : Type(TemplateTypeParm, QualType(this, 0), + /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, PP) { CanTTPTInfo.Depth = D; CanTTPTInfo.Index = I; CanTTPTInfo.ParameterPack = PP; } - friend class ASTContext; // ASTContext creates these - const CanonicalTTPTInfo& getCanTTPTInfo() const { QualType Can = getCanonicalTypeInternal(); return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo; @@ -4060,17 +4256,17 @@ public: /// type was originally written as a template type parameter; /// therefore they are never canonical. class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + // The original type parameter. const TemplateTypeParmType *Replaced; SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), - Canon->isInstantiationDependentType(), - Canon->isVariablyModifiedType(), - Canon->containsUnexpandedParameterPack()), - Replaced(Param) { } - - friend class ASTContext; + : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), + Canon->isInstantiationDependentType(), + Canon->isVariablyModifiedType(), + Canon->containsUnexpandedParameterPack()), + Replaced(Param) {} public: /// Gets the template parameter that was substituted for. @@ -4090,6 +4286,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReplacedParameter(), getReplacementType()); } + static void Profile(llvm::FoldingSetNodeID &ID, const TemplateTypeParmType *Replaced, QualType Replacement) { @@ -4115,6 +4312,8 @@ public: /// arguments), this type will be replaced with the \c SubstTemplateTypeParmType /// at the current pack substitution index. class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + /// \brief The original type parameter. const TemplateTypeParmType *Replaced; @@ -4129,8 +4328,6 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { QualType Canon, const TemplateArgument &ArgPack); - friend class ASTContext; - public: IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } @@ -4204,6 +4401,8 @@ public: /// \brief Represents a C++11 auto or C++14 decltype(auto) type. class AutoType : public DeducedType, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, bool IsDeducedAsDependent) : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent, @@ -4211,12 +4410,11 @@ class AutoType : public DeducedType, public llvm::FoldingSetNode { AutoTypeBits.Keyword = (unsigned)Keyword; } - friend class ASTContext; // ASTContext creates these - public: bool isDecltypeAuto() const { return getKeyword() == AutoTypeKeyword::DecltypeAuto; } + AutoTypeKeyword getKeyword() const { return (AutoTypeKeyword)AutoTypeBits.Keyword; } @@ -4240,6 +4438,8 @@ public: /// \brief Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public DeducedType, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + /// The name of the template whose arguments will be deduced. TemplateName Template; @@ -4252,8 +4452,6 @@ class DeducedTemplateSpecializationType : public DeducedType, Template.containsUnexpandedParameterPack()), Template(Template) {} - friend class ASTContext; // ASTContext creates these - public: /// Retrieve the name of the template that we are deducing. TemplateName getTemplateName() const { return Template;} @@ -4297,6 +4495,8 @@ public: class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType : public Type, 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 @@ -4318,8 +4518,6 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType QualType Canon, QualType Aliased); - friend class ASTContext; // ASTContext creates these - public: /// Determine whether any of the given template arguments are dependent. static bool anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, @@ -4328,21 +4526,6 @@ public: static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, bool &InstantiationDependent); - /// \brief Print a template argument list, including the '<' and '>' - /// enclosing the template arguments. - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef<TemplateArgument> Args, - const PrintingPolicy &Policy, - bool SkipBrackets = false); - - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef<TemplateArgumentLoc> Args, - const PrintingPolicy &Policy); - - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &, - const PrintingPolicy &Policy); - /// True if this template specialization type matches a current /// instantiation in the context in which it is found. bool isCurrentInstantiation() const { @@ -4373,7 +4556,7 @@ public: return *reinterpret_cast<const QualType*>(end()); } - typedef const TemplateArgument * iterator; + using iterator = const TemplateArgument *; iterator begin() const { return getArgs(); } iterator end() const; // defined inline in TemplateBase.h @@ -4400,6 +4583,7 @@ public: bool isSugared() const { return !isDependentType() || isCurrentInstantiation() || isTypeAlias(); } + QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { @@ -4417,6 +4601,20 @@ public: } }; +/// \brief Print a template argument list, including the '<' and '>' +/// enclosing the template arguments. +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgument> Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgumentLoc> Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy); + /// 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 @@ -4435,6 +4633,12 @@ public: /// will canonicalize to the injected class name (when appropriate /// according to the rules of the language). class InjectedClassNameType : public Type { + friend class ASTContext; // ASTContext creates these. + friend class ASTNodeImporter; + friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not + // currently suitable for AST reading, too much + // interdependencies. + CXXRecordDecl *Decl; /// The template specialization which this type represents. @@ -4448,18 +4652,12 @@ class InjectedClassNameType : public Type { /// and always dependent. QualType InjectedType; - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not - // currently suitable for AST reading, too much - // interdependencies. - friend class ASTNodeImporter; - InjectedClassNameType(CXXRecordDecl *D, QualType TST) - : Type(InjectedClassName, QualType(), /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(D), InjectedType(TST) { + : Type(InjectedClassName, QualType(), /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + /*ContainsUnexpandedParameterPack=*/false), + Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); assert(TST->isDependentType()); @@ -4467,9 +4665,11 @@ class InjectedClassNameType : public Type { public: QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } + TemplateName getTemplateName() const { return getInjectedTST()->getTemplateName(); } @@ -4488,12 +4688,16 @@ public: enum TagTypeKind { /// \brief The "struct" keyword. TTK_Struct, + /// \brief The "__interface" keyword. TTK_Interface, + /// \brief The "union" keyword. TTK_Union, + /// \brief The "class" keyword. TTK_Class, + /// \brief The "enum" keyword. TTK_Enum }; @@ -4503,17 +4707,23 @@ enum TagTypeKind { enum ElaboratedTypeKeyword { /// \brief The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, + /// \brief The "__interface" keyword introduces the elaborated-type-specifier. ETK_Interface, + /// \brief The "union" keyword introduces the elaborated-type-specifier. ETK_Union, + /// \brief The "class" keyword introduces the elaborated-type-specifier. ETK_Class, + /// \brief The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, + /// \brief The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, + /// \brief No keyword precedes the qualified type name. ETK_None }; @@ -4528,8 +4738,8 @@ protected: QualType Canonical, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack) { + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + ContainsUnexpandedParameterPack) { TypeWithKeywordBits.Keyword = Keyword; } @@ -4574,6 +4784,7 @@ public: /// The type itself is always "sugar", used to express what was written /// in the source code but containing no additional semantic information. class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4594,8 +4805,6 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { "and name qualifier both null."); } - friend class ASTContext; // ASTContext creates these - public: ~ElaboratedType(); @@ -4640,6 +4849,7 @@ public: /// 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 /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4649,13 +4859,11 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name) {} - - friend class ASTContext; // ASTContext creates these + : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + NNS->containsUnexpandedParameterPack()), + NNS(NNS), Name(Name) {} public: /// Retrieve the qualification on this type. @@ -4695,6 +4903,7 @@ public: class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4706,20 +4915,19 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType /// specialization. unsigned NumArgs; - const TemplateArgument *getArgBuffer() const { - return reinterpret_cast<const TemplateArgument*>(this+1); - } - TemplateArgument *getArgBuffer() { - return reinterpret_cast<TemplateArgument*>(this+1); - } - DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args, QualType Canon); - friend class ASTContext; // ASTContext creates these + const TemplateArgument *getArgBuffer() const { + return reinterpret_cast<const TemplateArgument*>(this+1); + } + + TemplateArgument *getArgBuffer() { + return reinterpret_cast<TemplateArgument*>(this+1); + } public: NestedNameSpecifier *getQualifier() const { return NNS; } @@ -4739,7 +4947,8 @@ public: return {getArgs(), NumArgs}; } - typedef const TemplateArgument * iterator; + using iterator = const TemplateArgument *; + iterator begin() const { return getArgs(); } iterator end() const; // inline in TemplateBase.h @@ -4785,6 +4994,8 @@ public: /// Here, the pack expansion \c Types&... is represented via a /// PackExpansionType whose pattern is Types&. class PackExpansionType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + /// \brief The pattern of the pack expansion. QualType Pattern; @@ -4798,14 +5009,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { PackExpansionType(QualType Pattern, QualType Canon, Optional<unsigned> NumExpansions) - : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), - /*InstantiationDependent=*/true, - /*VariablyModified=*/Pattern->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Pattern(Pattern), - NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } - - friend class ASTContext; // ASTContext creates these + : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), + /*InstantiationDependent=*/true, + /*VariablyModified=*/Pattern->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + Pattern(Pattern), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {} public: /// \brief Retrieve the pattern of this pack expansion, which is the @@ -4847,7 +5056,8 @@ public: template <class T> class ObjCProtocolQualifiers { protected: - ObjCProtocolQualifiers() {} + ObjCProtocolQualifiers() = default; + ObjCProtocolDecl * const *getProtocolStorage() const { return const_cast<ObjCProtocolQualifiers*>(this)->getProtocolStorage(); } @@ -4855,9 +5065,11 @@ protected: 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() && @@ -4868,8 +5080,8 @@ protected: } public: - typedef ObjCProtocolDecl * const *qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; + 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(); } @@ -4907,21 +5119,26 @@ class ObjCTypeParamType : public 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(); } @@ -4969,6 +5186,7 @@ public: 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 @@ -5004,15 +5222,16 @@ class ObjCObjectType : public Type, } protected: + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf); - enum Nonce_ObjCInterface { Nonce_ObjCInterface }; ObjCObjectType(enum Nonce_ObjCInterface) : Type(ObjCInterface, QualType(), false, false, false, false), - BaseType(QualType(this_(), 0)) { + BaseType(QualType(this_(), 0)) { ObjCObjectTypeBits.NumProtocols = 0; ObjCObjectTypeBits.NumTypeArgs = 0; ObjCObjectTypeBits.IsKindOf = 0; @@ -5032,9 +5251,11 @@ public: 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 { @@ -5125,7 +5346,7 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) - : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {} + : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {} public: void Profile(llvm::FoldingSetNodeID &ID); @@ -5163,14 +5384,15 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { /// - It is its own base type. That is, if T is an ObjCInterfaceType*, /// T->getBaseType() == QualType(T, 0). class ObjCInterfaceType : public ObjCObjectType { + friend class ASTContext; // ASTContext creates these. + friend class ASTReader; + friend class ObjCInterfaceDecl; + mutable ObjCInterfaceDecl *Decl; ObjCInterfaceType(const ObjCInterfaceDecl *D) - : ObjCObjectType(Nonce_ObjCInterface), - Decl(const_cast<ObjCInterfaceDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; - friend class ObjCInterfaceDecl; + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast<ObjCInterfaceDecl*>(D)) {} public: /// Get the declaration of this interface. @@ -5218,16 +5440,17 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { /// 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 { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, - Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) {} - friend class ASTContext; // ASTContext creates these. + : Type(ObjCObjectPointer, Canonical, + Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} public: /// Gets the type pointed to by this ObjC pointer. @@ -5336,16 +5559,19 @@ public: /// An iterator over the qualifiers on the object type. Provided /// for convenience. This will always iterate over the full set of /// protocols on a type, not just those provided directly. - typedef ObjCObjectType::qual_iterator qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; + using qual_iterator = ObjCObjectType::qual_iterator; + 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 getObjectType()->qual_begin(); } + qual_iterator qual_end() const { return getObjectType()->qual_end(); } + bool qual_empty() const { return getObjectType()->qual_empty(); } /// Return the number of qualifying protocols on the object type. @@ -5377,26 +5603,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { ID.AddPointer(T.getAsOpaquePtr()); } + static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } }; class AtomicType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType ValueType; AtomicType(QualType ValTy, QualType Canonical) - : Type(Atomic, Canonical, ValTy->isDependentType(), - ValTy->isInstantiationDependentType(), - ValTy->isVariablyModifiedType(), - ValTy->containsUnexpandedParameterPack()), - ValueType(ValTy) {} - friend class ASTContext; // ASTContext creates these. + : Type(Atomic, Canonical, ValTy->isDependentType(), + ValTy->isInstantiationDependentType(), + ValTy->isVariablyModifiedType(), + ValTy->containsUnexpandedParameterPack()), + ValueType(ValTy) {} - public: +public: /// Gets the type contained by this atomic type, i.e. /// the type returned by performing an atomic load of this atomic type. QualType getValueType() const { return ValueType; } @@ -5407,9 +5636,11 @@ class AtomicType : public Type, public llvm::FoldingSetNode { void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getValueType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { ID.AddPointer(T.getAsOpaquePtr()); } + static bool classof(const Type *T) { return T->getTypeClass() == Atomic; } @@ -5417,16 +5648,17 @@ class AtomicType : public Type, public llvm::FoldingSetNode { /// PipeType - OpenCL20. class PipeType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType ElementType; bool isRead; - PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) : - Type(Pipe, CanonicalPtr, elemType->isDependentType(), - elemType->isInstantiationDependentType(), - elemType->isVariablyModifiedType(), - elemType->containsUnexpandedParameterPack()), - ElementType(elemType), isRead(isRead) {} - friend class ASTContext; // ASTContext creates these. + PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) + : Type(Pipe, CanonicalPtr, elemType->isDependentType(), + elemType->isInstantiationDependentType(), + elemType->isVariablyModifiedType(), + elemType->containsUnexpandedParameterPack()), + ElementType(elemType), isRead(isRead) {} public: QualType getElementType() const { return ElementType; } @@ -5476,7 +5708,6 @@ public: QualType apply(const ASTContext &Context, const Type* T) const; }; - // Inline function definitions. inline SplitQualType SplitQualType::getSingleStepDesugaredType() const { @@ -5602,7 +5833,7 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { } /// Return the address space of this type. -inline unsigned QualType::getAddressSpace() const { +inline LangAS QualType::getAddressSpace() const { return getQualifiers().getAddressSpace(); } @@ -5709,88 +5940,117 @@ inline bool Type::isCompoundType() const { inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } + inline bool Type::isPointerType() const { return isa<PointerType>(CanonicalType); } + inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } + inline bool Type::isBlockPointerType() const { return isa<BlockPointerType>(CanonicalType); } + inline bool Type::isReferenceType() const { return isa<ReferenceType>(CanonicalType); } + inline bool Type::isLValueReferenceType() const { return isa<LValueReferenceType>(CanonicalType); } + inline bool Type::isRValueReferenceType() const { return isa<RValueReferenceType>(CanonicalType); } + inline bool Type::isFunctionPointerType() const { if (const PointerType *T = getAs<PointerType>()) return T->getPointeeType()->isFunctionType(); else return false; } + inline bool Type::isMemberPointerType() const { return isa<MemberPointerType>(CanonicalType); } + inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) return T->isMemberFunctionPointer(); else return false; } + inline bool Type::isMemberDataPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) return T->isMemberDataPointer(); else return false; } + inline bool Type::isArrayType() const { return isa<ArrayType>(CanonicalType); } + inline bool Type::isConstantArrayType() const { return isa<ConstantArrayType>(CanonicalType); } + inline bool Type::isIncompleteArrayType() const { return isa<IncompleteArrayType>(CanonicalType); } + inline bool Type::isVariableArrayType() const { return isa<VariableArrayType>(CanonicalType); } + inline bool Type::isDependentSizedArrayType() const { return isa<DependentSizedArrayType>(CanonicalType); } + inline bool Type::isBuiltinType() const { return isa<BuiltinType>(CanonicalType); } + inline bool Type::isRecordType() const { return isa<RecordType>(CanonicalType); } + inline bool Type::isEnumeralType() const { return isa<EnumType>(CanonicalType); } + inline bool Type::isAnyComplexType() const { return isa<ComplexType>(CanonicalType); } + inline bool Type::isVectorType() const { return isa<VectorType>(CanonicalType); } + inline bool Type::isExtVectorType() const { return isa<ExtVectorType>(CanonicalType); } + +inline bool Type::isDependentAddressSpaceType() const { + return isa<DependentAddressSpaceType>(CanonicalType); +} + inline bool Type::isObjCObjectPointerType() const { return isa<ObjCObjectPointerType>(CanonicalType); } + inline bool Type::isObjCObjectType() const { return isa<ObjCObjectType>(CanonicalType); } + inline bool Type::isObjCObjectOrInterfaceType() const { return isa<ObjCInterfaceType>(CanonicalType) || isa<ObjCObjectType>(CanonicalType); } + inline bool Type::isAtomicType() const { return isa<AtomicType>(CanonicalType); } @@ -5800,26 +6060,31 @@ inline bool Type::isObjCQualifiedIdType() const { return OPT->isObjCQualifiedIdType(); return false; } + inline bool Type::isObjCQualifiedClassType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedClassType(); return false; } + inline bool Type::isObjCIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCIdType(); return false; } + inline bool Type::isObjCClassType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCClassType(); return false; } + inline bool Type::isObjCSelType() const { if (const PointerType *OPT = getAs<PointerType>()) return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); return false; } + inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType() || isObjCSelType(); } @@ -5854,7 +6119,7 @@ inline bool Type::isImageType() const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) is##Id##Type() || return #include "clang/Basic/OpenCLImageTypes.def" - 0; // end boolean or operation + false; // end boolean or operation } inline bool Type::isPipeType() const { @@ -6133,7 +6398,6 @@ QualType DecayedType::getPointeeType() const { return cast<PointerType>(Decayed)->getPointeeType(); } +} // namespace clang -} // end namespace clang - -#endif +#endif // LLVM_CLANG_AST_TYPE_H |
