diff options
author | svnmir <svnmir@FreeBSD.org> | 2015-08-07 23:02:56 +0000 |
---|---|---|
committer | svnmir <svnmir@FreeBSD.org> | 2015-08-07 23:02:56 +0000 |
commit | 6416b56f5a3923c6c264b46365e16718ccabf081 (patch) | |
tree | ca13cf9e2e8c2499f61f1246e455efd2804abd36 /include/clang/AST | |
parent | e7bcad327814a78ecb8d5f5545d2e3df84c67a5c (diff) | |
download | FreeBSD-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.h | 30 | ||||
-rw-r--r-- | include/clang/AST/DataRecursiveASTVisitor.h | 33 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 292 | ||||
-rw-r--r-- | include/clang/AST/ExprObjC.h | 38 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 32 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 296 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 118 |
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 { |