summaryrefslogtreecommitdiffstats
path: root/include/clang/AST
diff options
context:
space:
mode:
authorsvnmir <svnmir@FreeBSD.org>2015-08-07 23:02:56 +0000
committersvnmir <svnmir@FreeBSD.org>2015-08-07 23:02:56 +0000
commit6416b56f5a3923c6c264b46365e16718ccabf081 (patch)
treeca13cf9e2e8c2499f61f1246e455efd2804abd36 /include/clang/AST
parente7bcad327814a78ecb8d5f5545d2e3df84c67a5c (diff)
downloadFreeBSD-src-6416b56f5a3923c6c264b46365e16718ccabf081.zip
FreeBSD-src-6416b56f5a3923c6c264b46365e16718ccabf081.tar.gz
Vendor import of clang trunk r242221:
https://llvm.org/svn/llvm-project/cfe/trunk@242221
Diffstat (limited to 'include/clang/AST')
-rw-r--r--include/clang/AST/ASTContext.h30
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h33
-rw-r--r--include/clang/AST/DeclObjC.h292
-rw-r--r--include/clang/AST/ExprObjC.h38
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h32
-rw-r--r--include/clang/AST/Type.h296
-rw-r--r--include/clang/AST/TypeLoc.h118
7 files changed, 729 insertions, 110 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 682be3d..a2bd55a 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -236,6 +236,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
+ /// The identifier 'NSObject'.
+ IdentifierInfo *NSObjectName = nullptr;
+
+ /// The identifier 'NSCopying'.
+ IdentifierInfo *NSCopyingName = nullptr;
+
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
@@ -1189,9 +1195,15 @@ public:
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;
+ /// Legacy interface: cannot provide type arguments or __kindof.
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const;
+
+ QualType getObjCObjectType(QualType Base,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
@@ -1351,6 +1363,24 @@ public:
ObjCSelRedefinitionType = RedefType;
}
+ /// Retrieve the identifier 'NSObject'.
+ IdentifierInfo *getNSObjectName() {
+ if (!NSObjectName) {
+ NSObjectName = &Idents.get("NSObject");
+ }
+
+ return NSObjectName;
+ }
+
+ /// Retrieve the identifier 'NSCopying'.
+ IdentifierInfo *getNSCopyingName() {
+ if (!NSCopyingName) {
+ NSCopyingName = &Idents.get("NSCopying");
+ }
+
+ return NSCopyingName;
+ }
+
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 923d98f..dd167fe 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -940,6 +940,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ TRY_TO(TraverseType(typeArg));
+ }
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@@ -1166,6 +1169,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@@ -1307,7 +1312,13 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+ return true;
+})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@@ -1316,7 +1327,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+
+ if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
+ TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
+ }
+})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@@ -1335,6 +1355,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
+DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
+ if (D->hasExplicitBound()) {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ }
+})
+
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index c3fb577..c42764b 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -332,10 +332,14 @@ public:
SourceRange getReturnTypeSourceRange() const;
/// \brief Determine the type of an expression that sends a message to this
- /// function.
- QualType getSendResultType() const {
- return getReturnType().getNonLValueExprType(getASTContext());
- }
+ /// function. This replaces the type parameters with the types they would
+ /// get if the receiver was parameterless (e.g. it may replace the type
+ /// parameter with 'id').
+ QualType getSendResultType() const;
+
+ /// Determine the type of an expression that sends a message to this
+ /// function with the given receiver type.
+ QualType getSendResultType(QualType receiverType) const;
TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
@@ -399,6 +403,11 @@ public:
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
+ /// \return the type for \c self and set \arg selfIsPseudoStrong and
+ /// \arg selfIsConsumed accordingly.
+ QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
+ bool &selfIsPseudoStrong, bool &selfIsConsumed);
+
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
@@ -501,6 +510,183 @@ public:
friend class ASTDeclWriter;
};
+/// Describes the variance of a given generic parameter.
+enum class ObjCTypeParamVariance : uint8_t {
+ /// The parameter is invariant: must match exactly.
+ Invariant,
+ /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
+ /// the type parameter is covariant and T is a subtype of U.
+ Covariant,
+ /// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
+ /// when the type parameter is covariant and U is a subtype of T.
+ Contravariant,
+};
+
+/// Represents the declaration of an Objective-C type parameter.
+///
+/// \code
+/// @interface NSDictionary<Key : id<NSCopying>, Value>
+/// @end
+/// \endcode
+///
+/// In the example above, both \c Key and \c Value are represented by
+/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
+/// while \c Value gets an implicit bound of \c id.
+///
+/// Objective-C type parameters are typedef-names in the grammar,
+class ObjCTypeParamDecl : public TypedefNameDecl {
+ void anchor() override;
+
+ /// Index of this type parameter in the type parameter list.
+ unsigned Index : 14;
+
+ /// The variance of the type parameter.
+ unsigned Variance : 2;
+
+ /// The location of the variance, if any.
+ SourceLocation VarianceLoc;
+
+ /// The location of the ':', which will be valid when the bound was
+ /// explicitly specified.
+ SourceLocation ColonLoc;
+
+ ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance, SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc, IdentifierInfo *name,
+ SourceLocation colonLoc, TypeSourceInfo *boundInfo)
+ : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
+ boundInfo),
+ Index(index), Variance(static_cast<unsigned>(variance)),
+ VarianceLoc(varianceLoc), ColonLoc(colonLoc) { }
+
+public:
+ static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc,
+ IdentifierInfo *name,
+ SourceLocation colonLoc,
+ TypeSourceInfo *boundInfo);
+ static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Determine the variance of this type parameter.
+ ObjCTypeParamVariance getVariance() const {
+ return static_cast<ObjCTypeParamVariance>(Variance);
+ }
+
+ /// Set the variance of this type parameter.
+ void setVariance(ObjCTypeParamVariance variance) {
+ Variance = static_cast<unsigned>(variance);
+ }
+
+ /// Retrieve the location of the variance keyword.
+ SourceLocation getVarianceLoc() const { return VarianceLoc; }
+
+ /// Retrieve the index into its type parameter list.
+ unsigned getIndex() const { return Index; }
+
+ /// Whether this type parameter has an explicitly-written type bound, e.g.,
+ /// "T : NSView".
+ bool hasExplicitBound() const { return ColonLoc.isValid(); }
+
+ /// Retrieve the location of the ':' separating the type parameter name
+ /// from the explicitly-specified bound.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCTypeParam; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Stores a list of Objective-C type parameters for a parameterized class
+/// or a category/extension thereof.
+///
+/// \code
+/// @interface NSArray<T> // stores the <T>
+/// @end
+/// \endcode
+class ObjCTypeParamList {
+ /// Stores the components of a SourceRange as a POD.
+ struct PODSourceRange {
+ unsigned Begin;
+ unsigned End;
+ };
+
+ union {
+ /// Location of the left and right angle brackets.
+ PODSourceRange Brackets;
+
+ // Used only for alignment.
+ ObjCTypeParamDecl *AlignmentHack;
+ };
+
+ /// The number of parameters in the list, which are tail-allocated.
+ unsigned NumParams;
+
+ ObjCTypeParamList(SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+public:
+ /// Create a new Objective-C type parameter list.
+ static ObjCTypeParamList *create(ASTContext &ctx,
+ SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+ /// Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl **iterator;
+
+ iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
+
+ iterator end() { return begin() + size(); }
+
+ /// Determine the number of type parameters in this list.
+ unsigned size() const { return NumParams; }
+
+ // Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl * const *const_iterator;
+
+ const_iterator begin() const {
+ return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
+ }
+
+ const_iterator end() const {
+ return begin() + size();
+ }
+
+ ObjCTypeParamDecl *front() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *begin();
+ }
+
+ ObjCTypeParamDecl *back() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *(end() - 1);
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.Begin);
+ }
+ SourceLocation getRAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.End);
+ }
+ SourceRange getSourceRange() const {
+ return SourceRange(getLAngleLoc(), getRAngleLoc());
+ }
+
+ /// Gather the default set of type arguments to be substituted for
+ /// these type parameters when dealing with an unspecialized type.
+ void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
+};
+
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
@@ -676,9 +862,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// declaration.
ObjCInterfaceDecl *Definition;
- /// Class's super class.
- ObjCInterfaceDecl *SuperClass;
-
+ /// When non-null, this is always an ObjCObjectType.
+ TypeSourceInfo *SuperClassTInfo;
+
/// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
@@ -719,16 +905,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
-
- /// \brief The location of the superclass, if any.
- SourceLocation SuperClassLoc;
/// \brief The location of the last location in this declaration, before
/// the properties/methods. For example, this will be the '>', '}', or
/// identifier,
SourceLocation EndLoc;
- DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
+ DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(),
ExternallyCompleted(),
IvarListMissingImplementation(true),
HasDesignatedInitializers(),
@@ -736,11 +919,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
- IdentifierInfo *Id, SourceLocation CLoc,
- ObjCInterfaceDecl *PrevDecl, bool IsInternal);
+ IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool IsInternal);
void LoadExternalDefinition() const;
+ /// The type parameters associated with this class, if any.
+ ObjCTypeParamList *TypeParamList;
+
/// \brief Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
///
@@ -771,12 +958,33 @@ public:
static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
+ ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(),
bool isInternal = false);
static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
+ /// Retrieve the type parameters of this class.
+ ///
+ /// This function looks for a type parameter list for the given
+ /// class; if the class has been declared (with \c \@class) but not
+ /// defined (with \c \@interface), it will search for a declaration that
+ /// has type parameters, skipping any declarations that do not.
+ ObjCTypeParamList *getTypeParamList() const;
+
+ /// Set the type parameters of this class.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+ /// Retrieve the type parameters written on this particular declaration of
+ /// the class.
+ ObjCTypeParamList *getTypeParamListAsWritten() const {
+ return TypeParamList;
+ }
+
SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
@@ -1023,7 +1231,16 @@ public:
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
- ObjCInterfaceDecl *getSuperClass() const {
+ /// Retrieve the superclass type.
+ const ObjCObjectType *getSuperClassType() const {
+ if (TypeSourceInfo *TInfo = getSuperClassTInfo())
+ return TInfo->getType()->castAs<ObjCObjectType>();
+
+ return nullptr;
+ }
+
+ // Retrieve the type source information for the superclass.
+ TypeSourceInfo *getSuperClassTInfo() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
@@ -1031,13 +1248,15 @@ public:
if (data().ExternallyCompleted)
LoadExternalDefinition();
- return data().SuperClass;
+ return data().SuperClassTInfo;
}
- void setSuperClass(ObjCInterfaceDecl * superCls) {
- data().SuperClass =
- (superCls && superCls->hasDefinition()) ? superCls->getDefinition()
- : superCls;
+ // Retrieve the declaration for the superclass of this class, which
+ // does not include any type arguments that apply to the superclass.
+ ObjCInterfaceDecl *getSuperClass() const;
+
+ void setSuperClass(TypeSourceInfo *superClass) {
+ data().SuperClassTInfo = superClass;
}
/// \brief Iterator that walks over the list of categories, filtering out
@@ -1329,8 +1548,8 @@ public:
void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
- void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
- SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
+ /// Retrieve the starting location of the superclass.
+ SourceLocation getSuperClassLoc() const;
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
@@ -1438,6 +1657,10 @@ public:
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
+ /// Retrieve the type of this instance variable when viewed as a member of a
+ /// specific object type.
+ QualType getUsageType(QualType objectType) const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCIvar; }
@@ -1719,6 +1942,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
+ /// The type parameters associated with this category, if any.
+ ObjCTypeParamList *TypeParamList;
+
/// referenced protocols in this category.
ObjCProtocolList ReferencedProtocols;
@@ -1736,13 +1962,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
- SourceLocation IvarRBraceLoc=SourceLocation())
- : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
- ClassInterface(IDecl), NextClassCategory(nullptr),
- CategoryNameLoc(CategoryNameLoc),
- IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
- }
+ SourceLocation IvarRBraceLoc=SourceLocation());
public:
@@ -1752,6 +1974,7 @@ public:
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation());
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -1759,6 +1982,17 @@ public:
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ /// Retrieve the type parameter list associated with this category or
+ /// extension.
+ ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }
+
+ /// Set the type parameters of this category.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+
ObjCCategoryImplDecl *getImplementation() const;
void setImplementation(ObjCCategoryImplDecl *ImplD);
@@ -2275,6 +2509,10 @@ public:
DeclTypeSourceInfo = TSI;
}
+ /// Retrieve the type when this property is used with a specific base object
+ /// type.
+ QualType getUsageType(QualType objectType) const;
+
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 899e648..f28e519 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -687,40 +687,7 @@ public:
QualType getSuperReceiverType() const {
return QualType(Receiver.get<const Type*>(), 0);
}
- QualType getGetterResultType() const {
- QualType ResultType;
- if (isExplicitProperty()) {
- const ObjCPropertyDecl *PDecl = getExplicitProperty();
- if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
- ResultType = Getter->getReturnType();
- else
- ResultType = PDecl->getType();
- } else {
- const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
- if (Getter)
- ResultType = Getter->getReturnType(); // with reference!
- }
- return ResultType;
- }
-
- QualType getSetterArgType() const {
- QualType ArgType;
- if (isImplicitProperty()) {
- const ObjCMethodDecl *Setter = getImplicitPropertySetter();
- ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
- ArgType = (*P)->getType();
- } else {
- if (ObjCPropertyDecl *PDecl = getExplicitProperty())
- if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
- ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
- ArgType = (*P)->getType();
- }
- if (ArgType.isNull())
- ArgType = getType();
- }
- return ArgType;
- }
-
+
ObjCInterfaceDecl *getClassReceiver() const {
return Receiver.get<ObjCInterfaceDecl*>();
}
@@ -728,6 +695,9 @@ public:
bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
+ /// Determine the type of the base, regardless of the kind of receiver.
+ QualType getReceiverType(const ASTContext &ctx) const;
+
SourceLocation getLocStart() const LLVM_READONLY {
return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
}
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index b118503..1017656 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1008,6 +1008,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ TRY_TO(TraverseType(typeArg));
+ }
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@@ -1234,6 +1237,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@@ -1382,7 +1387,12 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@@ -1391,7 +1401,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+
+ if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
+ TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
+ }
+})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@@ -1410,6 +1429,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
+DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
+ if (D->hasExplicitBound()) {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ }
+})
+
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 97f1331..632d4b9 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -533,6 +533,24 @@ struct SplitQualType {
}
};
+/// The kind of type we are substituting Objective-C type arguments into.
+///
+/// The kind of substitution affects the replacement of type parameters when
+/// no concrete type information is provided, e.g., when dealing with an
+/// unspecialized type.
+enum class ObjCSubstitutionContext {
+ /// An ordinary type.
+ Ordinary,
+ /// The result type of a method or function.
+ Result,
+ /// The parameter type of a method or function.
+ Parameter,
+ /// The type of a property.
+ Property,
+ /// The superclass of a type.
+ Superclass,
+};
+
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
/// greatly reduces the number of nodes we need to allocate for types (for
@@ -994,6 +1012,51 @@ public:
/// type other than void.
bool isCForbiddenLValueType() const;
+ /// Substitute type arguments for the Objective-C type parameters used in the
+ /// subject type.
+ ///
+ /// \param ctx ASTContext in which the type exists.
+ ///
+ /// \param typeArgs The type arguments that will be substituted for the
+ /// Objective-C type parameters in the subject type, which are generally
+ /// computed via \c Type::getObjCSubstitutions. If empty, the type
+ /// parameters will be replaced with their bounds or id/Class, as appropriate
+ /// for the context.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the resulting type.
+ QualType substObjCTypeArgs(ASTContext &ctx,
+ ArrayRef<QualType> typeArgs,
+ ObjCSubstitutionContext context) const;
+
+ /// Substitute type arguments from an object type for the Objective-C type
+ /// parameters used in the subject type.
+ ///
+ /// This operation combines the computation of type arguments for
+ /// substitution (\c Type::getObjCSubstitutions) with the actual process of
+ /// substitution (\c QualType::substObjCTypeArgs) for the convenience of
+ /// callers that need to perform a single substitution in isolation.
+ ///
+ /// \param objectType The type of the object whose member type we're
+ /// substituting into. For example, this might be the receiver of a message
+ /// or the base of a property access.
+ ///
+ /// \param dc The declaration context from which the subject type was
+ /// retrieved, which indicates (for example) which type parameters should
+ /// be substituted.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the subject type after replacing all of the Objective-C type
+ /// parameters with their corresponding arguments.
+ QualType substObjCMemberType(QualType objectType,
+ const DeclContext *dc,
+ ObjCSubstitutionContext context) const;
+
+ /// Strip Objective-C "__kindof" types from the given type.
+ QualType stripObjCKindOfType(const ASTContext &ctx) const;
+
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
@@ -1288,10 +1351,17 @@ protected:
unsigned : NumTypeBits;
+ /// The number of type arguments stored directly on this object type.
+ unsigned NumTypeArgs : 7;
+
/// NumProtocols - The number of protocols stored directly on this
/// object type.
- unsigned NumProtocols : 32 - NumTypeBits;
+ unsigned NumProtocols : 6;
+
+ /// Whether this is a "kindof" type.
+ unsigned IsKindOf : 1;
};
+ static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
class ReferenceTypeBitfields {
friend class ReferenceType;
@@ -1585,7 +1655,28 @@ public:
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
+
+ /// Whether the type is Objective-C 'id' or a __kindof type of an
+ /// object type, e.g., __kindof NSView * or __kindof id
+ /// <NSCopying>.
+ ///
+ /// \param bound Will be set to the bound on non-id subtype types,
+ /// which will be (possibly specialized) Objective-C class type, or
+ /// null for 'id.
+ bool isObjCIdOrObjectKindOfType(const ASTContext &ctx,
+ const ObjCObjectType *&bound) const;
+
bool isObjCClassType() const; // Class
+
+ /// Whether the type is Objective-C 'Class' or a __kindof type of an
+ /// Class type, e.g., __kindof Class <NSCopying>.
+ ///
+ /// Unlike \c isObjCIdOrObjectKindOfType, there is no relevant bound
+ /// here because Objective-C's type system cannot express "a class
+ /// object for a subclass of NSFoo".
+ bool isObjCClassOrClassKindOfType() const;
+
+ bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const;
bool isObjCSelType() const; // Class
bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isObjCARCBridgableType() const;
@@ -1697,6 +1788,7 @@ public:
/// NOTE: getAs*ArrayType are methods on ASTContext.
const RecordType *getAsUnionType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
+ const ObjCObjectType *getAsObjCInterfaceType() const;
// The following is a convenience method that returns an ObjCObjectPointerType
// for object declared using an interface.
const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
@@ -1832,6 +1924,28 @@ public:
/// pointer type.
bool canHaveNullability() const;
+ /// Retrieve the set of substitutions required when accessing a member
+ /// of the Objective-C receiver type that is declared in the given context.
+ ///
+ /// \c *this is the type of the object we're operating on, e.g., the
+ /// receiver for a message send or the base of a property access, and is
+ /// expected to be of some object or object pointer type.
+ ///
+ /// \param dc The declaration context for which we are building up a
+ /// substitution mapping, which should be an Objective-C class, extension,
+ /// category, or method within.
+ ///
+ /// \returns an array of type arguments that can be substituted for
+ /// the type parameters of the given declaration context in any type described
+ /// within that context, or an empty optional to indicate that no
+ /// substitution is required.
+ Optional<ArrayRef<QualType>>
+ getObjCSubstitutions(const DeclContext *dc) const;
+
+ /// Determines if this is an ObjC interface type that may accept type
+ /// parameters.
+ bool acceptsObjCTypeParams() const;
+
const char *getTypeClassName() const;
QualType getCanonicalTypeInternal() const {
@@ -3497,6 +3611,7 @@ public:
attr_nonnull,
attr_nullable,
attr_null_unspecified,
+ attr_objc_kindof,
};
private:
@@ -4369,19 +4484,25 @@ public:
};
/// ObjCObjectType - Represents a class type in Objective C.
-/// Every Objective C type is a combination of a base type and a
-/// list of protocols.
+///
+/// Every Objective C type is a combination of a base type, a set of
+/// type arguments (optional, for parameterized classes) and a list of
+/// protocols.
///
/// Given the following declarations:
/// \code
-/// \@class C;
+/// \@class C<T>;
/// \@protocol P;
/// \endcode
///
/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
/// with base C and no protocols.
///
-/// 'C<P>' is an ObjCObjectType with base C and protocol list [P].
+/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P].
+/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
+/// protocol list.
+/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*',
+/// and protocol list [P].
///
/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose
/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
@@ -4391,8 +4512,10 @@ public:
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
- // ObjCObjectType.NumProtocols - the number of protocols stored
+ // ObjCObjectType.NumTypeArgs - the number of type arguments stored
// after the ObjCObjectPointerType node.
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the type arguments of ObjCObjectPointerType node.
//
// These protocols are those written directly on the type. If
// protocol qualifiers ever become additive, the iterators will need
@@ -4404,23 +4527,38 @@ class ObjCObjectType : public Type {
/// Either a BuiltinType or an InterfaceType or sugar for either.
QualType BaseType;
+ /// Cached superclass type.
+ mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool>
+ CachedSuperClassType;
+
ObjCProtocolDecl * const *getProtocolStorage() const {
return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
}
+ QualType *getTypeArgStorage();
+ const QualType *getTypeArgStorage() const {
+ return const_cast<ObjCObjectType *>(this)->getTypeArgStorage();
+ }
+
ObjCProtocolDecl **getProtocolStorage();
protected:
ObjCObjectType(QualType Canonical, QualType Base,
- ObjCProtocolDecl * const *Protocols, unsigned NumProtocols);
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
: Type(ObjCInterface, QualType(), false, false, false, false),
BaseType(QualType(this_(), 0)) {
ObjCObjectTypeBits.NumProtocols = 0;
+ ObjCObjectTypeBits.NumTypeArgs = 0;
+ ObjCObjectTypeBits.IsKindOf = 0;
}
+ void computeSuperClassTypeSlow() const;
+
public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
@@ -4452,6 +4590,33 @@ public:
/// really is an interface.
ObjCInterfaceDecl *getInterface() const;
+ /// Determine whether this object type is "specialized", meaning
+ /// that it has type arguments.
+ bool isSpecialized() const;
+
+ /// Determine whether this object type was written with type arguments.
+ bool isSpecializedAsWritten() const {
+ return ObjCObjectTypeBits.NumTypeArgs > 0;
+ }
+
+ /// Determine whether this object type is "unspecialized", meaning
+ /// that it has no type arguments.
+ bool isUnspecialized() const { return !isSpecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments of this object type (semantically).
+ ArrayRef<QualType> getTypeArgs() const;
+
+ /// Retrieve the type arguments of this object type as they were
+ /// written.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return ArrayRef<QualType>(getTypeArgStorage(),
+ ObjCObjectTypeBits.NumTypeArgs);
+ }
+
typedef ObjCProtocolDecl * const *qual_iterator;
typedef llvm::iterator_range<qual_iterator> qual_range;
@@ -4471,6 +4636,35 @@ public:
return qual_begin()[I];
}
+ /// Retrieve all of the protocol qualifiers.
+ ArrayRef<ObjCProtocolDecl *> getProtocols() const {
+ return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
+ }
+
+ /// Whether this is a "__kindof" type as written.
+ bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }
+
+ /// Whether this ia a "__kindof" type (semantically).
+ bool isKindOfType() const;
+
+ /// Retrieve the type of the superclass of this object type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// specialization of the superclass type. Produces a null type if
+ /// there is no superclass.
+ QualType getSuperClassType() const {
+ if (!CachedSuperClassType.getInt())
+ computeSuperClassTypeSlow();
+
+ assert(CachedSuperClassType.getInt() && "Superclass not set?");
+ return QualType(CachedSuperClassType.getPointer(), 0);
+ }
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const;
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -4491,21 +4685,27 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
// will need to be modified.
ObjCObjectTypeImpl(QualType Canonical, QualType Base,
- ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols)
- : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf)
+ : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
- ObjCProtocolDecl *const *protocols,
- unsigned NumProtocols);
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
};
+inline QualType *ObjCObjectType::getTypeArgStorage() {
+ return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1);
+}
+
inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
- return reinterpret_cast<ObjCProtocolDecl**>(
- static_cast<ObjCObjectTypeImpl*>(this) + 1);
+ return reinterpret_cast<ObjCProtocolDecl**>(
+ getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
@@ -4556,9 +4756,14 @@ public:
};
inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
- if (const ObjCInterfaceType *T =
- getBaseType()->getAs<ObjCInterfaceType>())
- return T->getDecl();
+ QualType baseType = getBaseType();
+ while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
+ if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
+ return T->getDecl();
+
+ baseType = ObjT->getBaseType();
+ }
+
return nullptr;
}
@@ -4575,7 +4780,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical, false, false, false, false),
+ : Type(ObjCObjectPointer, Canonical,
+ Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
@@ -4617,9 +4826,7 @@ public:
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
- const ObjCInterfaceType *getInterfaceType() const {
- return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>();
- }
+ const ObjCInterfaceType *getInterfaceType() const;
/// getInterfaceDecl - If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
@@ -4641,6 +4848,12 @@ public:
return getObjectType()->isObjCUnqualifiedClass();
}
+ /// isObjCIdOrClassType - True if this is equivalent to the 'id' or
+ /// 'Class' type,
+ bool isObjCIdOrClassType() const {
+ return getObjectType()->isObjCUnqualifiedIdOrClass();
+ }
+
/// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
/// non-empty set of protocols.
bool isObjCQualifiedIdType() const {
@@ -4653,6 +4866,34 @@ public:
return getObjectType()->isObjCQualifiedClass();
}
+ /// Whether this is a "__kindof" type.
+ bool isKindOfType() const { return getObjectType()->isKindOfType(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecialized() const { return getObjectType()->isSpecialized(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecializedAsWritten() const {
+ return getObjectType()->isSpecializedAsWritten();
+ }
+
+ /// Whether this type is unspecialized, meaning that is has no type arguments.
+ bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgs() const {
+ return getObjectType()->getTypeArgs();
+ }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return getObjectType()->getTypeArgsAsWritten();
+ }
+
/// An iterator over the qualifiers on the object type. Provided
/// for convenience. This will always iterate over the full set of
/// protocols on a type, not just those provided directly.
@@ -4683,6 +4924,19 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+ /// Retrieve the type of the superclass of this object pointer type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// pointer to a specialization of the superclass type. Produces a
+ /// null type if there is no superclass.
+ QualType getSuperClassType() const;
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ const ObjCObjectPointerType *stripObjCKindOfTypeAndQuals(
+ const ASTContext &ctx) const;
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index e29fa49..f4d20b8 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -177,6 +177,9 @@ public:
memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
}
+ /// Copies the other type loc into this one.
+ void copy(TypeLoc other);
+
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
}
@@ -185,6 +188,10 @@ public:
return !(LHS == RHS);
}
+ /// Find the location of the nullability specifier (__nonnull,
+ /// __nullable, or __null_unspecifier), if there is one.
+ SourceLocation findNullabilityLoc() const;
+
private:
static bool isKind(const TypeLoc&) {
return true;
@@ -249,6 +256,10 @@ public:
// do nothing
}
+ void copyLocal(TypeLoc other) {
+ // do nothing
+ }
+
TypeLoc getNextTypeLoc() const {
return getUnqualifiedLoc();
}
@@ -339,6 +350,20 @@ public:
return size;
}
+ void copyLocal(Derived other) {
+ // Some subclasses have no data to copy.
+ if (asDerived()->getLocalDataSize() == 0) return;
+
+ // Copy the fixed-sized local data.
+ memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData));
+
+ // Copy the variable-sized local data. We need to do this
+ // separately because the padding in the source and the padding in
+ // the destination might be different.
+ memcpy(getExtraLocalData(), other.getExtraLocalData(),
+ asDerived()->getExtraLocalDataSize());
+ }
+
TypeLoc getNextTypeLoc() const {
return getNextTypeLoc(asDerived()->getInnerType());
}
@@ -799,9 +824,11 @@ public:
};
-struct ObjCProtocolListLocInfo {
- SourceLocation LAngleLoc;
- SourceLocation RAngleLoc;
+struct ObjCObjectTypeLocInfo {
+ SourceLocation TypeArgsLAngleLoc;
+ SourceLocation TypeArgsRAngleLoc;
+ SourceLocation ProtocolLAngleLoc;
+ SourceLocation ProtocolRAngleLoc;
bool HasBaseTypeAsWritten;
};
@@ -813,25 +840,59 @@ struct ObjCProtocolListLocInfo {
class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ObjCObjectTypeLoc,
ObjCObjectType,
- ObjCProtocolListLocInfo> {
- // SourceLocations are stored after Info, one for each Protocol.
+ ObjCObjectTypeLocInfo> {
+ // TypeSourceInfo*'s are stored after Info, one for each type argument.
+ TypeSourceInfo **getTypeArgLocArray() const {
+ return (TypeSourceInfo**)this->getExtraLocalData();
+ }
+
+ // SourceLocations are stored after the type argument information, one for
+ // each Protocol.
SourceLocation *getProtocolLocArray() const {
- return (SourceLocation*) this->getExtraLocalData();
+ return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs());
}
public:
- SourceLocation getLAngleLoc() const {
- return this->getLocalData()->LAngleLoc;
+ SourceLocation getTypeArgsLAngleLoc() const {
+ return this->getLocalData()->TypeArgsLAngleLoc;
}
- void setLAngleLoc(SourceLocation Loc) {
- this->getLocalData()->LAngleLoc = Loc;
+ void setTypeArgsLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsLAngleLoc = Loc;
}
- SourceLocation getRAngleLoc() const {
- return this->getLocalData()->RAngleLoc;
+ SourceLocation getTypeArgsRAngleLoc() const {
+ return this->getLocalData()->TypeArgsRAngleLoc;
}
- void setRAngleLoc(SourceLocation Loc) {
- this->getLocalData()->RAngleLoc = Loc;
+ void setTypeArgsRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsRAngleLoc = Loc;
+ }
+
+ unsigned getNumTypeArgs() const {
+ return this->getTypePtr()->getTypeArgsAsWritten().size();
+ }
+
+ TypeSourceInfo *getTypeArgTInfo(unsigned i) const {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ return getTypeArgLocArray()[i];
+ }
+
+ void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ getTypeArgLocArray()[i] = TInfo;
+ }
+
+ SourceLocation getProtocolLAngleLoc() const {
+ return this->getLocalData()->ProtocolLAngleLoc;
+ }
+ void setProtocolLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolLAngleLoc = Loc;
+ }
+
+ SourceLocation getProtocolRAngleLoc() const {
+ return this->getLocalData()->ProtocolRAngleLoc;
+ }
+ void setProtocolRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolRAngleLoc = Loc;
}
unsigned getNumProtocols() const {
@@ -852,6 +913,11 @@ public:
return *(this->getTypePtr()->qual_begin() + i);
}
+
+ ArrayRef<SourceLocation> getProtocolLocs() const {
+ return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
+ }
+
bool hasBaseTypeAsWritten() const {
return getLocalData()->HasBaseTypeAsWritten;
}
@@ -865,23 +931,27 @@ public:
}
SourceRange getLocalSourceRange() const {
- return SourceRange(getLAngleLoc(), getRAngleLoc());
+ SourceLocation start = getTypeArgsLAngleLoc();
+ if (start.isInvalid())
+ start = getProtocolLAngleLoc();
+ SourceLocation end = getProtocolRAngleLoc();
+ if (end.isInvalid())
+ end = getTypeArgsRAngleLoc();
+ return SourceRange(start, end);
}
- void initializeLocal(ASTContext &Context, SourceLocation Loc) {
- setHasBaseTypeAsWritten(true);
- setLAngleLoc(Loc);
- setRAngleLoc(Loc);
- for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
- setProtocolLoc(i, Loc);
- }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
unsigned getExtraLocalDataSize() const {
- return this->getNumProtocols() * sizeof(SourceLocation);
+ return this->getNumTypeArgs() * sizeof(TypeSourceInfo *)
+ + this->getNumProtocols() * sizeof(SourceLocation);
}
unsigned getExtraLocalDataAlignment() const {
- return llvm::alignOf<SourceLocation>();
+ assert(llvm::alignOf<ObjCObjectTypeLoc>()
+ >= llvm::alignOf<TypeSourceInfo *>() &&
+ "not enough alignment for tail-allocated data");
+ return llvm::alignOf<TypeSourceInfo *>();
}
QualType getInnerType() const {
OpenPOWER on IntegriCloud