summaryrefslogtreecommitdiff
path: root/lib/AST/Type.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/Type.cpp')
-rw-r--r--lib/AST/Type.cpp547
1 files changed, 436 insertions, 111 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d287552844776..08971eb034215 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -36,7 +36,10 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const {
(hasObjCGCAttr() && !Other.hasObjCGCAttr())) &&
// Address space superset.
((getAddressSpace() == Other.getAddressSpace()) ||
- (hasAddressSpace()&& !Other.hasAddressSpace()));
+ (hasAddressSpace()&& !Other.hasAddressSpace())) &&
+ // Lifetime qualifier superset.
+ ((getObjCLifetime() == Other.getObjCLifetime()) ||
+ (hasObjCLifetime() && !Other.hasObjCLifetime()));
}
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -107,6 +110,7 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const
Expr *SizeExpr,
SourceLocation loc)
: Type(DependentSizedExtVector, can, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
ElementType->isVariablyModifiedType(),
(ElementType->containsUnexpandedParameterPack() ||
(SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
@@ -126,6 +130,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
: Type(Vector, canonType, vecType->isDependentType(),
+ vecType->isInstantiationDependentType(),
vecType->isVariablyModifiedType(),
vecType->containsUnexpandedParameterPack()),
ElementType(vecType)
@@ -137,6 +142,7 @@ VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
: Type(tc, canonType, vecType->isDependentType(),
+ vecType->isInstantiationDependentType(),
vecType->isVariablyModifiedType(),
vecType->containsUnexpandedParameterPack()),
ElementType(vecType)
@@ -174,6 +180,26 @@ QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) {
return Context.getQualifiedType(split.first, split.second);
}
+QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const {
+ QualifierCollector Qs;
+
+ const Type *CurTy = Qs.strip(*this);
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return *this; \
+ return Context.getQualifiedType(Ty->desugar(), Qs); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ return *this;
+}
+
SplitQualType QualType::getSplitDesugaredType(QualType T) {
QualifierCollector Qs;
@@ -285,7 +311,6 @@ bool Type::isDerivedType() const {
return false;
}
}
-
bool Type::isClassType() const {
if (const RecordType *RT = getAs<RecordType>())
return RT->getDecl()->isClass();
@@ -385,7 +410,7 @@ const RecordType *Type::getAsUnionType() const {
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
- : Type(ObjCObject, Canonical, false, false, false),
+ : Type(ObjCObject, Canonical, false, false, false, false),
BaseType(Base)
{
ObjCObjectTypeBits.NumProtocols = NumProtocols;
@@ -866,39 +891,57 @@ bool Type::isIncompleteType() const {
}
}
-/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
-bool Type::isPODType() const {
+bool QualType::isPODType(ASTContext &Context) const {
// The compiler shouldn't query this for incomplete types, but the user might.
// We return false for that case. Except for incomplete arrays of PODs, which
// are PODs according to the standard.
- if (isIncompleteArrayType() &&
- cast<ArrayType>(CanonicalType)->getElementType()->isPODType())
- return true;
- if (isIncompleteType())
+ if (isNull())
+ return 0;
+
+ if ((*this)->isIncompleteArrayType())
+ return Context.getBaseElementType(*this).isPODType(Context);
+
+ if ((*this)->isIncompleteType())
return false;
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ break;
+ }
+ }
+
+ QualType CanonicalType = getTypePtr()->CanonicalType;
switch (CanonicalType->getTypeClass()) {
// Everything not explicitly mentioned is not POD.
default: return false;
- case VariableArray:
- case ConstantArray:
+ case Type::VariableArray:
+ case Type::ConstantArray:
// IncompleteArray is handled above.
- return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
-
- case Builtin:
- case Complex:
- case Pointer:
- case MemberPointer:
- case Vector:
- case ExtVector:
- case ObjCObjectPointer:
- case BlockPointer:
+ return Context.getBaseElementType(*this).isPODType(Context);
+
+ case Type::ObjCObjectPointer:
+ case Type::BlockPointer:
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Pointer:
+ case Type::MemberPointer:
+ case Type::Vector:
+ case Type::ExtVector:
return true;
- case Enum:
+ case Type::Enum:
return true;
- case Record:
+ case Type::Record:
if (CXXRecordDecl *ClassDecl
= dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
return ClassDecl->isPOD();
@@ -908,6 +951,121 @@ bool Type::isPODType() const {
}
}
+bool QualType::isTrivialType(ASTContext &Context) const {
+ // The compiler shouldn't query this for incomplete types, but the user might.
+ // We return false for that case. Except for incomplete arrays of PODs, which
+ // are PODs according to the standard.
+ if (isNull())
+ return 0;
+
+ if ((*this)->isArrayType())
+ return Context.getBaseElementType(*this).isTrivialType(Context);
+
+ // Return false for incomplete types after skipping any incomplete array
+ // types which are expressly allowed by the standard and thus our API.
+ if ((*this)->isIncompleteType())
+ return false;
+
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if ((*this)->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
+ QualType CanonicalType = getTypePtr()->CanonicalType;
+ if (CanonicalType->isDependentType())
+ return false;
+
+ // C++0x [basic.types]p9:
+ // Scalar types, trivial class types, arrays of such types, and
+ // cv-qualified versions of these types are collectively called trivial
+ // types.
+
+ // As an extension, Clang treats vector types as Scalar types.
+ if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+ return true;
+ if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+ if (const CXXRecordDecl *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ // C++0x [class]p5:
+ // A trivial class is a class that has a trivial default constructor
+ if (!ClassDecl->hasTrivialDefaultConstructor()) return false;
+ // and is trivially copyable.
+ if (!ClassDecl->isTriviallyCopyable()) return false;
+ }
+
+ return true;
+ }
+
+ // No other types can match.
+ return false;
+}
+
+bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
+ if ((*this)->isArrayType())
+ return Context.getBaseElementType(*this).isTrivialType(Context);
+
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if ((*this)->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
+ // C++0x [basic.types]p9
+ // Scalar types, trivially copyable class types, arrays of such types, and
+ // cv-qualified versions of these types are collectively called trivial
+ // types.
+
+ QualType CanonicalType = getCanonicalType();
+ if (CanonicalType->isDependentType())
+ return false;
+
+ // Return false for incomplete types after skipping any incomplete array types
+ // which are expressly allowed by the standard and thus our API.
+ if (CanonicalType->isIncompleteType())
+ return false;
+
+ // As an extension, Clang treats vector types as Scalar types.
+ if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+ return true;
+
+ if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+ if (const CXXRecordDecl *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (!ClassDecl->isTriviallyCopyable()) return false;
+ }
+
+ return true;
+ }
+
+ // No other types can match.
+ return false;
+}
+
+
+
bool Type::isLiteralType() const {
if (isDependentType())
return false;
@@ -928,6 +1086,10 @@ bool Type::isLiteralType() const {
if (BaseTy->isIncompleteType())
return false;
+ // Objective-C lifetime types are not literal types.
+ if (BaseTy->isObjCRetainableType())
+ return false;
+
// C++0x [basic.types]p10:
// A type is a literal type if it is:
// -- a scalar type; or
@@ -961,68 +1123,6 @@ bool Type::isLiteralType() const {
return false;
}
-bool Type::isTrivialType() const {
- if (isDependentType())
- return false;
-
- // C++0x [basic.types]p9:
- // Scalar types, trivial class types, arrays of such types, and
- // cv-qualified versions of these types are collectively called trivial
- // types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
- assert(BaseTy && "NULL element type");
-
- // Return false for incomplete types after skipping any incomplete array
- // types which are expressly allowed by the standard and thus our API.
- if (BaseTy->isIncompleteType())
- return false;
-
- // As an extension, Clang treats vector types as Scalar types.
- if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (!ClassDecl->isTrivial()) return false;
- }
-
- return true;
- }
-
- // No other types can match.
- return false;
-}
-
-bool Type::isTriviallyCopyableType() const {
- if (isDependentType())
- return false;
-
- // C++0x [basic.types]p9
- // Scalar types, trivially copyable class types, arrays of such types, and
- // cv-qualified versions of these types are collectively called trivial
- // types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
- assert(BaseTy && "NULL element type");
-
- // Return false for incomplete types after skipping any incomplete array types
- // which are expressly allowed by the standard and thus our API.
- if (BaseTy->isIncompleteType())
- return false;
-
- // As an extension, Clang treats vector types as Scalar types.
- if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (!ClassDecl->isTriviallyCopyable()) return false;
- }
-
- return true;
- }
-
- // No other types can match.
- return false;
-}
-
bool Type::isStandardLayoutType() const {
if (isDependentType())
return false;
@@ -1060,14 +1160,32 @@ bool Type::isStandardLayoutType() const {
// This is effectively the intersection of isTrivialType and
// isStandardLayoutType. We implement it dircetly to avoid redundant
// conversions from a type to a CXXRecordDecl.
-bool Type::isCXX11PODType() const {
- if (isDependentType())
+bool QualType::isCXX11PODType(ASTContext &Context) const {
+ const Type *ty = getTypePtr();
+ if (ty->isDependentType())
return false;
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if (ty->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
// C++11 [basic.types]p9:
// Scalar types, POD classes, arrays of such types, and cv-qualified
// versions of these types are collectively called trivial types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
+ const Type *BaseTy = ty->getBaseElementTypeUnsafe();
assert(BaseTy && "NULL element type");
// Return false for incomplete types after skipping any incomplete array
@@ -1253,7 +1371,7 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
NestedNameSpecifier *NNS, const IdentifierInfo *Name,
unsigned NumArgs, const TemplateArgument *Args,
QualType Canon)
- : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true,
/*VariablyModified=*/false,
NNS && NNS->containsUnexpandedParameterPack()),
NNS(NNS), Name(Name), NumArgs(NumArgs) {
@@ -1388,18 +1506,22 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
: FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals,
epi.RefQualifier, canonical,
result->isDependentType(),
+ result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
result->containsUnexpandedParameterPack(),
epi.ExtInfo),
NumArgs(numArgs), NumExceptions(epi.NumExceptions),
- ExceptionSpecType(epi.ExceptionSpecType)
+ ExceptionSpecType(epi.ExceptionSpecType),
+ HasAnyConsumedArgs(epi.ConsumedArguments != 0)
{
// Fill in the trailing argument array.
QualType *argSlot = reinterpret_cast<QualType*>(this+1);
for (unsigned i = 0; i != numArgs; ++i) {
if (args[i]->isDependentType())
setDependent();
-
+ else if (args[i]->isInstantiationDependentType())
+ setInstantiationDependent();
+
if (args[i]->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
@@ -1412,7 +1534,9 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) {
if (epi.Exceptions[i]->isDependentType())
setDependent();
-
+ else if (epi.Exceptions[i]->isInstantiationDependentType())
+ setInstantiationDependent();
+
if (epi.Exceptions[i]->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
@@ -1422,6 +1546,20 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
// Store the noexcept expression and context.
Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs);
*noexSlot = epi.NoexceptExpr;
+
+ if (epi.NoexceptExpr) {
+ if (epi.NoexceptExpr->isValueDependent()
+ || epi.NoexceptExpr->isTypeDependent())
+ setDependent();
+ else if (epi.NoexceptExpr->isInstantiationDependent())
+ setInstantiationDependent();
+ }
+ }
+
+ if (epi.ConsumedArguments) {
+ bool *consumedArgs = const_cast<bool*>(getConsumedArgsBuffer());
+ for (unsigned i = 0; i != numArgs; ++i)
+ consumedArgs[i] = epi.ConsumedArguments[i];
}
}
@@ -1461,18 +1599,48 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumArgs,
const ExtProtoInfo &epi,
const ASTContext &Context) {
+
+ // We have to be careful not to get ambiguous profile encodings.
+ // Note that valid type pointers are never ambiguous with anything else.
+ //
+ // The encoding grammar begins:
+ // type type* bool int bool
+ // If that final bool is true, then there is a section for the EH spec:
+ // bool type*
+ // This is followed by an optional "consumed argument" section of the
+ // same length as the first type sequence:
+ // bool*
+ // Finally, we have the ext info:
+ // int
+ //
+ // There is no ambiguity between the consumed arguments and an empty EH
+ // spec because of the leading 'bool' which unambiguously indicates
+ // whether the following bool is the EH spec or part of the arguments.
+
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
- ID.AddBoolean(epi.Variadic);
- ID.AddInteger(epi.TypeQuals);
- ID.AddInteger(epi.RefQualifier);
- ID.AddInteger(epi.ExceptionSpecType);
+ // This method is relatively performance sensitive, so as a performance
+ // 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.ExceptionSpecType) & ~7) &&
+ "Values larger than expected.");
+ ID.AddInteger(unsigned(epi.Variadic) +
+ (epi.TypeQuals << 1) +
+ (epi.RefQualifier << 9) +
+ (epi.ExceptionSpecType << 11));
if (epi.ExceptionSpecType == EST_Dynamic) {
for (unsigned i = 0; i != epi.NumExceptions; ++i)
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
- epi.NoexceptExpr->Profile(ID, Context, true);
+ epi.NoexceptExpr->Profile(ID, Context, false);
+ }
+ if (epi.ConsumedArguments) {
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddBoolean(epi.ConsumedArguments[i]);
}
epi.ExtInfo.Profile(ID);
}
@@ -1489,13 +1657,21 @@ QualType TypedefType::desugar() const {
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
: Type(TypeOfExpr, can, E->isTypeDependent(),
+ E->isInstantiationDependent(),
E->getType()->isVariablyModifiedType(),
E->containsUnexpandedParameterPack()),
TOExpr(E) {
}
+bool TypeOfExprType::isSugared() const {
+ return !TOExpr->isTypeDependent();
+}
+
QualType TypeOfExprType::desugar() const {
- return getUnderlyingExpr()->getType();
+ if (isSugared())
+ return getUnderlyingExpr()->getType();
+
+ return QualType(this, 0);
}
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
@@ -1505,12 +1681,22 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
: Type(Decltype, can, E->isTypeDependent(),
+ E->isInstantiationDependent(),
E->getType()->isVariablyModifiedType(),
E->containsUnexpandedParameterPack()),
E(E),
UnderlyingType(underlyingType) {
}
+bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
+
+QualType DecltypeType::desugar() const {
+ if (isSugared())
+ return getUnderlyingType();
+
+ return QualType(this, 0);
+}
+
DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
: DecltypeType(E, Context.DependentTy), Context(Context) { }
@@ -1520,7 +1706,9 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false,
+ : Type(TC, can, D->isDependentType(),
+ /*InstantiationDependent=*/D->isDependentType(),
+ /*VariablyModified=*/false,
/*ContainsUnexpandedParameterPack=*/false),
decl(const_cast<TagDecl*>(D)) {}
@@ -1540,6 +1728,7 @@ UnaryTransformType::UnaryTransformType(QualType BaseType,
UTTKind UKind,
QualType CanonicalType)
: Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(),
+ UnderlyingType->isInstantiationDependentType(),
UnderlyingType->isVariablyModifiedType(),
BaseType->containsUnexpandedParameterPack())
, BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
@@ -1573,7 +1762,8 @@ SubstTemplateTypeParmPackType::
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack)
- : Type(SubstTemplateTypeParmPack, Canon, true, false, true), Replaced(Param),
+ : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
+ Replaced(Param),
Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size())
{
}
@@ -1598,23 +1788,39 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) {
- return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size());
+anyDependentTemplateArguments(const TemplateArgumentListInfo &Args,
+ bool &InstantiationDependent) {
+ return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size(),
+ InstantiationDependent);
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
- for (unsigned i = 0; i != N; ++i)
- if (Args[i].getArgument().isDependent())
+anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N,
+ bool &InstantiationDependent) {
+ for (unsigned i = 0; i != N; ++i) {
+ if (Args[i].getArgument().isDependent()) {
+ InstantiationDependent = true;
return true;
+ }
+
+ if (Args[i].getArgument().isInstantiationDependent())
+ InstantiationDependent = true;
+ }
return false;
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
- for (unsigned i = 0; i != N; ++i)
- if (Args[i].isDependent())
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N,
+ bool &InstantiationDependent) {
+ for (unsigned i = 0; i != N; ++i) {
+ if (Args[i].isDependent()) {
+ InstantiationDependent = true;
return true;
+ }
+
+ if (Args[i].isInstantiationDependent())
+ InstantiationDependent = true;
+ }
return false;
}
@@ -1625,12 +1831,22 @@ TemplateSpecializationType(TemplateName T,
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
Canon.isNull()? T.isDependent() : Canon->isDependentType(),
+ Canon.isNull()? T.isDependent()
+ : Canon->isInstantiationDependentType(),
false, T.containsUnexpandedParameterPack()),
Template(T), NumArgs(NumArgs) {
assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
+ assert((T.getKind() == TemplateName::Template ||
+ T.getKind() == TemplateName::SubstTemplateTemplateParm ||
+ T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
+ "Unexpected template name for TemplateSpecializationType");
+ bool InstantiationDependent;
+ (void)InstantiationDependent;
assert((!Canon.isNull() ||
- T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
+ T.isDependent() ||
+ anyDependentTemplateArguments(Args, NumArgs,
+ InstantiationDependent)) &&
"No canonical type for non-dependent class template specialization");
TemplateArgument *TemplateArgs
@@ -1644,6 +1860,9 @@ TemplateSpecializationType(TemplateName T,
// U<T> is always non-dependent, irrespective of the type T.
if (Canon.isNull() && Args[Arg].isDependent())
setDependent();
+ else if (Args[Arg].isInstantiationDependent())
+ setInstantiationDependent();
+
if (Args[Arg].getKind() == TemplateArgument::Type &&
Args[Arg].getAsType()->isVariablyModifiedType())
setVariablyModified();
@@ -1795,8 +2014,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
#define DEPENDENT_TYPE(Class,Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
- // Treat dependent types as external.
- assert(T->isDependentType());
+ // Treat instantiation-dependent types as external.
+ assert(T->isInstantiationDependentType());
return CachedProperties(ExternalLinkage, DefaultVisibility, false);
case Type::Builtin:
@@ -1900,6 +2119,79 @@ void Type::ClearLinkageCache() {
CanonicalType->TypeBits.CacheValidAndVisibility = 0;
}
+Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const {
+ if (isObjCARCImplicitlyUnretainedType())
+ return Qualifiers::OCL_ExplicitNone;
+ return Qualifiers::OCL_Strong;
+}
+
+bool Type::isObjCARCImplicitlyUnretainedType() const {
+ assert(isObjCLifetimeType() &&
+ "cannot query implicit lifetime for non-inferrable type");
+
+ const Type *canon = getCanonicalTypeInternal().getTypePtr();
+
+ // Walk down to the base type. We don't care about qualifiers for this.
+ while (const ArrayType *array = dyn_cast<ArrayType>(canon))
+ canon = array->getElementType().getTypePtr();
+
+ if (const ObjCObjectPointerType *opt
+ = dyn_cast<ObjCObjectPointerType>(canon)) {
+ // Class and Class<Protocol> don't require retension.
+ if (opt->getObjectType()->isObjCClass())
+ return true;
+ }
+
+ return false;
+}
+
+bool Type::isObjCNSObjectType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+ return false;
+}
+bool Type::isObjCRetainableType() const {
+ return isObjCObjectPointerType() ||
+ isBlockPointerType() ||
+ isObjCNSObjectType();
+}
+bool Type::isObjCIndirectLifetimeType() const {
+ if (isObjCLifetimeType())
+ return true;
+ if (const PointerType *OPT = getAs<PointerType>())
+ return OPT->getPointeeType()->isObjCIndirectLifetimeType();
+ if (const ReferenceType *Ref = getAs<ReferenceType>())
+ return Ref->getPointeeType()->isObjCIndirectLifetimeType();
+ if (const MemberPointerType *MemPtr = getAs<MemberPointerType>())
+ return MemPtr->getPointeeType()->isObjCIndirectLifetimeType();
+ return false;
+}
+
+/// Returns true if objects of this type have lifetime semantics under
+/// ARC.
+bool Type::isObjCLifetimeType() const {
+ const Type *type = this;
+ while (const ArrayType *array = type->getAsArrayTypeUnsafe())
+ type = array->getElementType().getTypePtr();
+ return type->isObjCRetainableType();
+}
+
+/// \brief Determine whether the given type T is a "bridgable" Objective-C type,
+/// which is either an Objective-C object pointer type or an
+bool Type::isObjCARCBridgableType() const {
+ return isObjCObjectPointerType() || isBlockPointerType();
+}
+
+/// \brief Determine whether the given type T is a "bridgeable" C type.
+bool Type::isCARCBridgableType() const {
+ const PointerType *Pointer = getAs<PointerType>();
+ if (!Pointer)
+ return false;
+
+ QualType Pointee = Pointer->getPointeeType();
+ return Pointee->isVoidType() || Pointee->isRecordType();
+}
+
bool Type::hasSizedVLAType() const {
if (!isVariablyModifiedType()) return false;
@@ -1919,6 +2211,18 @@ bool Type::hasSizedVLAType() const {
}
QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
+ switch (type.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ break;
+
+ case Qualifiers::OCL_Strong:
+ return DK_objc_strong_lifetime;
+ case Qualifiers::OCL_Weak:
+ return DK_objc_weak_lifetime;
+ }
+
/// Currently, the only destruction kind we recognize is C++ objects
/// with non-trivial destructors.
const CXXRecordDecl *record =
@@ -1928,3 +2232,24 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
return DK_none;
}
+
+bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ break;
+
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Autoreleasing:
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ return !Context.getLangOptions().ObjCAutoRefCount;
+ }
+
+ if (const CXXRecordDecl *Record
+ = getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
+ return Record->hasTrivialCopyAssignment();
+
+ return true;
+}