aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/Type.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Type.cpp')
-rw-r--r--clang/lib/AST/Type.cpp276
1 files changed, 181 insertions, 95 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 0f168a518707..a713d6e3bd03 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -42,7 +42,6 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
@@ -51,6 +50,7 @@
#include <cassert>
#include <cstdint>
#include <cstring>
+#include <optional>
#include <type_traits>
using namespace clang;
@@ -525,6 +525,10 @@ template <> const TypedefType *Type::getAs() const {
return getAsSugar<TypedefType>(this);
}
+template <> const UsingType *Type::getAs() const {
+ return getAsSugar<UsingType>(this);
+}
+
template <> const TemplateSpecializationType *Type::getAs() const {
return getAsSugar<TemplateSpecializationType>(this);
}
@@ -1073,7 +1077,7 @@ public:
if (exceptionChanged) {
info.ExceptionSpec.Exceptions =
- llvm::makeArrayRef(exceptionTypes).copy(Ctx);
+ llvm::ArrayRef(exceptionTypes).copy(Ctx);
}
}
@@ -1166,8 +1170,9 @@ public:
== T->getReplacementType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(),
- replacementType);
+ return Ctx.getSubstTemplateTypeParmType(replacementType,
+ T->getAssociatedDecl(),
+ T->getIndex(), T->getPackIndex());
}
// FIXME: Non-trivial to implement, but important for C++
@@ -1214,10 +1219,10 @@ public:
!typeArgChanged)
return QualType(T, 0);
- return Ctx.getObjCObjectType(baseType, typeArgs,
- llvm::makeArrayRef(T->qual_begin(),
- T->getNumProtocols()),
- T->isKindOfTypeAsWritten());
+ return Ctx.getObjCObjectType(
+ baseType, typeArgs,
+ llvm::ArrayRef(T->qual_begin(), T->getNumProtocols()),
+ T->isKindOfTypeAsWritten());
}
TRIVIAL_TYPE_CLASS(ObjCInterface)
@@ -1369,7 +1374,7 @@ struct SubstObjCTypeArgsVisitor
if (exceptionChanged) {
info.ExceptionSpec.Exceptions =
- llvm::makeArrayRef(exceptionTypes).copy(Ctx);
+ llvm::ArrayRef(exceptionTypes).copy(Ctx);
}
}
@@ -1479,6 +1484,25 @@ struct StripObjCKindOfTypeVisitor
} // namespace
+bool QualType::UseExcessPrecision(const ASTContext &Ctx) {
+ const BuiltinType *BT = getTypePtr()->getAs<BuiltinType>();
+ if (BT) {
+ switch (BT->getKind()) {
+ case BuiltinType::Kind::Float16: {
+ const TargetInfo &TI = Ctx.getTargetInfo();
+ if (TI.hasFloat16Type() && !TI.hasLegalHalfType() &&
+ Ctx.getLangOpts().getFloat16ExcessPrecision() !=
+ Ctx.getLangOpts().ExcessPrecisionKind::FPP_None)
+ return true;
+ return false;
+ }
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
/// Substitute the given type arguments for Objective-C type
/// parameters within the given type, recursively.
QualType QualType::substObjCTypeArgs(ASTContext &ctx,
@@ -1510,8 +1534,8 @@ QualType QualType::getAtomicUnqualifiedType() const {
return getUnqualifiedType();
}
-Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
- const DeclContext *dc) const {
+std::optional<ArrayRef<QualType>>
+Type::getObjCSubstitutions(const DeclContext *dc) const {
// Look through method scopes.
if (const auto method = dyn_cast<ObjCMethodDecl>(dc))
dc = method->getDeclContext();
@@ -1526,23 +1550,23 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
// substitution to do.
dcTypeParams = dcClassDecl->getTypeParamList();
if (!dcTypeParams)
- return None;
+ return std::nullopt;
} else {
// If we are in neither a class nor a category, there's no
// substitution to perform.
dcCategoryDecl = dyn_cast<ObjCCategoryDecl>(dc);
if (!dcCategoryDecl)
- return None;
+ return std::nullopt;
// If the category does not have any type parameters, there's no
// substitution to do.
dcTypeParams = dcCategoryDecl->getTypeParamList();
if (!dcTypeParams)
- return None;
+ return std::nullopt;
dcClassDecl = dcCategoryDecl->getClassInterface();
if (!dcClassDecl)
- return None;
+ return std::nullopt;
}
assert(dcTypeParams && "No substitutions to perform");
assert(dcClassDecl && "No class context");
@@ -2320,6 +2344,20 @@ bool Type::isSizelessBuiltinType() const {
bool Type::isSizelessType() const { return isSizelessBuiltinType(); }
+bool Type::isSVESizelessBuiltinType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ // SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
bool Type::isVLSTBuiltinType() const {
if (const BuiltinType *BT = getAs<BuiltinType>()) {
switch (BT->getKind()) {
@@ -2777,39 +2815,6 @@ bool Type::isStdByteType() const {
return false;
}
-bool Type::isPromotableIntegerType() const {
- if (const auto *BT = getAs<BuiltinType>())
- switch (BT->getKind()) {
- case BuiltinType::Bool:
- case BuiltinType::Char_S:
- case BuiltinType::Char_U:
- case BuiltinType::SChar:
- case BuiltinType::UChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- case BuiltinType::Char8:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- return true;
- default:
- return false;
- }
-
- // Enumerated types are promotable to their compatible integer types
- // (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
- if (const auto *ET = getAs<EnumType>()){
- if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull()
- || ET->getDecl()->isScoped())
- return false;
-
- return true;
- }
-
- return false;
-}
-
bool Type::isSpecifierType() const {
// Note that this intentionally does not use the canonical type.
switch (getTypeClass()) {
@@ -2928,7 +2933,7 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
DependentTemplateSpecializationTypeBits.NumArgs = Args.size();
assert((!NNS || NNS->isDependent()) &&
"DependentTemplateSpecializatonType requires dependent qualifier");
- TemplateArgument *ArgBuffer = getArgBuffer();
+ auto *ArgBuffer = const_cast<TemplateArgument *>(template_arguments().data());
for (const TemplateArgument &Arg : Args) {
addDependence(toTypeDependence(Arg.getDependence() &
TemplateArgumentDependence::UnexpandedPack));
@@ -3084,7 +3089,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
case Char32:
return "char32_t";
case NullPtr:
- return "std::nullptr_t";
+ return Policy.NullptrTypeInNamespace ? "std::nullptr_t" : "nullptr_t";
case Overload:
return "<overloaded function type>";
case BoundMember:
@@ -3434,25 +3439,34 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
}
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D,
- QualType underlying, QualType can)
- : Type(tc, can, toSemanticDependence(underlying->getDependence())),
+ QualType Underlying, QualType can)
+ : Type(tc, can, toSemanticDependence(can->getDependence())),
Decl(const_cast<TypedefNameDecl *>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ TypedefBits.hasTypeDifferentFromDecl = !Underlying.isNull();
+ if (!typeMatchesDecl())
+ *getTrailingObjects<QualType>() = Underlying;
}
QualType TypedefType::desugar() const {
- return getDecl()->getUnderlyingType();
+ return typeMatchesDecl() ? Decl->getUnderlyingType()
+ : *getTrailingObjects<QualType>();
}
UsingType::UsingType(const UsingShadowDecl *Found, QualType Underlying,
QualType Canon)
- : Type(Using, Canon, toSemanticDependence(Underlying->getDependence())),
+ : Type(Using, Canon, toSemanticDependence(Canon->getDependence())),
Found(const_cast<UsingShadowDecl *>(Found)) {
- assert(Underlying == getUnderlyingType());
+ UsingBits.hasTypeDifferentFromDecl = !Underlying.isNull();
+ if (!typeMatchesDecl())
+ *getTrailingObjects<QualType>() = Underlying;
}
QualType UsingType::getUnderlyingType() const {
- return QualType(cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl(), 0);
+ return typeMatchesDecl()
+ ? QualType(
+ cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl(), 0)
+ : *getTrailingObjects<QualType>();
}
QualType MacroQualifiedType::desugar() const { return getUnderlyingType(); }
@@ -3469,27 +3483,37 @@ QualType MacroQualifiedType::getModifiedType() const {
return Inner;
}
-TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
- : Type(TypeOfExpr, can,
+TypeOfExprType::TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can)
+ : Type(TypeOfExpr,
+ // We have to protect against 'Can' being invalid through its
+ // default argument.
+ Kind == TypeOfKind::Unqualified && !Can.isNull()
+ ? Can.getAtomicUnqualifiedType()
+ : Can,
toTypeDependence(E->getDependence()) |
(E->getType()->getDependence() &
TypeDependence::VariablyModified)),
- TOExpr(E) {}
+ TOExpr(E) {
+ TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified;
+}
bool TypeOfExprType::isSugared() const {
return !TOExpr->isTypeDependent();
}
QualType TypeOfExprType::desugar() const {
- if (isSugared())
- return getUnderlyingExpr()->getType();
-
+ if (isSugared()) {
+ QualType QT = getUnderlyingExpr()->getType();
+ return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT;
+ }
return QualType(this, 0);
}
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
- const ASTContext &Context, Expr *E) {
+ const ASTContext &Context, Expr *E,
+ bool IsUnqual) {
E->Profile(ID, Context, true);
+ ID.AddBoolean(IsUnqual);
}
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
@@ -3539,7 +3563,7 @@ TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
decl(const_cast<TagDecl *>(D)) {}
static TagDecl *getInterestingTagDecl(TagDecl *decl) {
- for (auto I : decl->redecls()) {
+ for (auto *I : decl->redecls()) {
if (I->isCompleteDefinition() || I->isBeingDefined())
return I;
}
@@ -3649,28 +3673,80 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier();
}
+static const TemplateTypeParmDecl *getReplacedParameter(Decl *D,
+ unsigned Index) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+ return TTP;
+ return cast<TemplateTypeParmDecl>(
+ getReplacedTemplateParameterList(D)->getParam(Index));
+}
+
+SubstTemplateTypeParmType::SubstTemplateTypeParmType(
+ QualType Replacement, Decl *AssociatedDecl, unsigned Index,
+ std::optional<unsigned> PackIndex)
+ : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
+ Replacement->getDependence()),
+ AssociatedDecl(AssociatedDecl) {
+ SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType =
+ Replacement != getCanonicalTypeInternal();
+ if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType)
+ *getTrailingObjects<QualType>() = Replacement;
+
+ SubstTemplateTypeParmTypeBits.Index = Index;
+ SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
+ assert(AssociatedDecl != nullptr);
+}
+
+const TemplateTypeParmDecl *
+SubstTemplateTypeParmType::getReplacedParameter() const {
+ return ::getReplacedParameter(getAssociatedDecl(), getIndex());
+}
+
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
- const TemplateTypeParmType *Param, QualType Canon,
+ QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon,
TypeDependence::DependentInstantiation |
TypeDependence::UnexpandedPack),
- Replaced(Param), Arguments(ArgPack.pack_begin()) {
+ Arguments(ArgPack.pack_begin()),
+ AssociatedDeclAndFinal(AssociatedDecl, Final) {
+ SubstTemplateTypeParmPackTypeBits.Index = Index;
SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
+ assert(AssociatedDecl != nullptr);
+}
+
+Decl *SubstTemplateTypeParmPackType::getAssociatedDecl() const {
+ return AssociatedDeclAndFinal.getPointer();
+}
+
+bool SubstTemplateTypeParmPackType::getFinal() const {
+ return AssociatedDeclAndFinal.getInt();
+}
+
+const TemplateTypeParmDecl *
+SubstTemplateTypeParmPackType::getReplacedParameter() const {
+ return ::getReplacedParameter(getAssociatedDecl(), getIndex());
+}
+
+IdentifierInfo *SubstTemplateTypeParmPackType::getIdentifier() const {
+ return getReplacedParameter()->getIdentifier();
}
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
- return TemplateArgument(llvm::makeArrayRef(Arguments, getNumArgs()));
+ return TemplateArgument(llvm::ArrayRef(Arguments, getNumArgs()));
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getReplacedParameter(), getArgumentPack());
+ Profile(ID, getAssociatedDecl(), getIndex(), getFinal(), getArgumentPack());
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
- const TemplateTypeParmType *Replaced,
+ const Decl *AssociatedDecl,
+ unsigned Index, bool Final,
const TemplateArgument &ArgPack) {
- ID.AddPointer(Replaced);
+ ID.AddPointer(AssociatedDecl);
+ ID.AddInteger(Index);
+ ID.AddBoolean(Final);
ID.AddInteger(ArgPack.pack_size());
for (const auto &P : ArgPack.pack_elements())
ID.AddPointer(P.getAsType().getAsOpaquePtr());
@@ -3740,10 +3816,22 @@ TemplateSpecializationType::TemplateSpecializationType(
// Store the aliased type if this is a type alias template specialization.
if (isTypeAlias()) {
auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
- *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType;
+ *reinterpret_cast<QualType *>(Begin + Args.size()) = AliasedType;
}
}
+QualType TemplateSpecializationType::getAliasedType() const {
+ assert(isTypeAlias() && "not a type alias template specialization");
+ return *reinterpret_cast<const QualType *>(template_arguments().end());
+}
+
+void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Ctx) {
+ Profile(ID, Template, template_arguments(), Ctx);
+ if (isTypeAlias())
+ getAliasedType().Profile(ID);
+}
+
void
TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
TemplateName T,
@@ -3780,14 +3868,14 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID,
for (auto typeArg : typeArgs)
ID.AddPointer(typeArg.getAsOpaquePtr());
ID.AddInteger(protocols.size());
- for (auto proto : protocols)
+ for (auto *proto : protocols)
ID.AddPointer(proto);
ID.AddBoolean(isKindOf);
}
void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getBaseType(), getTypeArgsAsWritten(),
- llvm::makeArrayRef(qual_begin(), getNumProtocols()),
+ llvm::ArrayRef(qual_begin(), getNumProtocols()),
isKindOfTypeAsWritten());
}
@@ -3798,13 +3886,13 @@ void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID,
ID.AddPointer(OTPDecl);
ID.AddPointer(CanonicalType.getAsOpaquePtr());
ID.AddInteger(protocols.size());
- for (auto proto : protocols)
+ for (auto *proto : protocols)
ID.AddPointer(proto);
}
void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), getCanonicalTypeInternal(),
- llvm::makeArrayRef(qual_begin(), getNumProtocols()));
+ llvm::ArrayRef(qual_begin(), getNumProtocols()));
}
namespace {
@@ -4091,8 +4179,7 @@ LinkageInfo Type::getLinkageAndVisibility() const {
return LinkageComputer{}.getTypeLinkageAndVisibility(this);
}
-Optional<NullabilityKind>
-Type::getNullability(const ASTContext &Context) const {
+std::optional<NullabilityKind> Type::getNullability() const {
QualType Type(this, 0);
while (const auto *AT = Type->getAs<AttributedType>()) {
// Check whether this is an attributed type with nullability
@@ -4102,7 +4189,7 @@ Type::getNullability(const ASTContext &Context) const {
Type = AT->getEquivalentType();
}
- return None;
+ return std::nullopt;
}
bool Type::canHaveNullability(bool ResultIfUnknown) const {
@@ -4233,8 +4320,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
llvm_unreachable("bad type kind!");
}
-llvm::Optional<NullabilityKind>
-AttributedType::getImmediateNullability() const {
+std::optional<NullabilityKind> AttributedType::getImmediateNullability() const {
if (getAttrKind() == attr::TypeNonNull)
return NullabilityKind::NonNull;
if (getAttrKind() == attr::TypeNullable)
@@ -4243,10 +4329,11 @@ AttributedType::getImmediateNullability() const {
return NullabilityKind::Unspecified;
if (getAttrKind() == attr::TypeNullableResult)
return NullabilityKind::NullableResult;
- return None;
+ return std::nullopt;
}
-Optional<NullabilityKind> AttributedType::stripOuterNullability(QualType &T) {
+std::optional<NullabilityKind>
+AttributedType::stripOuterNullability(QualType &T) {
QualType AttrTy = T;
if (auto MacroTy = dyn_cast<MacroQualifiedType>(T))
AttrTy = MacroTy->getUnderlyingType();
@@ -4258,7 +4345,7 @@ Optional<NullabilityKind> AttributedType::stripOuterNullability(QualType &T) {
}
}
- return None;
+ return std::nullopt;
}
bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
@@ -4320,20 +4407,13 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
}
bool Type::isObjCNSObjectType() const {
- const Type *cur = this;
- while (true) {
- if (const auto *typedefType = dyn_cast<TypedefType>(cur))
- return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
-
- // Single-step desugar until we run out of sugar.
- QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
- if (next.getTypePtr() == cur) return false;
- cur = next.getTypePtr();
- }
+ if (const auto *typedefType = getAs<TypedefType>())
+ return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+ return false;
}
bool Type::isObjCIndependentClassType() const {
- if (const auto *typedefType = dyn_cast<TypedefType>(this))
+ if (const auto *typedefType = getAs<TypedefType>())
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
return false;
}
@@ -4465,7 +4545,8 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
AutoTypeBits.NumArgs = TypeConstraintArgs.size();
this->TypeConstraintConcept = TypeConstraintConcept;
if (TypeConstraintConcept) {
- TemplateArgument *ArgBuffer = getArgBuffer();
+ auto *ArgBuffer =
+ const_cast<TemplateArgument *>(getTypeConstraintArguments().data());
for (const TemplateArgument &Arg : TypeConstraintArgs) {
addDependence(
toSyntacticDependence(toTypeDependence(Arg.getDependence())));
@@ -4486,3 +4567,8 @@ void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
for (const TemplateArgument &Arg : Arguments)
Arg.Profile(ID, Context);
}
+
+void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
+ Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(),
+ getTypeConstraintConcept(), getTypeConstraintArguments());
+}