diff options
Diffstat (limited to 'include/clang/AST/Type.h')
-rw-r--r-- | include/clang/AST/Type.h | 256 |
1 files changed, 142 insertions, 114 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index fb829e4d4103..09862e4fb7f7 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -18,20 +18,19 @@ #include "clang/AST/TemplateName.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" -#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/type_traits.h" namespace clang { enum { @@ -500,14 +499,14 @@ struct SplitQualType { /// The local qualifiers. Qualifiers Quals; - SplitQualType() : Ty(0), Quals() {} + SplitQualType() : Ty(nullptr), Quals() {} SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} SplitQualType getSingleStepDesugaredType() const; // end of this file - // Make llvm::tie work. - operator std::pair<const Type *,Qualifiers>() const { - return std::pair<const Type *,Qualifiers>(Ty, Quals); + // Make std::tie work. + std::pair<const Type *,Qualifiers> asPair() const { + return std::pair<const Type *, Qualifiers>(Ty, Quals); } friend bool operator==(SplitQualType a, SplitQualType b) { @@ -1438,7 +1437,7 @@ public: /// \brief 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 = 0) const; + bool isIncompleteType(NamedDecl **Def = nullptr) const; /// isIncompleteOrObjectType - Return true if this is an incomplete or object /// type, in other words, not a function type. @@ -1797,7 +1796,7 @@ public: return CanonicalType; } CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; friend class ASTReader; friend class ASTWriter; @@ -1996,39 +1995,59 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } }; -/// \brief Represents a pointer type decayed from an array or function type. -class DecayedType : public Type, public llvm::FoldingSetNode { - QualType OriginalType; - QualType DecayedPointer; +/// \brief Represents a type which was implicitly adjusted by the semantic +/// engine for arbitrary reasons. For example, array and function types can +/// decay, and function types can have their calling conventions adjusted. +class AdjustedType : public Type, public llvm::FoldingSetNode { + QualType OriginalTy; + QualType AdjustedTy; - DecayedType(QualType OriginalType, QualType DecayedPointer, - QualType CanonicalPtr) - : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(), - OriginalType->isInstantiationDependentType(), - OriginalType->isVariablyModifiedType(), - OriginalType->containsUnexpandedParameterPack()), - OriginalType(OriginalType), DecayedPointer(DecayedPointer) { - assert(isa<PointerType>(DecayedPointer)); - } +protected: + AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, + QualType CanonicalPtr) + : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), + OriginalTy->isInstantiationDependentType(), + OriginalTy->isVariablyModifiedType(), + OriginalTy->containsUnexpandedParameterPack()), + OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} friend class ASTContext; // ASTContext creates these. public: - QualType getDecayedType() const { return DecayedPointer; } - QualType getOriginalType() const { return OriginalType; } - - QualType getPointeeType() const { - return cast<PointerType>(DecayedPointer)->getPointeeType(); - } + QualType getOriginalType() const { return OriginalTy; } + QualType getAdjustedType() const { return AdjustedTy; } bool isSugared() const { return true; } - QualType desugar() const { return DecayedPointer; } + QualType desugar() const { return AdjustedTy; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, OriginalType); + Profile(ID, OriginalTy, AdjustedTy); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) { + ID.AddPointer(Orig.getAsOpaquePtr()); + ID.AddPointer(New.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Adjusted || T->getTypeClass() == Decayed; } - static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) { - ID.AddPointer(OriginalType.getAsOpaquePtr()); +}; + +/// \brief Represents a pointer type decayed from an array or function type. +class DecayedType : public AdjustedType { + + DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr) + : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) { + assert(isa<PointerType>(getAdjustedType())); + } + + friend class ASTContext; // ASTContext creates these. + +public: + QualType getDecayedType() const { return getAdjustedType(); } + + QualType getPointeeType() const { + return cast<PointerType>(getDecayedType())->getPointeeType(); } static bool classof(const Type *T) { return T->getTypeClass() == Decayed; } @@ -2185,6 +2204,7 @@ public: } const Type *getClass() const { return Class; } + CXXRecordDecl *getMostRecentCXXRecordDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2758,8 +2778,7 @@ protected: unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: - - QualType getResultType() const { return ResultType; } + QualType getReturnType() const { return ResultType; } bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } @@ -2776,7 +2795,7 @@ public: /// \brief Determine the type of an expression that calls a function of /// this type. QualType getCallResultType(ASTContext &Context) const { - return getResultType().getNonLValueExprType(Context); + return getReturnType().getNonLValueExprType(Context); } static StringRef getNameForCallConv(CallingConv CC); @@ -2805,7 +2824,7 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), getExtInfo()); + Profile(ID, getReturnType(), getExtInfo()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, ExtInfo Info) { @@ -2818,27 +2837,28 @@ public: } }; -/// FunctionProtoType - Represents a prototype with argument type info, e.g. +/// FunctionProtoType - Represents a prototype with parameter type info, e.g. /// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no -/// arguments, not as having a single void argument. Such a type can have an +/// parameters, not as having a single void parameter. Such a type can have an /// exception specification, but this specification is not part of the canonical /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { - ExtProtoInfo() : - Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), - NumExceptions(0), Exceptions(0), NoexceptExpr(0), - ExceptionSpecDecl(0), ExceptionSpecTemplate(0), - ConsumedArguments(0) {} + ExtProtoInfo() + : Variadic(false), HasTrailingReturn(false), TypeQuals(0), + ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), + Exceptions(nullptr), NoexceptExpr(nullptr), + ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), + ConsumedParameters(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0), - ExceptionSpecTemplate(0), ConsumedArguments(0) {} + Exceptions(nullptr), NoexceptExpr(nullptr), + ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), + ConsumedParameters(nullptr) {} FunctionType::ExtInfo ExtInfo; bool Variadic : 1; @@ -2851,7 +2871,7 @@ public: Expr *NoexceptExpr; FunctionDecl *ExceptionSpecDecl; FunctionDecl *ExceptionSpecTemplate; - const bool *ConsumedArguments; + const bool *ConsumedParameters; }; private: @@ -2866,11 +2886,11 @@ private: return false; } - FunctionProtoType(QualType result, ArrayRef<QualType> args, + FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi); - /// NumArgs - The number of arguments this function has, not counting '...'. - unsigned NumArgs : 15; + /// The number of parameters this function has, not counting '...'. + unsigned NumParams : 15; /// NumExceptions - The number of types in the exception spec, if any. unsigned NumExceptions : 9; @@ -2878,8 +2898,8 @@ private: /// ExceptionSpecType - The type of exception specification this function has. unsigned ExceptionSpecType : 3; - /// HasAnyConsumedArgs - Whether this function has any consumed arguments. - unsigned HasAnyConsumedArgs : 1; + /// HasAnyConsumedParams - Whether this function has any consumed parameters. + unsigned HasAnyConsumedParams : 1; /// Variadic - Whether the function is variadic. unsigned Variadic : 1; @@ -2892,8 +2912,8 @@ private: /// This is a value of type \c RefQualifierKind. unsigned RefQualifier : 2; - // ArgInfo - There is an variable size array after the class in memory that - // holds the argument types. + // ParamInfo - There is an variable size array after the class in memory that + // holds the parameter types. // Exceptions - There is another variable size array after ArgInfo that // holds the exception types. @@ -2906,17 +2926,17 @@ private: // instantiate this function type's exception specification, and the function // from which it should be instantiated. - // ConsumedArgs - A variable size array, following Exceptions - // and of length NumArgs, holding flags indicating which arguments - // are consumed. This only appears if HasAnyConsumedArgs is true. + // ConsumedParameters - A variable size array, following Exceptions + // and of length NumParams, holding flags indicating which parameters + // are consumed. This only appears if HasAnyConsumedParams is true. friend class ASTContext; // ASTContext creates these. - const bool *getConsumedArgsBuffer() const { - assert(hasAnyConsumedArgs()); + const bool *getConsumedParamsBuffer() const { + assert(hasAnyConsumedParams()); // Find the end of the exceptions. - Expr * const *eh_end = reinterpret_cast<Expr * const *>(arg_type_end()); + Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end()); if (getExceptionSpecType() != EST_ComputedNoexcept) eh_end += NumExceptions; else @@ -2926,13 +2946,13 @@ private: } public: - unsigned getNumArgs() const { return NumArgs; } - QualType getArgType(unsigned i) const { - assert(i < NumArgs && "Invalid argument number!"); - return arg_type_begin()[i]; + unsigned getNumParams() const { return NumParams; } + QualType getParamType(unsigned i) const { + assert(i < NumParams && "invalid parameter index"); + return param_type_begin()[i]; } - ArrayRef<QualType> getArgTypes() const { - return ArrayRef<QualType>(arg_type_begin(), arg_type_end()); + ArrayRef<QualType> getParamTypes() const { + return ArrayRef<QualType>(param_type_begin(), param_type_end()); } ExtProtoInfo getExtProtoInfo() const { @@ -2954,8 +2974,8 @@ public: } else if (EPI.ExceptionSpecType == EST_Unevaluated) { EPI.ExceptionSpecDecl = getExceptionSpecDecl(); } - if (hasAnyConsumedArgs()) - EPI.ConsumedArguments = getConsumedArgsBuffer(); + if (hasAnyConsumedParams()) + EPI.ConsumedParameters = getConsumedParamsBuffer(); return EPI; } @@ -2992,9 +3012,9 @@ public: } Expr *getNoexceptExpr() const { if (getExceptionSpecType() != EST_ComputedNoexcept) - return 0; + return nullptr; // NoexceptExpr sits where the arguments end. - return *reinterpret_cast<Expr *const *>(arg_type_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 @@ -3003,8 +3023,8 @@ public: FunctionDecl *getExceptionSpecDecl() const { if (getExceptionSpecType() != EST_Uninstantiated && getExceptionSpecType() != EST_Unevaluated) - return 0; - return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0]; + 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 @@ -3012,18 +3032,13 @@ public: /// this type. FunctionDecl *getExceptionSpecTemplate() const { if (getExceptionSpecType() != EST_Uninstantiated) - return 0; - return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1]; - } - bool isNothrow(const ASTContext &Ctx) const { - ExceptionSpecificationType EST = getExceptionSpecType(); - assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); - if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) - return true; - if (EST != EST_ComputedNoexcept) - return false; - return getNoexceptSpec(Ctx) == NR_Nothrow; + return nullptr; + return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; } + /// \brief 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; bool isVariadic() const { return Variadic; } @@ -3045,16 +3060,28 @@ public: return static_cast<RefQualifierKind>(RefQualifier); } - typedef const QualType *arg_type_iterator; - arg_type_iterator arg_type_begin() const { + typedef const QualType *param_type_iterator; + typedef llvm::iterator_range<param_type_iterator> param_type_range; + + 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); } - arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; } + param_type_iterator param_type_end() const { + return param_type_begin() + NumParams; + } typedef const QualType *exception_iterator; + typedef llvm::iterator_range<exception_iterator> exception_range; + + exception_range exceptions() const { + return exception_range(exception_begin(), exception_end()); + } exception_iterator exception_begin() const { // exceptions begin where arguments end - return arg_type_end(); + return param_type_end(); } exception_iterator exception_end() const { if (getExceptionSpecType() != EST_Dynamic) @@ -3062,13 +3089,11 @@ public: return exception_begin() + NumExceptions; } - bool hasAnyConsumedArgs() const { - return HasAnyConsumedArgs; - } - bool isArgConsumed(unsigned I) const { - assert(I < getNumArgs() && "argument index out of range!"); - if (hasAnyConsumedArgs()) - return getConsumedArgsBuffer()[I]; + bool hasAnyConsumedParams() const { return HasAnyConsumedParams; } + bool isParamConsumed(unsigned I) const { + assert(I < getNumParams() && "parameter index out of range"); + if (hasAnyConsumedParams()) + return getConsumedParamsBuffer()[I]; return false; } @@ -3084,7 +3109,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, - arg_type_iterator ArgTys, unsigned NumArgs, + param_type_iterator ArgTys, unsigned NumArgs, const ExtProtoInfo &EPI, const ASTContext &Context); }; @@ -3495,7 +3520,7 @@ public: bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } TemplateTypeParmDecl *getDecl() const { - return isCanonicalUnqualified() ? 0 : TTPDecl; + return isCanonicalUnqualified() ? nullptr : TTPDecl; } IdentifierInfo *getIdentifier() const; @@ -3956,9 +3981,9 @@ public: static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); - static const char *getKeywordName(ElaboratedTypeKeyword Keyword); + static StringRef getKeywordName(ElaboratedTypeKeyword Keyword); - static const char *getTagTypeKindName(TagTypeKind Kind) { + static StringRef getTagTypeKindName(TagTypeKind Kind) { return getKeywordName(getKeywordForTagTypeKind(Kind)); } @@ -3990,7 +4015,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { NamedType->isVariablyModifiedType(), NamedType->containsUnexpandedParameterPack()), NNS(NNS), NamedType(NamedType) { - assert(!(Keyword == ETK_None && NNS == 0) && + assert(!(Keyword == ETK_None && NNS == nullptr) && "ElaboratedType cannot have elaborated type keyword " "and name qualifier both null."); } @@ -4032,11 +4057,14 @@ public: /// dependent. /// /// DependentNameType represents a class of dependent types that involve a -/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) +/// possibly dependent nested-name-specifier (e.g., "T::") followed by a /// name of a type. The DependentNameType may start with a "typename" (for a /// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). +/// Typically the nested-name-specifier is dependent, but in MSVC compatibility +/// mode, this type is used with non-dependent names to delay name lookup until +/// instantiation. class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The nested name specifier containing the qualifier. @@ -4051,10 +4079,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /*InstantiationDependent=*/true, /*VariablyModified=*/false, NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name) { - assert(NNS->isDependent() && - "DependentNameType requires a dependent nested-name-specifier"); - } + NNS(NNS), Name(Name) {} friend class ASTContext; // ASTContext creates these @@ -4199,7 +4224,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { Optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), /*InstantiationDependent=*/true, - /*VariableModified=*/Pattern->isVariablyModifiedType(), + /*VariablyModified=*/Pattern->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), Pattern(Pattern), NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } @@ -4326,7 +4351,9 @@ public: ObjCInterfaceDecl *getInterface() const; typedef ObjCProtocolDecl * const *qual_iterator; + typedef llvm::iterator_range<qual_iterator> qual_range; + qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getProtocolStorage(); } qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } @@ -4430,7 +4457,7 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { if (const ObjCInterfaceType *T = getBaseType()->getAs<ObjCInterfaceType>()) return T->getDecl(); - return 0; + return nullptr; } /// ObjCObjectPointerType - Used to represent a pointer to an @@ -4528,7 +4555,9 @@ public: /// 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; + qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getObjectType()->qual_begin(); } @@ -4633,7 +4662,7 @@ inline const Type *QualType::getTypePtr() const { } inline const Type *QualType::getTypePtrOrNull() const { - return (isNull() ? 0 : getCommonPtr()->BaseType); + return (isNull() ? nullptr : getCommonPtr()->BaseType); } inline SplitQualType QualType::split() const { @@ -5022,7 +5051,7 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) if (BT->isPlaceholderType()) return BT; - return 0; + return nullptr; } inline bool Type::isSpecificPlaceholderType(unsigned K) const { @@ -5159,10 +5188,9 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, // Helper class template that is used by Type::getAs to ensure that one does // not try to look through a qualified type to get to an array type. -template<typename T, - bool isArrayType = (llvm::is_same<T, ArrayType>::value || - llvm::is_base_of<ArrayType, T>::value)> -struct ArrayType_cannot_be_used_with_getAs { }; +template <typename T, bool isArrayType = (std::is_same<T, ArrayType>::value || + std::is_base_of<ArrayType, T>::value)> +struct ArrayType_cannot_be_used_with_getAs {}; template<typename T> struct ArrayType_cannot_be_used_with_getAs<T, true>; @@ -5178,7 +5206,7 @@ template <typename T> const T *Type::getAs() const { // If the canonical form of this type isn't the right kind, reject it. if (!isa<T>(CanonicalType)) - return 0; + return nullptr; // If this is a typedef for the type, strip the typedef off without // losing all typedef information. @@ -5192,7 +5220,7 @@ inline const ArrayType *Type::getAsArrayTypeUnsafe() const { // If the canonical form of this type isn't the right kind, reject it. if (!isa<ArrayType>(CanonicalType)) - return 0; + return nullptr; // If this is a typedef for the type, strip the typedef off without // losing all typedef information. |