diff options
Diffstat (limited to 'include/clang/AST/Type.h')
-rw-r--r-- | include/clang/AST/Type.h | 639 |
1 files changed, 431 insertions, 208 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 882878bb7e1e..c692707847a6 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief C Language Family Type Representation +/// C Language Family Type Representation /// /// This file defines the clang::Type interface and subclasses, used to /// represent types for languages in the C family. @@ -30,6 +30,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" @@ -56,6 +57,7 @@ namespace clang { class ExtQuals; class QualType; +class TagDecl; class Type; enum { @@ -445,7 +447,7 @@ public: } } - /// \brief Remove the qualifiers from the given set from this set. + /// Remove the qualifiers from the given set from this set. void removeQualifiers(Qualifiers Q) { // If the other set doesn't have any non-boolean qualifiers, just // bit-and the inverse in. @@ -508,7 +510,7 @@ public: (!other.hasUnaligned() || hasUnaligned()); } - /// \brief Determines if these qualifiers compatibly include another set of + /// Determines if these qualifiers compatibly include another set of /// qualifiers from the narrow perspective of Objective-C ARC lifetime. /// /// One set of Objective-C lifetime qualifiers compatibly includes the other @@ -528,7 +530,7 @@ public: return hasConst(); } - /// \brief Determine whether this set of qualifiers is a strict superset of + /// Determine whether this set of qualifiers is a strict superset of /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; @@ -554,7 +556,7 @@ public: return *this; } - /// \brief Compute the difference between two qualifier sets. + /// Compute the difference between two qualifier sets. friend Qualifiers operator-(Qualifiers L, Qualifiers R) { L -= R; return L; @@ -667,8 +669,7 @@ class QualType { const ExtQualsTypeCommonBase *getCommonPtr() const { assert(!isNull() && "Cannot retrieve a NULL type pointer"); - uintptr_t CommonPtrVal - = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); + auto CommonPtrVal = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1); return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); } @@ -720,69 +721,69 @@ public: return Value.getPointer().isNull(); } - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "const" qualifier set, without looking through typedefs that may have /// added "const" at a different level. bool isLocalConstQualified() const { return (getLocalFastQualifiers() & Qualifiers::Const); } - /// \brief Determine whether this type is const-qualified. + /// Determine whether this type is const-qualified. bool isConstQualified() const; - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "restrict" qualifier set, without looking through typedefs that may have /// added "restrict" at a different level. bool isLocalRestrictQualified() const { return (getLocalFastQualifiers() & Qualifiers::Restrict); } - /// \brief Determine whether this type is restrict-qualified. + /// Determine whether this type is restrict-qualified. bool isRestrictQualified() const; - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "volatile" qualifier set, without looking through typedefs that may have /// added "volatile" at a different level. bool isLocalVolatileQualified() const { return (getLocalFastQualifiers() & Qualifiers::Volatile); } - /// \brief Determine whether this type is volatile-qualified. + /// Determine whether this type is volatile-qualified. bool isVolatileQualified() const; - /// \brief Determine whether this particular QualType instance has any + /// Determine whether this particular QualType instance has any /// qualifiers, without looking through any typedefs that might add /// qualifiers at a different level. bool hasLocalQualifiers() const { return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); } - /// \brief Determine whether this type has any qualifiers. + /// Determine whether this type has any qualifiers. bool hasQualifiers() const; - /// \brief Determine whether this particular QualType instance has any + /// Determine whether this particular QualType instance has any /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType /// instance. bool hasLocalNonFastQualifiers() const { return Value.getPointer().is<const ExtQuals*>(); } - /// \brief Retrieve the set of qualifiers local to this particular QualType + /// Retrieve the set of qualifiers local to this particular QualType /// instance, not including any qualifiers acquired through typedefs or /// other sugar. Qualifiers getLocalQualifiers() const; - /// \brief Retrieve the set of qualifiers applied to this type. + /// Retrieve the set of qualifiers applied to this type. Qualifiers getQualifiers() const; - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// local to this particular QualType instance, not including any qualifiers /// acquired through typedefs or other sugar. unsigned getLocalCVRQualifiers() const { return getLocalFastQualifiers(); } - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; @@ -790,7 +791,7 @@ public: return QualType::isConstant(*this, Ctx); } - /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). + /// Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). bool isPODType(const ASTContext &Context) const; /// Return true if this is a POD type according to the rules of the C++98 @@ -799,7 +800,8 @@ public: /// Return true if this is a POD type according to the more relaxed rules /// of the C++11 standard, regardless of the current compilation's language. - /// (C++0x [basic.types]p9) + /// (C++0x [basic.types]p9). Note that, unlike + /// CXXRecordDecl::isCXX11StandardLayout, this takes DRs into account. bool isCXX11PODType(const ASTContext &Context) const; /// Return true if this is a trivial type per (C++0x [basic.types]p9) @@ -808,6 +810,13 @@ public: /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + + /// Returns true if it is a class and it might be dynamic. + bool mayBeDynamicClass() const; + + /// Returns true if it is not a class or if the class might not be dynamic. + bool mayBeNotDynamicClass() const; + // Don't promise in the API that anything besides 'const' can be // easily added. @@ -879,12 +888,12 @@ public: QualType getCanonicalType() const; - /// \brief Return this type with all of the instance-specific qualifiers + /// Return this type with all of the instance-specific qualifiers /// removed, but without removing any qualifiers that may have been applied /// through typedefs. QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } - /// \brief Retrieve the unqualified variant of the given type, + /// Retrieve the unqualified variant of the given type, /// removing as little sugar as possible. /// /// This routine looks through various kinds of sugar to find the @@ -915,17 +924,17 @@ public: /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; - /// \brief Determine whether this type is more qualified than the other + /// Determine whether this type is more qualified than the other /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; - /// \brief Determine whether this type is at least as qualified as the other + /// Determine whether this type is at least as qualified as the other /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; - /// \brief Determine the type of a (typically non-lvalue) expression with the + /// Determine the type of a (typically non-lvalue) expression with the /// specified result type. /// /// This routine should be used for expressions for which the return type is @@ -951,7 +960,7 @@ public: return getSplitDesugaredType(*this); } - /// \brief Return the specified type with one level of "sugar" removed from + /// Return the specified type with one level of "sugar" removed from /// the type. /// /// This routine takes off the first typedef, typeof, etc. If the outer level @@ -1082,11 +1091,79 @@ public: // true when Type is objc's weak and weak is enabled but ARC isn't. bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; + enum PrimitiveDefaultInitializeKind { + /// The type does not fall into any of the following categories. Note that + /// this case is zero-valued so that values of this enum can be used as a + /// boolean condition for non-triviality. + PDIK_Trivial, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __strong qualifier. + PDIK_ARCStrong, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __weak qualifier. + PDIK_ARCWeak, + + /// The type is a struct containing a field whose type is not PCK_Trivial. + PDIK_Struct + }; + + /// Functions to query basic properties of non-trivial C struct types. + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to default initialize + /// and return the kind. + PrimitiveDefaultInitializeKind + isNonTrivialToPrimitiveDefaultInitialize() const; + + enum PrimitiveCopyKind { + /// The type does not fall into any of the following categories. Note that + /// this case is zero-valued so that values of this enum can be used as a + /// boolean condition for non-triviality. + PCK_Trivial, + + /// The type would be trivial except that it is volatile-qualified. Types + /// that fall into one of the other non-trivial cases may additionally be + /// volatile-qualified. + PCK_VolatileTrivial, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __strong qualifier. + PCK_ARCStrong, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __weak qualifier. + PCK_ARCWeak, + + /// The type is a struct containing a field whose type is neither + /// PCK_Trivial nor PCK_VolatileTrivial. + /// Note that a C++ struct type does not necessarily match this; C++ copying + /// semantics are too complex to express here, in part because they depend + /// on the exact constructor or assignment operator that is chosen by + /// overload resolution to do the copy. + PCK_Struct + }; + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to copy and return the + /// kind. + PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const; + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to destructively + /// move and return the kind. Destructive move in this context is a C++-style + /// move in which the source object is placed in a valid but unspecified state + /// after it is moved, as opposed to a truly destructive move in which the + /// source object is placed in an uninitialized state. + PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const; + enum DestructionKind { DK_none, DK_cxx_destructor, DK_objc_strong_lifetime, - DK_objc_weak_lifetime + DK_objc_weak_lifetime, + DK_nontrivial_c_struct }; /// Returns a nonzero value if objects of this type require @@ -1204,7 +1281,7 @@ struct PointerLikeTypeTraits<clang::QualType> { namespace clang { -/// \brief Base class that is common to both the \c ExtQuals and \c Type +/// 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 { @@ -1212,14 +1289,14 @@ class ExtQualsTypeCommonBase { friend class QualType; friend class Type; - /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or + /// The "base" type of an extended qualifiers type (\c ExtQuals) or /// a self-referential pointer (for \c Type). /// /// This pointer allows an efficient mapping from a QualType to its /// underlying type pointer. const Type *const BaseType; - /// \brief The canonical type of this type. A QualType. + /// The canonical type of this type. A QualType. QualType CanonicalType; ExtQualsTypeCommonBase(const Type *baseType, QualType canon) @@ -1300,25 +1377,25 @@ public: /// This determines whether a member function's "this" object can be an /// lvalue, rvalue, or neither. enum RefQualifierKind { - /// \brief No ref-qualifier was provided. + /// No ref-qualifier was provided. RQ_None = 0, - /// \brief An lvalue ref-qualifier was provided (\c &). + /// An lvalue ref-qualifier was provided (\c &). RQ_LValue, - /// \brief An rvalue ref-qualifier was provided (\c &&). + /// An rvalue ref-qualifier was provided (\c &&). RQ_RValue }; /// Which keyword(s) were used to create an AutoType. enum class AutoTypeKeyword { - /// \brief auto + /// auto Auto, - /// \brief decltype(auto) + /// decltype(auto) DecltypeAuto, - /// \brief __auto_type (GNU extension) + /// __auto_type (GNU extension) GNUAutoType }; @@ -1377,21 +1454,21 @@ private: /// Whether this type is a variably-modified type (C99 6.7.5). unsigned VariablyModified : 1; - /// \brief Whether this type contains an unexpanded parameter pack + /// Whether this type contains an unexpanded parameter pack /// (for C++11 variadic templates). unsigned ContainsUnexpandedParameterPack : 1; - /// \brief True if the cache (i.e. the bitfields here starting with + /// True if the cache (i.e. the bitfields here starting with /// 'Cache') is valid. mutable unsigned CacheValid : 1; - /// \brief Linkage of this type. + /// Linkage of this type. mutable unsigned CachedLinkage : 3; - /// \brief Whether this type involves and local or unnamed types. + /// Whether this type involves and local or unnamed types. mutable unsigned CachedLocalOrUnnamed : 1; - /// \brief Whether this type comes from an AST file. + /// Whether this type comes from an AST file. mutable unsigned FromAST : 1; bool isCacheValid() const { @@ -1446,7 +1523,7 @@ protected: /// Extra information which affects how the function is called, like /// regparm and the calling convention. - unsigned ExtInfo : 11; + unsigned ExtInfo : 12; /// Used only by FunctionProtoType, put here to pack with the /// other bitfields. @@ -1456,7 +1533,7 @@ protected: /// cv-qualifier-seq, [...], are part of the function type. unsigned TypeQuals : 4; - /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// The ref-qualifier associated with a \c FunctionProtoType. /// /// This is a value of type \c RefQualifierKind. unsigned RefQualifier : 2; @@ -1513,6 +1590,7 @@ protected: class VectorTypeBitfields { friend class VectorType; + friend class DependentVectorType; unsigned : NumTypeBits; @@ -1561,7 +1639,7 @@ protected: private: template <class T> friend class TypePropertyCache; - /// \brief Set whether this type comes from an AST file. + /// Set whether this type comes from an AST file. void setFromAST(bool V = true) const { TypeBits.FromAST = V; } @@ -1612,10 +1690,10 @@ public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); } - /// \brief Whether this type comes from an AST file. + /// Whether this type comes from an AST file. bool isFromAST() const { return TypeBits.FromAST; } - /// \brief Whether this type is or contains an unexpanded parameter + /// Whether this type is or contains an unexpanded parameter /// pack, used to support C++0x variadic templates. /// /// A type that contains a parameter pack shall be expanded by the @@ -1653,7 +1731,7 @@ public: /// determine its size (e.g. void, or a fwd declared struct). Clients of this /// routine will need to determine if the size is actually required. /// - /// \brief Def If non-null, and the type refers to some kind of declaration + /// Def If non-null, and the type refers to some kind of declaration /// that can be completed (such as a C struct, C++ class, or Objective-C /// class), will be set to the declaration. bool isIncompleteType(NamedDecl **Def = nullptr) const; @@ -1664,7 +1742,7 @@ public: return !isFunctionType(); } - /// \brief Determine whether this type is an object type. + /// Determine whether this type is an object type. bool isObjectType() const { // C++ [basic.types]p8: // An object type is a (possibly cv-qualified) type that is not a @@ -1706,9 +1784,13 @@ public: /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) bool isEnumeralType() const; + + /// Determine whether this type is a scoped enumeration type. + bool isScopedEnumeralType() const; bool isBooleanType() const; bool isCharType() const; bool isWideCharType() const; + bool isChar8Type() const; bool isChar16Type() const; bool isChar32Type() const; bool isAnyCharacterType() const; @@ -1728,6 +1810,8 @@ public: bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) + bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isFloat128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) bool isVoidType() const; // C99 6.2.5p19 @@ -1857,7 +1941,7 @@ public: /// somehow depends on a template parameter (C++ [temp.dep.type]). bool isDependentType() const { return TypeBits.Dependent; } - /// \brief Determine whether this type is an instantiation-dependent type, + /// Determine whether this type is an instantiation-dependent type, /// meaning that the type involves a template parameter (even if the /// definition does not actually depend on the type substituted for that /// template parameter). @@ -1865,24 +1949,24 @@ public: return TypeBits.InstantiationDependent; } - /// \brief Determine whether this type is an undeduced type, meaning that + /// Determine whether this type is an undeduced type, meaning that /// it somehow involves a C++11 'auto' type or similar which has not yet been /// deduced. bool isUndeducedType() const; - /// \brief Whether this type is a variably-modified type (C99 6.7.5). + /// Whether this type is a variably-modified type (C99 6.7.5). bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } - /// \brief Whether this type involves a variable-length array type + /// Whether this type involves a variable-length array type /// with a definite size. bool hasSizedVLAType() const; - /// \brief Whether this type is or contains a local or unnamed type. + /// Whether this type is or contains a local or unnamed type. bool hasUnnamedOrLocalType() const; bool isOverloadableType() const; - /// \brief Determine wither this type is a C++ elaborated-type-specifier. + /// Determine wither this type is a C++ elaborated-type-specifier. bool isElaboratedTypeSpecifier() const; bool canDecayToPointerType() const; @@ -1896,19 +1980,19 @@ public: /// purpose of GC'ability bool hasObjCPointerRepresentation() const; - /// \brief Determine whether this type has an integer representation + /// Determine whether this type has an integer representation /// of some sort, e.g., it is an integer type or a vector. bool hasIntegerRepresentation() const; - /// \brief Determine whether this type has an signed integer representation + /// Determine whether this type has an signed integer representation /// of some sort, e.g., it is an signed integer type or a vector. bool hasSignedIntegerRepresentation() const; - /// \brief Determine whether this type has an unsigned integer representation + /// Determine whether this type has an unsigned integer representation /// of some sort, e.g., it is an unsigned integer type or a vector. bool hasUnsignedIntegerRepresentation() const; - /// \brief Determine whether this type has a floating-point representation + /// Determine whether this type has a floating-point representation /// of some sort, e.g., it is a floating-point type or a vector thereof. bool hasFloatingRepresentation() const; @@ -1928,18 +2012,18 @@ public: const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; - /// \brief Retrieves the CXXRecordDecl that this type refers to, either + /// Retrieves the CXXRecordDecl that this type refers to, either /// because the type is a RecordType or because it is the injected-class-name /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; - /// \brief Retrieves the TagDecl that this type refers to, either + /// Retrieves the TagDecl that this type refers to, either /// because the type is a TagType or because it is the injected-class-name /// type of a class template or class template partial specialization. TagDecl *getAsTagDecl() const; /// If this is a pointer or reference to a RecordType, return the - /// CXXRecordDecl that that type refers to. + /// CXXRecordDecl that the type refers to. /// /// If this is not a pointer or reference, or the type being pointed to does /// not refer to a CXXRecordDecl, returns NULL. @@ -2037,6 +2121,26 @@ public: /// enumeration types whose underlying type is a unsigned integer type. bool isUnsignedIntegerOrEnumerationType() const; + /// Return true if this is a fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. + bool isFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isSaturatedFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isUnsaturatedFixedPointType() const; + + /// Return true if this is a fixed point type that is signed according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isSignedFixedPointType() const; + + /// Return true if this is a fixed point type that is unsigned according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isUnsignedFixedPointType() const; + /// Return true if this is not a variable sized type, /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types. @@ -2113,16 +2217,16 @@ public: void dump(llvm::raw_ostream &OS) const; }; -/// \brief This will check for a TypedefType by removing any existing sugar +/// This will check for a TypedefType by removing any existing sugar /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; -/// \brief This will check for a TemplateSpecializationType by removing any +/// This will check for a TemplateSpecializationType by removing any /// existing sugar until it reaches a TemplateSpecializationType or a /// non-sugared type. template <> const TemplateSpecializationType *Type::getAs() const; -/// \brief This will check for an AttributedType by removing any existing sugar +/// This will check for an AttributedType by removing any existing sugar /// until it reaches an AttributedType or a non-sugared type. template <> const AttributedType *Type::getAs() const; @@ -2152,7 +2256,9 @@ public: #include "clang/AST/BuiltinTypes.def" }; -public: +private: + friend class ASTContext; // ASTContext creates these. + BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), /*InstantiationDependent=*/(K == Dependent), @@ -2161,6 +2267,7 @@ public: BuiltinTypeBits.Kind = K; } +public: Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } StringRef getName(const PrintingPolicy &Policy) const; @@ -2637,13 +2744,13 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - /// \brief Determine the number of bits required to address a member of + /// 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, QualType ElementType, const llvm::APInt &NumElements); - /// \brief Determine the maximum number of active bits that an array's size + /// Determine the maximum number of active bits that an array's size /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(const ASTContext &Context); @@ -2774,7 +2881,7 @@ class DependentSizedArrayType : public ArrayType { const ASTContext &Context; - /// \brief An assignment expression that will instantiate to the + /// An assignment expression that will instantiate to the /// size of the array. /// /// The expression itself might be null, in which case the array @@ -2979,6 +3086,51 @@ public: } }; +/// Represents a vector type where either the type or size is dependent. +//// +/// For example: +/// \code +/// template<typename T, int Size> +/// class vector { +/// typedef T __attribute__((vector_size(Size))) type; +/// } +/// \endcode +class DependentVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + QualType ElementType; + Expr *SizeExpr; + SourceLocation Loc; + + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, VectorType::VectorKind vecKind); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return Loc; } + VectorType::VectorKind getVectorKind() const { + return VectorType::VectorKind(VectorTypeBits.VecKind); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentVector; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, const Expr *SizeExpr, + VectorType::VectorKind VecKind); +}; + /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This @@ -3081,24 +3233,24 @@ public: class ExtInfo { friend class FunctionType; - // Feel free to rearrange or add bits, but if you go over 11, + // Feel free to rearrange or add bits, but if you go over 12, // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|produces|nocallersavedregs|regparm| - // |0 .. 4| 5 | 6 | 7 |8 .. 10| + // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck| + // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | // // regparm is either 0 (no regparm attribute) or the regparm value+1. enum { CallConvMask = 0x1F }; enum { NoReturnMask = 0x20 }; enum { ProducesResultMask = 0x40 }; enum { NoCallerSavedRegsMask = 0x80 }; + enum { NoCfCheckMask = 0x800 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask | - NoCallerSavedRegsMask), + NoCallerSavedRegsMask | NoCfCheckMask), RegParmOffset = 8 }; // Assumed to be the last field - uint16_t Bits = CC_C; ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} @@ -3107,12 +3259,13 @@ public: // 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) { + bool producesResult, bool noCallerSavedRegs, bool NoCfCheck) { assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) | (producesResult ? ProducesResultMask : 0) | (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) | - (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0); + (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) | + (NoCfCheck ? NoCfCheckMask : 0); } // Constructor with all defaults. Use when for example creating a @@ -3126,10 +3279,11 @@ public: bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; } + bool getNoCfCheck() const { return Bits & NoCfCheckMask; } bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } unsigned getRegParm() const { - unsigned RegParm = Bits >> RegParmOffset; + unsigned RegParm = (Bits & RegParmMask) >> RegParmOffset; if (RegParm > 0) --RegParm; return RegParm; @@ -3168,6 +3322,13 @@ public: return ExtInfo(Bits & ~NoCallerSavedRegsMask); } + ExtInfo withNoCfCheck(bool noCfCheck) const { + if (noCfCheck) + return ExtInfo(Bits | NoCfCheckMask); + else + return ExtInfo(Bits & ~NoCfCheckMask); + } + ExtInfo withRegParm(unsigned RegParm) const { assert(RegParm < 7 && "Invalid regparm value"); return ExtInfo((Bits & ~RegParmMask) | @@ -3214,7 +3375,7 @@ public: bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; } bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; } - /// \brief Determine the type of an expression that calls a function of + /// Determine the type of an expression that calls a function of /// this type. QualType getCallResultType(const ASTContext &Context) const { return getReturnType().getNonLValueExprType(Context); @@ -3367,7 +3528,7 @@ public: /// Explicitly-specified list of exception types. ArrayRef<QualType> Exceptions; - /// Noexcept expression, if this is EST_ComputedNoexcept. + /// Noexcept expression, if this is a computed noexcept specification. Expr *NoexceptExpr = nullptr; /// The function whose exception specification this is, for @@ -3409,7 +3570,7 @@ public: private: friend class ASTContext; // ASTContext creates these. - /// \brief Determine whether there are any argument types that + /// Determine whether there are any argument types that /// contain an unexpanded parameter pack. static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, unsigned numArgs) { @@ -3464,26 +3625,41 @@ private: assert(hasExtParameterInfos()); // Find the end of the exception specification. - const char *ptr = reinterpret_cast<const char *>(exception_begin()); + const auto *ptr = reinterpret_cast<const char *>(exception_begin()); ptr += getExceptionSpecSize(); return reinterpret_cast<const ExtParameterInfo *>(ptr); } - size_t getExceptionSpecSize() const { - switch (getExceptionSpecType()) { - case EST_None: return 0; - case EST_DynamicNone: return 0; - case EST_MSAny: return 0; - case EST_BasicNoexcept: return 0; - case EST_Unparsed: return 0; - case EST_Dynamic: return getNumExceptions() * sizeof(QualType); - case EST_ComputedNoexcept: return sizeof(Expr*); - case EST_Uninstantiated: return 2 * sizeof(FunctionDecl*); - case EST_Unevaluated: return sizeof(FunctionDecl*); + static size_t getExceptionSpecSize(ExceptionSpecificationType EST, + unsigned NumExceptions) { + switch (EST) { + case EST_None: + case EST_DynamicNone: + case EST_MSAny: + case EST_BasicNoexcept: + case EST_Unparsed: + return 0; + + case EST_Dynamic: + return NumExceptions * sizeof(QualType); + + case EST_DependentNoexcept: + case EST_NoexceptFalse: + case EST_NoexceptTrue: + return sizeof(Expr *); + + case EST_Uninstantiated: + return 2 * sizeof(FunctionDecl *); + + case EST_Unevaluated: + return sizeof(FunctionDecl *); } llvm_unreachable("bad exception specification kind"); } + size_t getExceptionSpecSize() const { + return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions()); + } public: unsigned getNumParams() const { return NumParams; } @@ -3507,7 +3683,7 @@ public: EPI.RefQualifier = getRefQualifier(); if (EPI.ExceptionSpec.Type == EST_Dynamic) { EPI.ExceptionSpec.Exceptions = exceptions(); - } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { + } else if (isComputedNoexcept(EPI.ExceptionSpec.Type)) { EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); @@ -3547,39 +3723,19 @@ public: /// spec. bool hasInstantiationDependentExceptionSpec() const; - /// Result type of getNoexceptSpec(). - enum NoexceptResult { - /// 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; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); return exception_begin()[i]; } Expr *getNoexceptExpr() const { - if (getExceptionSpecType() != EST_ComputedNoexcept) + if (!isComputedNoexcept(getExceptionSpecType())) return nullptr; // 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 + /// 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 /// specification is represented by this type. @@ -3590,7 +3746,7 @@ public: return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; } - /// \brief If this function type has an uninstantiated exception + /// 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 /// this type. @@ -3602,14 +3758,14 @@ public: /// Determine whether this function type has a non-throwing exception /// specification. - CanThrowResult canThrow(const ASTContext &Ctx) const; + CanThrowResult canThrow() const; /// Determine whether this function type has a non-throwing exception /// specification. If this depends on template arguments, returns /// \c ResultIfDependent. - bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const { - return ResultIfDependent ? canThrow(Ctx) != CT_Can - : canThrow(Ctx) == CT_Cannot; + bool isNothrow(bool ResultIfDependent = false) const { + return ResultIfDependent ? canThrow() != CT_Can + : canThrow() == CT_Cannot; } bool isVariadic() const { return Variadic; } @@ -3719,7 +3875,7 @@ public: bool Canonical); }; -/// \brief Represents the dependent type named by a dependently-scoped +/// Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. /// using typename Base<T>::foo; /// @@ -3790,16 +3946,16 @@ protected: public: Expr *getUnderlyingExpr() const { return TOExpr; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const; - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// `typeof(expr)` types. /// /// This class is used internally by the ASTContext to manage @@ -3839,10 +3995,10 @@ class TypeOfType : public Type { public: QualType getUnderlyingType() const { return TOType; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const { return getUnderlyingType(); } - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } @@ -3862,16 +4018,16 @@ public: Expr *getUnderlyingExpr() const { return E; } QualType getUnderlyingType() const { return UnderlyingType; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const; - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// decltype(expr) types. /// /// This class is used internally by the ASTContext to manage @@ -3927,7 +4083,7 @@ public: } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// __underlying_type(type) types. /// /// This class is used internally by the ASTContext to manage @@ -4054,6 +4210,7 @@ public: // No operand. attr_noreturn, + attr_nocf_check, attr_cdecl, attr_fastcall, attr_stdcall, @@ -4246,7 +4403,7 @@ public: } }; -/// \brief Represents the result of substituting a type for a template +/// Represents the result of substituting a type for a template /// type parameter. /// /// Within an instantiated template, all template type parameters have @@ -4297,7 +4454,7 @@ public: } }; -/// \brief Represents the result of substituting a set of types for a template +/// 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 @@ -4312,14 +4469,14 @@ public: class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - /// \brief The original type parameter. + /// The original type parameter. const TemplateTypeParmType *Replaced; - /// \brief A pointer to the set of template arguments that this + /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - /// \brief The number of template arguments in \c Arguments. + /// The number of template arguments in \c Arguments. unsigned NumArguments; SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, @@ -4349,7 +4506,7 @@ public: } }; -/// \brief Common base class for placeholders for types that get replaced by +/// 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 (eventually) constrained type names from the C++ /// Concepts TS. @@ -4382,7 +4539,7 @@ public: bool isSugared() const { return !isCanonicalUnqualified(); } QualType desugar() const { return getCanonicalTypeInternal(); } - /// \brief Get the type deduced for this placeholder type, or null if it's + /// Get the type deduced for this placeholder type, or null if it's /// either not been deduced or was deduced to a dependent type. QualType getDeducedType() const { return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); @@ -4397,7 +4554,7 @@ public: } }; -/// \brief Represents a C++11 auto or C++14 decltype(auto) type. +/// Represents a C++11 auto or C++14 decltype(auto) type. class AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4433,7 +4590,7 @@ public: } }; -/// \brief Represents a C++17 deduced template specialization type. +/// Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4470,7 +4627,7 @@ public: } }; -/// \brief Represents a type template specialization; the template +/// 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 @@ -4490,7 +4647,7 @@ public: /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType +class alignas(8) TemplateSpecializationType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4530,7 +4687,7 @@ public: return isa<InjectedClassNameType>(getCanonicalTypeInternal()); } - /// \brief Determine if this template specialization type is for a type alias + /// 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 @@ -4599,7 +4756,7 @@ public: } }; -/// \brief Print a template argument list, including the '<' and '>' +/// Print a template argument list, including the '<' and '>' /// enclosing the template arguments. void printTemplateArgumentList(raw_ostream &OS, ArrayRef<TemplateArgument> Args, @@ -4682,47 +4839,47 @@ public: } }; -/// \brief The kind of a tag type. +/// The kind of a tag type. enum TagTypeKind { - /// \brief The "struct" keyword. + /// The "struct" keyword. TTK_Struct, - /// \brief The "__interface" keyword. + /// The "__interface" keyword. TTK_Interface, - /// \brief The "union" keyword. + /// The "union" keyword. TTK_Union, - /// \brief The "class" keyword. + /// The "class" keyword. TTK_Class, - /// \brief The "enum" keyword. + /// The "enum" keyword. TTK_Enum }; -/// \brief The elaboration keyword that precedes a qualified type name or +/// The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. enum ElaboratedTypeKeyword { - /// \brief The "struct" keyword introduces the elaborated-type-specifier. + /// The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, - /// \brief The "__interface" keyword introduces the elaborated-type-specifier. + /// The "__interface" keyword introduces the elaborated-type-specifier. ETK_Interface, - /// \brief The "union" keyword introduces the elaborated-type-specifier. + /// The "union" keyword introduces the elaborated-type-specifier. ETK_Union, - /// \brief The "class" keyword introduces the elaborated-type-specifier. + /// The "class" keyword introduces the elaborated-type-specifier. ETK_Class, - /// \brief The "enum" keyword introduces the elaborated-type-specifier. + /// The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, - /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, - /// \brief No keyword precedes the qualified type name. + /// No keyword precedes the qualified type name. ETK_None }; @@ -4773,7 +4930,7 @@ public: static CannotCastToThisType classof(const Type *); }; -/// \brief Represents a type that was referred to using an elaborated type +/// Represents a type that was referred to using an elaborated type /// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, /// or both. /// @@ -4790,14 +4947,18 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { /// The type that this qualified name refers to. QualType NamedType; + /// The (re)declaration of this tag type owned by this occurrence, or nullptr + /// if none. + TagDecl *OwnedTagDecl; + ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - QualType NamedType, QualType CanonType) + QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl) : TypeWithKeyword(Keyword, Elaborated, CanonType, NamedType->isDependentType(), NamedType->isInstantiationDependentType(), NamedType->isVariablyModifiedType(), NamedType->containsUnexpandedParameterPack()), - NNS(NNS), NamedType(NamedType) { + NNS(NNS), NamedType(NamedType), OwnedTagDecl(OwnedTagDecl) { assert(!(Keyword == ETK_None && NNS == nullptr) && "ElaboratedType cannot have elaborated type keyword " "and name qualifier both null."); @@ -4818,15 +4979,21 @@ public: /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } + /// Return the (re)declaration of this type owned by this occurrence of this + /// type, or nullptr if none. + TagDecl *getOwnedTagDecl() const { return OwnedTagDecl; } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getKeyword(), NNS, NamedType); + Profile(ID, getKeyword(), NNS, NamedType, OwnedTagDecl); } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType NamedType) { + NestedNameSpecifier *NNS, QualType NamedType, + TagDecl *OwnedTagDecl) { ID.AddInteger(Keyword); ID.AddPointer(NNS); NamedType.Profile(ID); + ID.AddPointer(OwnedTagDecl); } static bool classof(const Type *T) { @@ -4834,7 +5001,7 @@ public: } }; -/// \brief Represents a qualified type name for which the type name is +/// Represents a qualified type name for which the type name is /// dependent. /// /// DependentNameType represents a class of dependent types that involve a @@ -4849,10 +5016,10 @@ public: class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - /// \brief The nested name specifier containing the qualifier. + /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - /// \brief The type that this typename specifier refers to. + /// The type that this typename specifier refers to. const IdentifierInfo *Name; DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, @@ -4898,7 +5065,7 @@ public: /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A<T>::template B<T> -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType +class alignas(8) DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4909,7 +5076,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType /// The identifier of the template. const IdentifierInfo *Name; - /// \brief The number of template arguments named in this class template + /// The number of template arguments named in this class template /// specialization. unsigned NumArgs; @@ -4931,12 +5098,12 @@ public: NestedNameSpecifier *getQualifier() const { return NNS; } const IdentifierInfo *getIdentifier() const { return Name; } - /// \brief Retrieve the template arguments. + /// Retrieve the template arguments. const TemplateArgument *getArgs() const { return getArgBuffer(); } - /// \brief Retrieve the number of template arguments. + /// Retrieve the number of template arguments. unsigned getNumArgs() const { return NumArgs; } const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h @@ -4969,7 +5136,7 @@ public: } }; -/// \brief Represents a pack expansion of types. +/// 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 @@ -4994,10 +5161,10 @@ public: class PackExpansionType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - /// \brief The pattern of the pack expansion. + /// The pattern of the pack expansion. QualType Pattern; - /// \brief The number of expansions that this pack expansion will + /// The number of expansions that this pack expansion will /// generate when substituted (+1), or indicates that /// /// This field will only have a non-zero value when some of the parameter @@ -5015,12 +5182,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {} public: - /// \brief Retrieve the pattern of this pack expansion, which is the + /// 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; } - /// \brief Retrieve the number of expansions that this pack expansion will + /// Retrieve the number of expansions that this pack expansion will /// generate, if known. Optional<unsigned> getNumExpansions() const { if (NumExpansions) @@ -5418,8 +5585,8 @@ public: inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { QualType baseType = getBaseType(); - while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) { - if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT)) + while (const auto *ObjT = baseType->getAs<ObjCObjectType>()) { + if (const auto *T = dyn_cast<ObjCInterfaceType>(ObjT)) return T->getDecl(); baseType = ObjT->getBaseType(); @@ -5841,10 +6008,10 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const { } inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { - if (const PointerType *PT = t.getAs<PointerType>()) { - if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) + if (const auto *PT = t.getAs<PointerType>()) { + if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>()) return FT->getExtInfo(); - } else if (const FunctionType *FT = t.getAs<FunctionType>()) + } else if (const auto *FT = t.getAs<FunctionType>()) return FT->getExtInfo(); return FunctionType::ExtInfo(); @@ -5889,7 +6056,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { /// analysis, the expression designates the object or function /// denoted by the reference, and the expression is an lvalue. inline QualType QualType::getNonReferenceType() const { - if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>()) + if (const auto *RefType = (*this)->getAs<ReferenceType>()) return RefType->getPointeeType(); else return *this; @@ -5964,7 +6131,7 @@ inline bool Type::isRValueReferenceType() const { } inline bool Type::isFunctionPointerType() const { - if (const PointerType *T = getAs<PointerType>()) + if (const auto *T = getAs<PointerType>()) return T->getPointeeType()->isFunctionType(); else return false; @@ -5975,14 +6142,14 @@ inline bool Type::isMemberPointerType() const { } inline bool Type::isMemberFunctionPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) + if (const auto *T = getAs<MemberPointerType>()) return T->isMemberFunctionPointer(); else return false; } inline bool Type::isMemberDataPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) + if (const auto *T = getAs<MemberPointerType>()) return T->isMemberDataPointer(); else return false; @@ -6054,31 +6221,31 @@ inline bool Type::isAtomicType() const { } inline bool Type::isObjCQualifiedIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedIdType(); return false; } inline bool Type::isObjCQualifiedClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedClassType(); return false; } inline bool Type::isObjCIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCIdType(); return false; } inline bool Type::isObjCClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCClassType(); return false; } inline bool Type::isObjCSelType() const { - if (const PointerType *OPT = getAs<PointerType>()) + if (const auto *OPT = getAs<PointerType>()) return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); return false; } @@ -6141,13 +6308,13 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const { } inline bool Type::isPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return BT->isPlaceholderType(); return false; } inline const BuiltinType *Type::getAsPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) if (BT->isPlaceholderType()) return BT; return nullptr; @@ -6155,32 +6322,44 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { inline bool Type::isSpecificPlaceholderType(unsigned K) const { assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K)); - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return (BT->getKind() == (BuiltinType::Kind) K); return false; } inline bool Type::isNonOverloadPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return BT->isNonOverloadPlaceholderType(); return false; } inline bool Type::isVoidType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Void; return false; } inline bool Type::isHalfType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Half; // FIXME: Should we allow complex __fp16? Probably not. return false; } +inline bool Type::isFloat16Type() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Float16; + return false; +} + +inline bool Type::isFloat128Type() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Float128; + return false; +} + inline bool Type::isNullPtrType() const { - if (const BuiltinType *BT = getAs<BuiltinType>()) + if (const auto *BT = getAs<BuiltinType>()) return BT->getKind() == BuiltinType::NullPtr; return false; } @@ -6189,7 +6368,7 @@ bool IsEnumDeclComplete(EnumDecl *); bool IsEnumDeclScoped(EnumDecl *); inline bool Type::isIntegerType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { @@ -6201,8 +6380,46 @@ inline bool Type::isIntegerType() const { return false; } +inline bool Type::isFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isSaturatedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isUnsaturatedFixedPointType() const { + return isFixedPointType() && !isSaturatedFixedPointType(); +} + +inline bool Type::isSignedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return ((BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::LongAccum) || + (BT->getKind() >= BuiltinType::ShortFract && + BT->getKind() <= BuiltinType::LongFract) || + (BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatLongAccum) || + (BT->getKind() >= BuiltinType::SatShortFract && + BT->getKind() <= BuiltinType::SatLongFract)); + } + return false; +} + +inline bool Type::isUnsignedFixedPointType() const { + return isFixedPointType() && !isSignedFixedPointType(); +} + inline bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() > BuiltinType::Void && BT->getKind() <= BuiltinType::NullPtr; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) @@ -6217,20 +6434,20 @@ inline bool Type::isScalarType() const { } inline bool Type::isIntegralOrEnumerationType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; // Check for a complete enum type; incomplete enum types are not properly an // enumeration type in the sense required here. - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) return IsEnumDeclComplete(ET->getDecl()); return false; } inline bool Type::isBooleanType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Bool; return false; } @@ -6240,13 +6457,13 @@ inline bool Type::isUndeducedType() const { return DT && !DT->isDeduced(); } -/// \brief Determines whether this is a type for which one can define +/// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { return isDependentType() || isRecordType() || isEnumeralType(); } -/// \brief Determines whether this type can decay to a pointer type. +/// Determines whether this type can decay to a pointer type. inline bool Type::canDecayToPointerType() const { return isFunctionType() || isArrayType(); } @@ -6307,7 +6524,7 @@ template <typename T> const T *Type::getAs() const { "ArrayType cannot be used with getAs!"); // If this is directly a T type, return it. - if (const T *Ty = dyn_cast<T>(this)) + if (const auto *Ty = dyn_cast<T>(this)) return Ty; // If the canonical form of this type isn't the right kind, reject it. @@ -6323,7 +6540,7 @@ template <typename T> const T *Type::getAsAdjusted() const { static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!"); // If this is directly a T type, return it. - if (const T *Ty = dyn_cast<T>(this)) + if (const auto *Ty = dyn_cast<T>(this)) return Ty; // If the canonical form of this type isn't the right kind, reject it. @@ -6353,7 +6570,7 @@ template <typename T> const T *Type::getAsAdjusted() const { inline const ArrayType *Type::getAsArrayTypeUnsafe() const { // If this is directly an array type, return it. - if (const ArrayType *arr = dyn_cast<ArrayType>(this)) + if (const auto *arr = dyn_cast<ArrayType>(this)) return arr; // If the canonical form of this type isn't the right kind, reject it. @@ -6369,14 +6586,14 @@ template <typename T> const T *Type::castAs() const { static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with castAs!"); - if (const T *ty = dyn_cast<T>(this)) return ty; + if (const auto *ty = dyn_cast<T>(this)) return ty; assert(isa<T>(CanonicalType)); return cast<T>(getUnqualifiedDesugaredType()); } inline const ArrayType *Type::castAsArrayTypeUnsafe() const { assert(isa<ArrayType>(CanonicalType)); - if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr; + if (const auto *arr = dyn_cast<ArrayType>(this)) return arr; return cast<ArrayType>(getUnqualifiedDesugaredType()); } @@ -6396,6 +6613,12 @@ QualType DecayedType::getPointeeType() const { return cast<PointerType>(Decayed)->getPointeeType(); } +// Get the decimal string representation of a fixed point type, represented +// as a scaled integer. +void FixedPointValueToString(SmallVectorImpl<char> &Str, + const llvm::APSInt &Val, + unsigned Scale, unsigned Radix); + } // namespace clang #endif // LLVM_CLANG_AST_TYPE_H |