diff options
Diffstat (limited to 'lib/AST/Type.cpp')
| -rw-r--r-- | lib/AST/Type.cpp | 342 |
1 files changed, 167 insertions, 175 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f79a59712a41..0dbc88c04521 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -291,6 +291,14 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type, return Context.getQualifiedType(desugar, split.Quals); } +// Check that no type class is polymorphic. LLVM style RTTI should be used +// instead. If absolutely needed an exception can still be added here by +// defining the appropriate macro (but please don't do this). +#define TYPE(CLASS, BASE) \ + static_assert(!std::is_polymorphic<CLASS##Type>::value, \ + #CLASS "Type should not be polymorphic!"); +#include "clang/AST/TypeNodes.def" + QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const { switch (getTypeClass()) { #define ABSTRACT_TYPE(Class, Parent) @@ -592,28 +600,6 @@ bool Type::isObjCClassOrClassKindOfType() const { return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType(); } -/// Was this type written with the special inert-in-MRC __unsafe_unretained -/// qualifier? -/// -/// This approximates the answer to the following question: if this -/// translation unit were compiled in ARC, would this type be qualified -/// with __unsafe_unretained? -bool Type::isObjCInertUnsafeUnretainedType() const { - const Type *cur = this; - while (true) { - if (const auto attributed = dyn_cast<AttributedType>(cur)) { - if (attributed->getAttrKind() == - AttributedType::attr_objc_inert_unsafe_unretained) - return true; - } - - // Single-step desugar until we run out of sugar. - QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); - if (next.getTypePtr() == cur) return false; - cur = next.getTypePtr(); - } -} - ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) @@ -1641,6 +1627,16 @@ TagDecl *Type::getAsTagDecl() const { return nullptr; } +bool Type::hasAttr(attr::Kind AK) const { + const Type *Cur = this; + while (const auto *AT = Cur->getAs<AttributedType>()) { + if (AT->getAttrKind() == AK) + return true; + Cur = AT->getEquivalentType().getTypePtr(); + } + return false; +} + namespace { class GetContainedDeducedTypeVisitor : @@ -1977,6 +1973,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer; if (BT->isInteger()) return STK_Integral; if (BT->isFloatingPoint()) return STK_Floating; + if (BT->isFixedPointType()) return STK_FixedPoint; llvm_unreachable("unknown scalar builtin type"); } else if (isa<PointerType>(T)) { return STK_CPointer; @@ -2604,7 +2601,8 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true, /*VariablyModified=*/false, NNS && NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name), NumArgs(Args.size()) { + NNS(NNS), Name(Name) { + DependentTemplateSpecializationTypeBits.NumArgs = Args.size(); assert((!NNS || NNS->isDependent()) && "DependentTemplateSpecializatonType requires dependent qualifier"); TemplateArgument *ArgBuffer = getArgBuffer(); @@ -2796,6 +2794,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "reserve_id_t"; case OMPArraySection: return "<OpenMP array section type>"; +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case Id: \ + return #ExtType; +#include "clang/Basic/OpenCLExtensionTypes.def" } llvm_unreachable("Invalid builtin type."); @@ -2830,6 +2832,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; + case CC_AArch64VectorCall: return "aarch64_vector_pcs"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_OpenCLKernel: return "opencl_kernel"; @@ -2844,24 +2847,28 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, canonical, - result->isDependentType(), + : FunctionType(FunctionProto, result, canonical, result->isDependentType(), result->isInstantiationDependentType(), result->isVariablyModifiedType(), - result->containsUnexpandedParameterPack(), epi.ExtInfo), - NumParams(params.size()), - NumExceptions(epi.ExceptionSpec.Exceptions.size()), - ExceptionSpecType(epi.ExceptionSpec.Type), - HasExtParameterInfos(epi.ExtParameterInfos != nullptr), - Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) { - assert(NumParams == params.size() && "function has too many parameters"); - - FunctionTypeBits.TypeQuals = epi.TypeQuals; + result->containsUnexpandedParameterPack(), epi.ExtInfo) { + FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers(); FunctionTypeBits.RefQualifier = epi.RefQualifier; + FunctionTypeBits.NumParams = params.size(); + assert(getNumParams() == params.size() && "NumParams overflow!"); + FunctionTypeBits.ExceptionSpecType = epi.ExceptionSpec.Type; + FunctionTypeBits.HasExtParameterInfos = !!epi.ExtParameterInfos; + FunctionTypeBits.Variadic = epi.Variadic; + FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn; + + // Fill in the extra trailing bitfields if present. + if (hasExtraBitfields(epi.ExceptionSpec.Type)) { + auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>(); + ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + } // Fill in the trailing argument array. - auto *argSlot = reinterpret_cast<QualType *>(this+1); - for (unsigned i = 0; i != NumParams; ++i) { + auto *argSlot = getTrailingObjects<QualType>(); + for (unsigned i = 0; i != getNumParams(); ++i) { if (params[i]->isDependentType()) setDependent(); else if (params[i]->isInstantiationDependentType()) @@ -2873,9 +2880,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, argSlot[i] = params[i]; } + // Fill in the exception type array if present. if (getExceptionSpecType() == EST_Dynamic) { - // Fill in the exception array. - QualType *exnSlot = argSlot + NumParams; + assert(hasExtraBitfields() && "missing trailing extra bitfields!"); + auto *exnSlot = + reinterpret_cast<QualType *>(getTrailingObjects<ExceptionType>()); unsigned I = 0; for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { // Note that, before C++17, a dependent exception specification does @@ -2889,14 +2898,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, exnSlot[I++] = ExceptionType; } - } else if (isComputedNoexcept(getExceptionSpecType())) { + } + // Fill in the Expr * in the exception specification if present. + else if (isComputedNoexcept(getExceptionSpecType())) { assert(epi.ExceptionSpec.NoexceptExpr && "computed noexcept with no expr"); assert((getExceptionSpecType() == EST_DependentNoexcept) == epi.ExceptionSpec.NoexceptExpr->isValueDependent()); // Store the noexcept expression and context. - auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams); - *noexSlot = epi.ExceptionSpec.NoexceptExpr; + *getTrailingObjects<Expr *>() = epi.ExceptionSpec.NoexceptExpr; if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() || epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent()) @@ -2904,10 +2914,12 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - } else if (getExceptionSpecType() == EST_Uninstantiated) { + } + // Fill in the FunctionDecl * in the exception specification if present. + else if (getExceptionSpecType() == EST_Uninstantiated) { // Store the function decl from which we will resolve our // exception specification. - auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); + auto **slot = getTrailingObjects<FunctionDecl *>(); slot[0] = epi.ExceptionSpec.SourceDecl; slot[1] = epi.ExceptionSpec.SourceTemplate; // This exception specification doesn't make the type dependent, because @@ -2915,7 +2927,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, } else if (getExceptionSpecType() == EST_Unevaluated) { // Store the function decl from which we will resolve our // exception specification. - auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); + auto **slot = getTrailingObjects<FunctionDecl *>(); slot[0] = epi.ExceptionSpec.SourceDecl; } @@ -2932,12 +2944,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, setDependent(); } + // Fill in the extra parameter info if present. if (epi.ExtParameterInfos) { - auto *extParamInfos = - const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer()); - for (unsigned i = 0; i != NumParams; ++i) + auto *extParamInfos = getTrailingObjects<ExtParameterInfo>(); + for (unsigned i = 0; i != getNumParams(); ++i) extParamInfos[i] = epi.ExtParameterInfos[i]; } + + if (epi.TypeQuals.hasNonFastQualifiers()) { + FunctionTypeBits.HasExtQuals = 1; + *getTrailingObjects<Qualifiers>() = epi.TypeQuals; + } else { + FunctionTypeBits.HasExtQuals = 0; + } } bool FunctionProtoType::hasDependentExceptionSpec() const { @@ -2981,7 +3000,7 @@ CanThrowResult FunctionProtoType::canThrow() const { case EST_Dynamic: // A dynamic exception specification is throwing unless every exception // type is an (unexpanded) pack expansion type. - for (unsigned I = 0, N = NumExceptions; I != N; ++I) + for (unsigned I = 0; I != getNumExceptions(); ++I) if (!getExceptionType(I)->getAs<PackExpansionType>()) return CT_Can; return CT_Dependent; @@ -3029,14 +3048,13 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, // shortcut, use one AddInteger call instead of four for the next four // fields. assert(!(unsigned(epi.Variadic) & ~1) && - !(unsigned(epi.TypeQuals) & ~255) && !(unsigned(epi.RefQualifier) & ~3) && !(unsigned(epi.ExceptionSpec.Type) & ~15) && "Values larger than expected."); ID.AddInteger(unsigned(epi.Variadic) + - (epi.TypeQuals << 1) + - (epi.RefQualifier << 9) + - (epi.ExceptionSpec.Type << 11)); + (epi.RefQualifier << 1) + + (epi.ExceptionSpec.Type << 3)); + ID.Add(epi.TypeQuals); if (epi.ExceptionSpec.Type == EST_Dynamic) { for (QualType Ex : epi.ExceptionSpec.Exceptions) ID.AddPointer(Ex.getAsOpaquePtr()); @@ -3056,8 +3074,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(), - Ctx, isCanonicalUnqualified()); + Profile(ID, getReturnType(), param_type_begin(), getNumParams(), + getExtProtoInfo(), Ctx, isCanonicalUnqualified()); } QualType TypedefType::desugar() const { @@ -3154,118 +3172,81 @@ bool TagType::isBeingDefined() const { } bool RecordType::hasConstFields() const { - for (FieldDecl *FD : getDecl()->fields()) { - QualType FieldTy = FD->getType(); - if (FieldTy.isConstQualified()) - return true; - FieldTy = FieldTy.getCanonicalType(); - if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) - if (FieldRecTy->hasConstFields()) + std::vector<const RecordType*> RecordTypeList; + RecordTypeList.push_back(this); + unsigned NextToCheckIndex = 0; + + while (RecordTypeList.size() > NextToCheckIndex) { + for (FieldDecl *FD : + RecordTypeList[NextToCheckIndex]->getDecl()->fields()) { + QualType FieldTy = FD->getType(); + if (FieldTy.isConstQualified()) return true; + FieldTy = FieldTy.getCanonicalType(); + if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) { + if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end()) + RecordTypeList.push_back(FieldRecTy); + } + } + ++NextToCheckIndex; } return false; } bool AttributedType::isQualifier() const { + // FIXME: Generate this with TableGen. switch (getAttrKind()) { // These are type qualifiers in the traditional C sense: they annotate // something about a specific value/variable of a type. (They aren't // always part of the canonical type, though.) - case AttributedType::attr_address_space: - case AttributedType::attr_objc_gc: - case AttributedType::attr_objc_ownership: - case AttributedType::attr_objc_inert_unsafe_unretained: - case AttributedType::attr_nonnull: - case AttributedType::attr_nullable: - case AttributedType::attr_null_unspecified: - case AttributedType::attr_lifetimebound: + case attr::ObjCGC: + case attr::ObjCOwnership: + case attr::ObjCInertUnsafeUnretained: + case attr::TypeNonNull: + case attr::TypeNullable: + case attr::TypeNullUnspecified: + case attr::LifetimeBound: return true; - // These aren't qualifiers; they rewrite the modified type to be a - // semantically different type. - case AttributedType::attr_regparm: - case AttributedType::attr_vector_size: - case AttributedType::attr_neon_vector_type: - case AttributedType::attr_neon_polyvector_type: - case AttributedType::attr_pcs: - case AttributedType::attr_pcs_vfp: - case AttributedType::attr_noreturn: - case AttributedType::attr_cdecl: - case AttributedType::attr_fastcall: - case AttributedType::attr_stdcall: - case AttributedType::attr_thiscall: - case AttributedType::attr_regcall: - case AttributedType::attr_pascal: - case AttributedType::attr_swiftcall: - case AttributedType::attr_vectorcall: - case AttributedType::attr_inteloclbicc: - case AttributedType::attr_preserve_most: - case AttributedType::attr_preserve_all: - case AttributedType::attr_ms_abi: - case AttributedType::attr_sysv_abi: - case AttributedType::attr_ptr32: - case AttributedType::attr_ptr64: - case AttributedType::attr_sptr: - case AttributedType::attr_uptr: - case AttributedType::attr_objc_kindof: - case AttributedType::attr_ns_returns_retained: - case AttributedType::attr_nocf_check: + // All other type attributes aren't qualifiers; they rewrite the modified + // type to be a semantically different type. + default: return false; } - llvm_unreachable("bad attributed type kind"); } bool AttributedType::isMSTypeSpec() const { + // FIXME: Generate this with TableGen? switch (getAttrKind()) { - default: return false; - case attr_ptr32: - case attr_ptr64: - case attr_sptr: - case attr_uptr: + default: return false; + case attr::Ptr32: + case attr::Ptr64: + case attr::SPtr: + case attr::UPtr: return true; } llvm_unreachable("invalid attr kind"); } bool AttributedType::isCallingConv() const { + // FIXME: Generate this with TableGen. switch (getAttrKind()) { - case attr_ptr32: - case attr_ptr64: - case attr_sptr: - case attr_uptr: - case attr_address_space: - case attr_regparm: - case attr_vector_size: - case attr_neon_vector_type: - case attr_neon_polyvector_type: - case attr_objc_gc: - case attr_objc_ownership: - case attr_objc_inert_unsafe_unretained: - case attr_noreturn: - case attr_nonnull: - case attr_ns_returns_retained: - case attr_nullable: - case attr_null_unspecified: - case attr_objc_kindof: - case attr_nocf_check: - case attr_lifetimebound: - return false; - - case attr_pcs: - case attr_pcs_vfp: - case attr_cdecl: - case attr_fastcall: - case attr_stdcall: - case attr_thiscall: - case attr_regcall: - case attr_swiftcall: - case attr_vectorcall: - case attr_pascal: - case attr_ms_abi: - case attr_sysv_abi: - case attr_inteloclbicc: - case attr_preserve_most: - case attr_preserve_all: + default: return false; + case attr::Pcs: + case attr::CDecl: + case attr::FastCall: + case attr::StdCall: + case attr::ThisCall: + case attr::RegCall: + case attr::SwiftCall: + case attr::VectorCall: + case attr::AArch64VectorPcs: + case attr::Pascal: + case attr::MSABI: + case attr::SysVABI: + case attr::IntelOclBicc: + case attr::PreserveMost: + case attr::PreserveAll: return true; } llvm_unreachable("invalid attr kind"); @@ -3284,11 +3265,12 @@ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack) : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), - Replaced(Param), - Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {} + Replaced(Param), Arguments(ArgPack.pack_begin()) { + SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size(); +} TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { - return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); + return TemplateArgument(llvm::makeArrayRef(Arguments, getNumArgs())); } void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { @@ -3335,8 +3317,10 @@ TemplateSpecializationType(TemplateName T, Canon.isNull()? true : Canon->isDependentType(), Canon.isNull()? true : Canon->isInstantiationDependentType(), false, - T.containsUnexpandedParameterPack()), - Template(T), NumArgs(Args.size()), TypeAlias(!AliasedType.isNull()) { + T.containsUnexpandedParameterPack()), Template(T) { + TemplateSpecializationTypeBits.NumArgs = Args.size(); + TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull(); + assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || @@ -3365,7 +3349,7 @@ TemplateSpecializationType(TemplateName T, } // Store the aliased type if this is a type alias template specialization. - if (TypeAlias) { + if (isTypeAlias()) { auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1); *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType; } @@ -3708,23 +3692,18 @@ LinkageInfo Type::getLinkageAndVisibility() const { return LinkageComputer{}.getTypeLinkageAndVisibility(this); } -Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const { - QualType type(this, 0); - do { +Optional<NullabilityKind> +Type::getNullability(const ASTContext &Context) const { + QualType Type(this, 0); + while (const auto *AT = Type->getAs<AttributedType>()) { // Check whether this is an attributed type with nullability // information. - if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) { - if (auto nullability = attributed->getImmediateNullability()) - return nullability; - } - - // Desugar the type. If desugaring does nothing, we're done. - QualType desugared = type.getSingleStepDesugaredType(context); - if (desugared.getTypePtr() == type.getTypePtr()) - return None; + if (auto Nullability = AT->getImmediateNullability()) + return Nullability; - type = desugared; - } while (true); + Type = AT->getEquivalentType(); + } + return None; } bool Type::canHaveNullability(bool ResultIfUnknown) const { @@ -3796,6 +3775,9 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: @@ -3837,12 +3819,13 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { llvm_unreachable("bad type kind!"); } -llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const { - if (getAttrKind() == AttributedType::attr_nonnull) +llvm::Optional<NullabilityKind> +AttributedType::getImmediateNullability() const { + if (getAttrKind() == attr::TypeNonNull) return NullabilityKind::NonNull; - if (getAttrKind() == AttributedType::attr_nullable) + if (getAttrKind() == attr::TypeNullable) return NullabilityKind::Nullable; - if (getAttrKind() == AttributedType::attr_null_unspecified) + if (getAttrKind() == attr::TypeNullUnspecified) return NullabilityKind::Unspecified; return None; } @@ -4032,17 +4015,26 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { } void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, - const llvm::APSInt &Val, unsigned Scale, - unsigned Radix) { - llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale); - llvm::APSInt IntPart = Val / ScaleVal; - llvm::APSInt FractPart = Val % ScaleVal; - llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix); + llvm::APSInt Val, unsigned Scale) { + if (Val.isSigned() && Val.isNegative() && Val != -Val) { + Val = -Val; + Str.push_back('-'); + } + + llvm::APSInt IntPart = Val >> Scale; + + // Add 4 digits to hold the value after multiplying 10 (the radix) + unsigned Width = Val.getBitWidth() + 4; + llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); + llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); + llvm::APInt RadixInt = llvm::APInt(Width, 10); - IntPart.toString(Str, Radix); + IntPart.toString(Str, /*radix=*/10); Str.push_back('.'); do { - (FractPart * RadixInt / ScaleVal).toString(Str, Radix); - FractPart = (FractPart * RadixInt) % ScaleVal; - } while (FractPart.getExtValue()); + (FractPart * RadixInt) + .lshr(Scale) + .toString(Str, /*radix=*/10, Val.isSigned()); + FractPart = (FractPart * RadixInt) & FractPartMask; + } while (FractPart != 0); } |
