r241542 - Handle Objective-C type arguments.
Justin Bogner
mail at justinbogner.com
Wed Jul 8 11:32:53 PDT 2015
Douglas Gregor <dgregor at apple.com> writes:
> Author: dgregor
> Date: Mon Jul 6 22:57:35 2015
> New Revision: 241542
>
> URL: http://llvm.org/viewvc/llvm-project?rev=241542&view=rev
> Log:
> Handle Objective-C type arguments.
>
> Objective-C type arguments can be provided in angle brackets following
> an Objective-C interface type. Syntactically, this is the same
> position as one would provide protocol qualifiers (e.g.,
> id<NSCopying>), so parse both together and let Sema sort out the
> ambiguous cases. This applies both when parsing types and when parsing
> the superclass of an Objective-C class, which can now be a specialized
> type (e.g., NSMutableArray<T> inherits from NSArray<T>).
>
> Check Objective-C type arguments against the type parameters of the
> corresponding class. Verify the length of the type argument list and
> that each type argument satisfies the corresponding bound.
>
> Specializations of parameterized Objective-C classes are represented
> in the type system as distinct types. Both specialized types (e.g.,
> NSArray<NSString *> *) and unspecialized types (NSArray *) are
> represented, separately.
>
> Added:
> cfe/trunk/test/Index/annotate-parameterized-classes.m
> cfe/trunk/test/SemaObjCXX/parameterized_classes.mm
> Modified:
> cfe/trunk/include/clang/AST/ASTContext.h
> cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
> cfe/trunk/include/clang/AST/DeclObjC.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/AST/Type.h
> cfe/trunk/include/clang/AST/TypeLoc.h
> cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Parse/Parser.h
> cfe/trunk/include/clang/Sema/DeclSpec.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/ASTDiagnostic.cpp
> cfe/trunk/lib/AST/ASTImporter.cpp
> cfe/trunk/lib/AST/DeclObjC.cpp
> cfe/trunk/lib/AST/Type.cpp
> cfe/trunk/lib/AST/TypeLoc.cpp
> cfe/trunk/lib/AST/TypePrinter.cpp
> cfe/trunk/lib/Parse/ParseDecl.cpp
> cfe/trunk/lib/Parse/ParseObjc.cpp
> cfe/trunk/lib/Parse/ParseTentative.cpp
> cfe/trunk/lib/Sema/DeclSpec.cpp
> cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprObjC.cpp
> cfe/trunk/lib/Sema/SemaType.cpp
> cfe/trunk/lib/Serialization/ASTReader.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> cfe/trunk/test/Index/complete-method-decls.m
> cfe/trunk/test/PCH/objc_parameterized_classes.m
> cfe/trunk/test/Parser/objcxx11-protocol-in-template.mm
> cfe/trunk/test/SemaObjC/interface-1.m
> cfe/trunk/test/SemaObjC/parameterized_classes.m
> cfe/trunk/tools/libclang/CIndex.cpp
> cfe/trunk/tools/libclang/CursorVisitor.h
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Jul 6 22:57:35 2015
> @@ -236,6 +236,12 @@ class ASTContext : public RefCountedBase
> QualType ObjCClassRedefinitionType;
> QualType ObjCSelRedefinitionType;
>
> + /// The identifier 'NSObject'.
> + IdentifierInfo *NSObjectName = nullptr;
> +
> + /// The identifier 'NSCopying'.
> + IdentifierInfo *NSCopyingName = nullptr;
> +
> QualType ObjCConstantStringType;
> mutable RecordDecl *CFConstantStringTypeDecl;
>
> @@ -1189,9 +1195,14 @@ public:
> QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
> ObjCInterfaceDecl *PrevDecl = nullptr) const;
>
> + /// Legacy interface: cannot provide type arguments.
> QualType getObjCObjectType(QualType Base,
> ObjCProtocolDecl * const *Protocols,
> unsigned NumProtocols) const;
> +
> + QualType getObjCObjectType(QualType Base,
> + ArrayRef<QualType> typeArgs,
> + ArrayRef<ObjCProtocolDecl *> protocols) const;
>
> bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
> /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
> @@ -1351,6 +1362,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() {
>
> Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Mon Jul 6 22:57:35 2015
> @@ -940,6 +940,8 @@ 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 +1168,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,
> @@ -1325,7 +1329,10 @@ DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {//
> for (auto typeParam : *typeParamList)
> TRY_TO(TraverseObjCTypeParamDecl(typeParam));
> }
> - return true;
> +
> + if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
> + TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
> + }
> })
>
> DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
>
> Modified: cfe/trunk/include/clang/AST/DeclObjC.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclObjC.h (original)
> +++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Jul 6 22:57:35 2015
> @@ -794,9 +794,9 @@ class ObjCInterfaceDecl : public ObjCCon
> /// 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;
>
> @@ -837,16 +837,13 @@ class ObjCInterfaceDecl : public ObjCCon
> };
> /// 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(),
> @@ -903,8 +900,8 @@ public:
> /// 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 @class) but not
> - /// defined (with @interface), it will search for a declaration that
> + /// 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;
>
> @@ -1160,7 +1157,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;
> @@ -1168,13 +1174,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
> @@ -1466,8 +1474,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
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Jul 6 22:57:35 2015
> @@ -1008,6 +1008,8 @@ 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 +1236,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,
> @@ -1399,6 +1403,10 @@ DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {//
> for (auto typeParam : *typeParamList)
> TRY_TO(TraverseObjCTypeParamDecl(typeParam));
> }
> +
> + if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
> + TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
> + }
> })
>
> DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Mon Jul 6 22:57:35 2015
> @@ -1288,10 +1288,14 @@ 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 : 7;
> };
> + static_assert(NumTypeBits + 7 + 7 <= 32, "Does not fit in an unsigned");
>
> class ReferenceTypeBitfields {
> friend class ReferenceType;
> @@ -1586,6 +1590,7 @@ public:
> bool isObjCObjectOrInterfaceType() const;
> bool isObjCIdType() const; // id
> bool isObjCClassType() const; // Class
> + bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const;
> bool isObjCSelType() const; // Class
> bool isObjCBuiltinType() const; // 'id' or 'Class'
> bool isObjCARCBridgableType() const;
> @@ -4369,19 +4374,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 +4402,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
> @@ -4408,17 +4421,24 @@ class ObjCObjectType : public Type {
> 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);
>
> 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;
> }
>
> public:
> @@ -4452,6 +4472,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;
>
> @@ -4491,21 +4538,25 @@ class ObjCObjectTypeImpl : public ObjCOb
> // 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)
> + : ObjCObjectType(Canonical, Base, typeArgs, protocols) {}
>
> 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);
> };
>
> +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 +4607,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;
> }
>
> @@ -4653,6 +4709,31 @@ public:
> return getObjectType()->isObjCQualifiedClass();
> }
>
> + /// 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.
>
> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
> +++ cfe/trunk/include/clang/AST/TypeLoc.h Mon Jul 6 22:57:35 2015
> @@ -799,9 +799,11 @@ public:
> };
>
>
> -struct ObjCProtocolListLocInfo {
> - SourceLocation LAngleLoc;
> - SourceLocation RAngleLoc;
> +struct ObjCObjectTypeLocInfo {
> + SourceLocation TypeArgsLAngleLoc;
> + SourceLocation TypeArgsRAngleLoc;
> + SourceLocation ProtocolLAngleLoc;
> + SourceLocation ProtocolRAngleLoc;
> bool HasBaseTypeAsWritten;
> };
>
> @@ -813,25 +815,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 setTypeArgsLAngleLoc(SourceLocation Loc) {
> + this->getLocalData()->TypeArgsLAngleLoc = Loc;
> + }
> +
> + SourceLocation getTypeArgsRAngleLoc() const {
> + return this->getLocalData()->TypeArgsRAngleLoc;
> + }
> + void setTypeArgsRAngleLoc(SourceLocation Loc) {
> + this->getLocalData()->TypeArgsRAngleLoc = Loc;
> }
> - void setLAngleLoc(SourceLocation Loc) {
> - this->getLocalData()->LAngleLoc = Loc;
> +
> + unsigned getNumTypeArgs() const {
> + return this->getTypePtr()->getTypeArgsAsWritten().size();
> }
>
> - SourceLocation getRAngleLoc() const {
> - return this->getLocalData()->RAngleLoc;
> + TypeSourceInfo *getTypeArgTInfo(unsigned i) const {
> + assert(i < getNumTypeArgs() && "Index is out of bounds!");
> + return getTypeArgLocArray()[i];
> }
> - void setRAngleLoc(SourceLocation Loc) {
> - this->getLocalData()->RAngleLoc = Loc;
> +
> + 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 {
> @@ -865,23 +901,26 @@ 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>();
> + static_assert(alignof(ObjCObjectTypeLoc) >= alignof(TypeSourceInfo *),
> + "not enough alignment for tail-allocated data");
> + return llvm::alignOf<TypeSourceInfo *>();
> }
>
> QualType getInnerType() const {
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Jul 6 22:57:35 2015
> @@ -1022,12 +1022,11 @@ let CategoryName = "Generics Issue" in {
> def err_objc_expected_type_parameter : Error<
> "expected type parameter name">;
>
> -def err_objc_parameterized_class_without_base : Error<
> - "parameterized Objective-C class %0 must have a superclass">;
> -
> def err_objc_parameterized_implementation : Error<
> "@implementation cannot have type parameters">;
>
> +def err_objc_type_args_after_protocols : Error<
> + "protocol qualifiers must precede type arguments">;
> }
>
> } // end of Parser diagnostics
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jul 6 22:57:35 2015
> @@ -7780,6 +7780,36 @@ def err_objc_parameterized_forward_class
> def err_objc_parameterized_forward_class_first : Error<
> "class %0 previously declared with type parameters">;
>
> +def err_objc_type_arg_missing_star : Error<
> + "type argument %0 must be a pointer (requires a '*')">;
> +
> +def err_objc_type_arg_missing : Error<
> + "no type or protocol named %0">;
> +
> +def err_objc_protocol_suggest : Error<
> + "no protocol named %0: did you mean %1?">;
> +
> +def err_objc_type_args_and_protocols : Error<
> + "angle brackets contain both a %select{type|protocol}0 (%1) and a "
> + "%select{protocol|type}0 (%2)">;
> +
> +def err_objc_type_args_non_class : Error<
> + "type arguments cannot be applied to non-class type %0">;
> +
> +def err_objc_type_args_non_parameterized_class : Error<
> + "type arguments cannot be applied to non-parameterized class %0">;
> +
> +def err_objc_type_args_specialized_class : Error<
> + "type arguments cannot be applied to already-specialized class type %0">;
> +
> +def err_objc_type_args_wrong_arity : Error<
> + "too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">;
> }
>
> +def err_objc_type_arg_not_id_compatible : Error<
> + "type argument %0 is neither an Objective-C object nor a block type">;
> +
> +def err_objc_type_arg_does_not_match_bound : Error<
> + "type argument %0 does not satisy the bound (%1) of type parameter %2">;
> +
> } // end of sema component.
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Mon Jul 6 22:57:35 2015
> @@ -1269,6 +1269,8 @@ private:
> SourceLocation &LAngleLoc,
> SourceLocation &EndProtoLoc);
> bool ParseObjCProtocolQualifiers(DeclSpec &DS);
> + void ParseObjCTypeArgsOrProtocolQualifiers(DeclSpec &DS,
> + bool warnOnIncompleteProtocols);
> void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
> Decl *CDecl);
> DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Mon Jul 6 22:57:35 2015
> @@ -373,6 +373,14 @@ private:
> // Scope specifier for the type spec, if applicable.
> CXXScopeSpec TypeScope;
>
> + /// List of Objective-C type arguments, e.g., in \c NSArray<NSView *>.
> + ArrayRef<ParsedType> ObjCTypeArgs;
> +
> + /// Location of the '<' that starts a list of Objective-C type arguments.
> + SourceLocation ObjCTypeArgsLAngleLoc;
> + /// Location of the '>' that ends a list of Objective-C type arguments.
> + SourceLocation ObjCTypeArgsRAngleLoc;
> +
> // List of protocol qualifiers for objective-c classes. Used for
> // protocol-qualified interfaces "NString<foo>" and protocol-qualified id
> // "id<foo>".
> @@ -449,6 +457,7 @@ public:
> ObjCQualifiers(nullptr) {
> }
> ~DeclSpec() {
> + delete [] ObjCTypeArgs.data();
> delete [] ProtocolQualifiers;
> delete [] ProtocolLocs;
> }
> @@ -751,6 +760,25 @@ public:
> Attrs.takeAllFrom(attrs);
> }
>
> + /// Determine whether the declaration specifiers contain Objective-C
> + /// type arguments.
> + bool hasObjCTypeArgs() const { return !ObjCTypeArgs.empty(); }
> +
> + ArrayRef<ParsedType> getObjCTypeArgs() const { return ObjCTypeArgs; }
> + SourceLocation getObjCTypeArgsLAngleLoc() const {
> + return ObjCTypeArgsLAngleLoc;
> + }
> + SourceLocation getObjCTypeArgsRAngleLoc() const {
> + return ObjCTypeArgsRAngleLoc;
> + }
> + SourceRange getObjCTypeArgsRange() const {
> + return SourceRange(ObjCTypeArgsLAngleLoc, ObjCTypeArgsRAngleLoc);
> + }
> +
> + void setObjCTypeArgs(SourceLocation lAngleLoc,
> + ArrayRef<ParsedType> args,
> + SourceLocation rAngleLoc);
> +
> typedef Decl * const *ProtocolQualifierListTy;
> ProtocolQualifierListTy getProtocolQualifiers() const {
> return ProtocolQualifiers;
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jul 6 22:57:35 2015
> @@ -7098,17 +7098,30 @@ public:
> SourceLocation rAngleLoc);
> void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
>
> - Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
> + Decl *ActOnStartClassInterface(Scope *S,
> + SourceLocation AtInterfaceLoc,
> IdentifierInfo *ClassName,
> SourceLocation ClassLoc,
> ObjCTypeParamList *typeParamList,
> IdentifierInfo *SuperName,
> SourceLocation SuperLoc,
> + ArrayRef<ParsedType> SuperTypeArgs,
> + SourceRange SuperTypeArgsRange,
> Decl * const *ProtoRefs,
> unsigned NumProtoRefs,
> const SourceLocation *ProtoLocs,
> SourceLocation EndProtoLoc,
> AttributeList *AttrList);
> +
> + void ActOnSuperClassOfClassInterface(Scope *S,
> + SourceLocation AtInterfaceLoc,
> + ObjCInterfaceDecl *IDecl,
> + IdentifierInfo *ClassName,
> + SourceLocation ClassLoc,
> + IdentifierInfo *SuperName,
> + SourceLocation SuperLoc,
> + ArrayRef<ParsedType> SuperTypeArgs,
> + SourceRange SuperTypeArgsRange);
>
> void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
> IdentifierInfo *SuperName,
> @@ -7174,6 +7187,19 @@ public:
> unsigned NumProtocols,
> SmallVectorImpl<Decl *> &Protocols);
>
> + /// Given a list of identifiers (and their locations), resolve the
> + /// names to either Objective-C protocol qualifiers or type
> + /// arguments, as appropriate. The result will be attached to the
> + /// given declaration specifiers.
> + void actOnObjCTypeArgsOrProtocolQualifiers(
> + Scope *S,
> + DeclSpec &DS,
> + SourceLocation lAngleLoc,
> + ArrayRef<IdentifierInfo *> identifiers,
> + ArrayRef<SourceLocation> identifierLocs,
> + SourceLocation rAngleLoc,
> + bool warnOnIncompleteProtocols);
> +
> /// Ensure attributes are consistent with type.
> /// \param [in, out] Attributes The attributes to check; they will
> /// be modified to be consistent with \p PropertyTy.
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jul 6 22:57:35 2015
> @@ -3618,45 +3618,85 @@ static void SortAndUniqueProtocols(ObjCP
> QualType ASTContext::getObjCObjectType(QualType BaseType,
> ObjCProtocolDecl * const *Protocols,
> unsigned NumProtocols) const {
> - // If the base type is an interface and there aren't any protocols
> - // to add, then the interface type will do just fine.
> - if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
> - return BaseType;
> + return getObjCObjectType(BaseType, { },
> + llvm::makeArrayRef(Protocols, NumProtocols));
> +}
> +
> +QualType ASTContext::getObjCObjectType(
> + QualType baseType,
> + ArrayRef<QualType> typeArgs,
> + ArrayRef<ObjCProtocolDecl *> protocols) const {
> + // If the base type is an interface and there aren't any protocols or
> + // type arguments to add, then the interface type will do just fine.
> + if (typeArgs.empty() && protocols.empty() && isa<ObjCInterfaceType>(baseType))
> + return baseType;
>
> // Look in the folding set for an existing type.
> llvm::FoldingSetNodeID ID;
> - ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
> + ObjCObjectTypeImpl::Profile(ID, baseType, typeArgs, protocols);
> void *InsertPos = nullptr;
> if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
> return QualType(QT, 0);
>
> - // Build the canonical type, which has the canonical base type and
> - // a sorted-and-uniqued list of protocols.
> - QualType Canonical;
> - bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
> - if (!ProtocolsSorted || !BaseType.isCanonical()) {
> - if (!ProtocolsSorted) {
> - SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
> - Protocols + NumProtocols);
> - unsigned UniqueCount = NumProtocols;
> -
> - SortAndUniqueProtocols(&Sorted[0], UniqueCount);
> - Canonical = getObjCObjectType(getCanonicalType(BaseType),
> - &Sorted[0], UniqueCount);
> + // Determine the type arguments to be used for canonicalization,
> + // which may be explicitly specified here or written on the base
> + // type.
> + ArrayRef<QualType> effectiveTypeArgs = typeArgs;
> + if (effectiveTypeArgs.empty()) {
> + if (auto baseObject = baseType->getAs<ObjCObjectType>())
> + effectiveTypeArgs = baseObject->getTypeArgs();
> + }
> +
> + // Build the canonical type, which has the canonical base type and a
> + // sorted-and-uniqued list of protocols and the type arguments
> + // canonicalized.
> + QualType canonical;
> + bool typeArgsAreCanonical = std::all_of(effectiveTypeArgs.begin(),
> + effectiveTypeArgs.end(),
> + [&](QualType type) {
> + return type.isCanonical();
> + });
> + bool protocolsSorted = areSortedAndUniqued(protocols.data(),
> + protocols.size());
> + if (!typeArgsAreCanonical || !protocolsSorted || !baseType.isCanonical()) {
> + // Determine the canonical type arguments.
> + ArrayRef<QualType> canonTypeArgs;
> + SmallVector<QualType, 4> canonTypeArgsVec;
> + if (!typeArgsAreCanonical) {
> + canonTypeArgsVec.reserve(effectiveTypeArgs.size());
> + for (auto typeArg : effectiveTypeArgs)
> + canonTypeArgsVec.push_back(getCanonicalType(typeArg));
> + canonTypeArgs = canonTypeArgsVec;
> } else {
> - Canonical = getObjCObjectType(getCanonicalType(BaseType),
> - Protocols, NumProtocols);
> + canonTypeArgs = effectiveTypeArgs;
> }
>
> + ArrayRef<ObjCProtocolDecl *> canonProtocols;
> + SmallVector<ObjCProtocolDecl*, 8> canonProtocolsVec;
> + if (!protocolsSorted) {
> + canonProtocolsVec.insert(canonProtocolsVec.begin(),
> + protocols.begin(),
> + protocols.end());
> + unsigned uniqueCount = protocols.size();
> + SortAndUniqueProtocols(&canonProtocolsVec[0], uniqueCount);
> + canonProtocols = llvm::makeArrayRef(&canonProtocolsVec[0], uniqueCount);
> + } else {
> + canonProtocols = protocols;
> + }
> +
> + canonical = getObjCObjectType(getCanonicalType(baseType), canonTypeArgs,
> + canonProtocols);
> +
> // Regenerate InsertPos.
> ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
> }
>
> - unsigned Size = sizeof(ObjCObjectTypeImpl);
> - Size += NumProtocols * sizeof(ObjCProtocolDecl *);
> - void *Mem = Allocate(Size, TypeAlignment);
> + unsigned size = sizeof(ObjCObjectTypeImpl);
> + size += typeArgs.size() * sizeof(QualType);
> + size += protocols.size() * sizeof(ObjCProtocolDecl *);
> + void *mem = Allocate(size, TypeAlignment);
> ObjCObjectTypeImpl *T =
> - new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
> + new (mem) ObjCObjectTypeImpl(canonical, baseType, typeArgs, protocols);
>
> Types.push_back(T);
> ObjCObjectTypes.InsertNode(T, InsertPos);
> @@ -5921,7 +5961,7 @@ void ASTContext::getObjCEncodingForTypeQ
>
> TypedefDecl *ASTContext::getObjCIdDecl() const {
> if (!ObjCIdDecl) {
> - QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0);
> + QualType T = getObjCObjectType(ObjCBuiltinIdTy, { }, { });
> T = getObjCObjectPointerType(T);
> ObjCIdDecl = buildImplicitTypedef(T, "id");
> }
> @@ -5938,7 +5978,7 @@ TypedefDecl *ASTContext::getObjCSelDecl(
>
> TypedefDecl *ASTContext::getObjCClassDecl() const {
> if (!ObjCClassDecl) {
> - QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0);
> + QualType T = getObjCObjectType(ObjCBuiltinClassTy, { }, { });
> T = getObjCObjectPointerType(T);
> ObjCClassDecl = buildImplicitTypedef(T, "Class");
> }
>
> Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
> +++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Mon Jul 6 22:57:35 2015
> @@ -125,12 +125,22 @@ break; \
> if (const PointerType *Ty = QT->getAs<PointerType>()) {
> QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
> ShouldAKA));
> + } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
> + QT = Context.getObjCObjectPointerType(Desugar(Context, Ty->getPointeeType(),
> + ShouldAKA));
> } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
> QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
> ShouldAKA));
> } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
> QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
> ShouldAKA));
> + } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
> + if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
According to ubsan, ShouldAKA is evaluated uninitialized here. In fact,
only one of the two non-recursive callers bother initializing it, but
until now we never read the value within Desugar.
I've gone ahead and fixed this in r241705. Please take a look.
> + QualType BaseType = Desugar(Context, Ty->getBaseType(), ShouldAKA);
> + QT = Context.getObjCObjectType(BaseType, Ty->getTypeArgsAsWritten(),
> + llvm::makeArrayRef(Ty->qual_begin(),
> + Ty->getNumProtocols()));
> + }
> }
>
> return QC.apply(Context, QT);
>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jul 6 22:57:35 2015
> @@ -1844,6 +1844,16 @@ QualType ASTNodeImporter::VisitObjCObjec
> if (ToBaseType.isNull())
> return QualType();
>
> + SmallVector<QualType, 4> TypeArgs;
> + for (auto TypeArg : T->getTypeArgs()) {
> + QualType ImportedTypeArg = Importer.Import(TypeArg);
> + if (ImportedTypeArg.isNull())
> + return QualType();
> +
> + TypeArgs.push_back(ImportedTypeArg);
> + }
> +
> +
> SmallVector<ObjCProtocolDecl *, 4> Protocols;
> for (auto *P : T->quals()) {
> ObjCProtocolDecl *Protocol
> @@ -1853,9 +1863,8 @@ QualType ASTNodeImporter::VisitObjCObjec
> Protocols.push_back(Protocol);
> }
>
> - return Importer.getToContext().getObjCObjectType(ToBaseType,
> - Protocols.data(),
> - Protocols.size());
> + return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs,
> + Protocols);
> }
>
> QualType
> @@ -3694,13 +3703,11 @@ bool ASTNodeImporter::ImportDefinition(O
>
> // If this class has a superclass, import it.
> if (From->getSuperClass()) {
> - ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
> - Importer.Import(From->getSuperClass()));
> - if (!Super)
> + TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
> + if (!SuperTInfo)
> return true;
> -
> - To->setSuperClass(Super);
> - To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
> +
> + To->setSuperClass(SuperTInfo);
> }
>
> // Import protocols
> @@ -5367,7 +5374,7 @@ TypeSourceInfo *ASTImporter::Import(Type
> return nullptr;
>
> return ToContext.getTrivialTypeSourceInfo(T,
> - FromTSI->getTypeLoc().getLocStart());
> + Import(FromTSI->getTypeLoc().getLocStart()));
> }
>
> Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
>
> Modified: cfe/trunk/lib/AST/DeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclObjC.cpp (original)
> +++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Jul 6 22:57:35 2015
> @@ -259,6 +259,33 @@ ObjCTypeParamList *ObjCInterfaceDecl::ge
> return nullptr;
> }
>
> +ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
> + // FIXME: Should make sure no callers ever do this.
> + if (!hasDefinition())
> + return nullptr;
> +
> + if (data().ExternallyCompleted)
> + LoadExternalDefinition();
> +
> + if (const ObjCObjectType *superType = getSuperClassType()) {
> + if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
> + if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
> + return superDef;
> +
> + return superDecl;
> + }
> + }
> +
> + return nullptr;
> +}
> +
> +SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
> + if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
> + return superTInfo->getTypeLoc().getLocStart();
> +
> + return SourceLocation();
> +}
> +
> /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
> /// with name 'PropertyId' in the primary class; including those in protocols
> /// (direct or indirect) used by the primary class.
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Mon Jul 6 22:57:35 2015
> @@ -467,19 +467,56 @@ const RecordType *Type::getAsUnionType()
> }
>
> ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
> - ObjCProtocolDecl * const *Protocols,
> - unsigned NumProtocols)
> + ArrayRef<QualType> typeArgs,
> + ArrayRef<ObjCProtocolDecl *> protocols)
> : Type(ObjCObject, Canonical, false, false, false, false),
> BaseType(Base)
> {
> - ObjCObjectTypeBits.NumProtocols = NumProtocols;
> - assert(getNumProtocols() == NumProtocols &&
> + ObjCObjectTypeBits.NumTypeArgs = typeArgs.size();
> + assert(getTypeArgsAsWritten().size() == typeArgs.size() &&
> + "bitfield overflow in type argument count");
> + ObjCObjectTypeBits.NumProtocols = protocols.size();
> + assert(getNumProtocols() == protocols.size() &&
> "bitfield overflow in protocol count");
> - if (NumProtocols)
> - memcpy(getProtocolStorage(), Protocols,
> - NumProtocols * sizeof(ObjCProtocolDecl*));
> + if (!typeArgs.empty())
> + memcpy(getTypeArgStorage(), typeArgs.data(),
> + typeArgs.size() * sizeof(QualType));
> + if (!protocols.empty())
> + memcpy(getProtocolStorage(), protocols.data(),
> + protocols.size() * sizeof(ObjCProtocolDecl*));
> }
>
> +bool ObjCObjectType::isSpecialized() const {
> + // If we have type arguments written here, the type is specialized.
> + if (ObjCObjectTypeBits.NumTypeArgs > 0)
> + return true;
> +
> + if (!qual_empty()) {
> + // Otherwise, check whether the base type is specialized.
> + if (auto objcObject = getBaseType()->getAs<ObjCObjectType>())
> + return objcObject->isSpecialized();
> + }
> +
> + // Not specialized.
> + return false;
> +}
> +
> +ArrayRef<QualType> ObjCObjectType::getTypeArgs() const {
> + // We have type arguments written on this type.
> + if (isSpecializedAsWritten())
> + return getTypeArgsAsWritten();
> +
> + if (!qual_empty()) {
> + // Look at the base type, which might have type arguments.
> + if (auto objcObject = getBaseType()->getAs<ObjCObjectType>())
> + return objcObject->getTypeArgs();
> + }
> +
> + // No type arguments.
> + return { };
> +}
> +
> +
> const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
> // There is no sugar for ObjCObjectType's, just return the canonical
> // type pointer if it is the right class. There is no typedef information to
> @@ -2076,15 +2113,20 @@ QualifierCollector::apply(const ASTConte
>
> void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID,
> QualType BaseType,
> - ObjCProtocolDecl * const *Protocols,
> - unsigned NumProtocols) {
> + ArrayRef<QualType> typeArgs,
> + ArrayRef<ObjCProtocolDecl *> protocols) {
> ID.AddPointer(BaseType.getAsOpaquePtr());
> - for (unsigned i = 0; i != NumProtocols; i++)
> - ID.AddPointer(Protocols[i]);
> + ID.AddInteger(typeArgs.size());
> + for (auto typeArg : typeArgs)
> + ID.AddPointer(typeArg.getAsOpaquePtr());
> + ID.AddInteger(protocols.size());
> + for (auto proto : protocols)
> + ID.AddPointer(proto);
> }
>
> void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
> - Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
> + Profile(ID, getBaseType(), getTypeArgs(),
> + llvm::makeArrayRef(qual_begin(), getNumProtocols()));
> }
>
> namespace {
> @@ -2495,6 +2537,39 @@ Optional<NullabilityKind> AttributedType
> return None;
> }
>
> +bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
> + const ObjCObjectPointerType *objcPtr = getAs<ObjCObjectPointerType>();
> + if (!objcPtr)
> + return false;
> +
> + if (objcPtr->isObjCIdType()) {
> + // id is always okay.
> + return true;
> + }
> +
> + // Blocks are NSObjects.
> + if (ObjCInterfaceDecl *iface = objcPtr->getInterfaceDecl()) {
> + if (iface->getIdentifier() != ctx.getNSObjectName())
> + return false;
> +
> + // Continue to check qualifiers, below.
> + } else if (objcPtr->isObjCQualifiedIdType()) {
> + // Continue to check qualifiers, below.
> + } else {
> + return false;
> + }
> +
> + // Check protocol qualifiers.
> + for (ObjCProtocolDecl *proto : objcPtr->quals()) {
> + // Blocks conform to NSObject and NSCopying.
> + if (proto->getIdentifier() != ctx.getNSObjectName() &&
> + proto->getIdentifier() != ctx.getNSCopyingName())
> + return false;
> + }
> +
> + return true;
> +}
> +
> Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const {
> if (isObjCARCImplicitlyUnretainedType())
> return Qualifiers::OCL_ExplicitNone;
>
> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
> +++ cfe/trunk/lib/AST/TypeLoc.cpp Mon Jul 6 22:57:35 2015
> @@ -312,6 +312,22 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLo
> return TL;
> }
>
> +void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
> + SourceLocation Loc) {
> + setHasBaseTypeAsWritten(true);
> + setTypeArgsLAngleLoc(Loc);
> + setTypeArgsRAngleLoc(Loc);
> + for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
> + setTypeArgTInfo(i,
> + Context.getTrivialTypeSourceInfo(
> + getTypePtr()->getTypeArgsAsWritten()[i], Loc));
> + }
> + setProtocolLAngleLoc(Loc);
> + setProtocolRAngleLoc(Loc);
> + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
> + setProtocolLoc(i, Loc);
> +}
> +
> void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
> SourceLocation Loc) {
> TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
>
> Modified: cfe/trunk/lib/AST/TypePrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/TypePrinter.cpp (original)
> +++ cfe/trunk/lib/AST/TypePrinter.cpp Mon Jul 6 22:57:35 2015
> @@ -1310,59 +1310,56 @@ void TypePrinter::printObjCInterfaceAfte
>
> void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
> raw_ostream &OS) {
> - if (T->qual_empty())
> + if (T->qual_empty() && T->isUnspecializedAsWritten())
> return printBefore(T->getBaseType(), OS);
>
> print(T->getBaseType(), OS, StringRef());
> - OS << '<';
> - bool isFirst = true;
> - for (const auto *I : T->quals()) {
> - if (isFirst)
> - isFirst = false;
> - else
> - OS << ',';
> - OS << I->getName();
> +
> + if (T->isSpecializedAsWritten()) {
> + bool isFirst = true;
> + OS << '<';
> + for (auto typeArg : T->getTypeArgsAsWritten()) {
> + if (isFirst)
> + isFirst = false;
> + else
> + OS << ",";
> +
> + print(typeArg, OS, StringRef());
> + }
> + OS << '>';
> + }
> +
> + if (!T->qual_empty()) {
> + bool isFirst = true;
> + OS << '<';
> + for (const auto *I : T->quals()) {
> + if (isFirst)
> + isFirst = false;
> + else
> + OS << ',';
> + OS << I->getName();
> + }
> + OS << '>';
> }
> - OS << '>';
> +
> spaceBeforePlaceHolder(OS);
> }
> void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
> raw_ostream &OS) {
> - if (T->qual_empty())
> + if (T->qual_empty() && T->isUnspecializedAsWritten())
> return printAfter(T->getBaseType(), OS);
> }
>
> void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
> raw_ostream &OS) {
> - T->getPointeeType().getLocalQualifiers().print(OS, Policy,
> - /*appendSpaceIfNonEmpty=*/true);
> + printBefore(T->getPointeeType(), OS);
>
> - assert(!T->isObjCSelType());
> -
> - if (T->isObjCIdType() || T->isObjCQualifiedIdType())
> - OS << "id";
> - else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
> - OS << "Class";
> - else
> - OS << T->getInterfaceDecl()->getName();
> -
> - if (!T->qual_empty()) {
> - OS << '<';
> - for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
> - E = T->qual_end();
> - I != E; ++I) {
> - OS << (*I)->getName();
> - if (I+1 != E)
> - OS << ',';
> - }
> - OS << '>';
> - }
> -
> + // If we need to print the pointer, print it now.
> if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
> !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
> - OS << " *"; // Don't forget the implicit pointer.
> - } else {
> - spaceBeforePlaceHolder(OS);
> + if (HasEmptyPlaceHolder)
> + OS << ' ';
> + OS << '*';
> }
> }
> void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jul 6 22:57:35 2015
> @@ -2886,11 +2886,26 @@ void Parser::ParseDeclarationSpecifiers(
> DS.SetRangeEnd(Tok.getAnnotationEndLoc());
> ConsumeToken(); // The typename
>
> - // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
> - // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
> - // Objective-C interface.
> - if (Tok.is(tok::less) && getLangOpts().ObjC1)
> - ParseObjCProtocolQualifiers(DS);
> + // Objective-C supports type arguments and protocol references
> + // following an Objective-C object pointer type. Handle either
> + // one of them.
> + if (Tok.is(tok::less) && getLangOpts().ObjC1) {
> + ParseObjCTypeArgsOrProtocolQualifiers(
> + DS, /*warnOnIncompleteProtocols=*/false);
> +
> + // An Objective-C object pointer followed by type arguments
> + // can then be followed again by a set of protocol references, e.g.,
> + // \c NSArray<NSView><NSTextDelegate>
> + if (Tok.is(tok::less)) {
> + if (DS.getProtocolQualifiers()) {
> + Diag(Tok, diag::err_objc_type_args_after_protocols)
> + << SourceRange(DS.getProtocolLAngleLoc(), DS.getLocEnd());
> + SkipUntil(tok::greater, tok::greatergreater);
> + } else {
> + ParseObjCProtocolQualifiers(DS);
> + }
> + }
> + }
>
> continue;
> }
> @@ -2997,11 +3012,26 @@ void Parser::ParseDeclarationSpecifiers(
> DS.SetRangeEnd(Tok.getLocation());
> ConsumeToken(); // The identifier
>
> - // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
> - // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
> - // Objective-C interface.
> - if (Tok.is(tok::less) && getLangOpts().ObjC1)
> - ParseObjCProtocolQualifiers(DS);
> + // Objective-C supports type arguments and protocol references
> + // following an Objective-C object pointer type. Handle either
> + // one of them.
> + if (Tok.is(tok::less) && getLangOpts().ObjC1) {
> + ParseObjCTypeArgsOrProtocolQualifiers(
> + DS, /*warnOnIncompleteProtocols=*/false);
> +
> + // An Objective-C object pointer followed by type arguments
> + // can then be followed again by a set of protocol references, e.g.,
> + // \c NSArray<NSView><NSTextDelegate>
> + if (Tok.is(tok::less)) {
> + if (DS.getProtocolQualifiers()) {
> + Diag(Tok, diag::err_objc_type_args_after_protocols)
> + << SourceRange(DS.getProtocolLAngleLoc(), DS.getLocEnd());
> + SkipUntil(tok::greater, tok::greatergreater);
> + } else {
> + ParseObjCProtocolQualifiers(DS);
> + }
> + }
> + }
>
> // Need to support trailing type qualifiers (e.g. "id<p> const").
> // If a type specifier follows, it will be diagnosed elsewhere.
>
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Jul 6 22:57:35 2015
> @@ -179,7 +179,7 @@ void Parser::CheckNestedObjCContexts(Sou
> /// @end
> ///
> /// objc-superclass:
> -/// ':' identifier
> +/// ':' identifier objc-type-arguments[opt]
> ///
> /// objc-class-interface-attributes:
> /// __attribute__((visibility("default")))
> @@ -293,6 +293,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclar
> // Parse a class interface.
> IdentifierInfo *superClassId = nullptr;
> SourceLocation superClassLoc;
> + DeclSpec superClassDS(AttrFactory);
>
> if (Tok.is(tok::colon)) { // a super class is specified.
> ConsumeToken();
> @@ -311,18 +312,12 @@ Decl *Parser::ParseObjCAtInterfaceDeclar
> }
> superClassId = Tok.getIdentifierInfo();
> superClassLoc = ConsumeToken();
> - } else if (typeParameterList) {
> - // An objc-type-parameter-list is ambiguous with an objc-protocol-refs
> - // in an @interface without a specified superclass, so such classes
> - // are ill-formed. We have determined that we have an
> - // objc-type-parameter-list but no superclass, so complain and record
> - // as if we inherited from NSObject.
> - SourceLocation insertLoc = PP.getLocForEndOfToken(PrevTokLocation);
> - Diag(insertLoc, diag::err_objc_parameterized_class_without_base)
> - << nameId
> - << FixItHint::CreateInsertion(insertLoc, " : NSObject");
> - superClassId = PP.getIdentifierInfo("NSObject");
> - superClassLoc = Tok.getLocation();
> +
> + // Type arguments for the superclass or protocol conformances.
> + if (Tok.is(tok::less)) {
> + ParseObjCTypeArgsOrProtocolQualifiers(superClassDS,
> + /*warnOnIncompleteProtocols=*/true);
> + }
> }
>
> // Next, we need to check for any protocol references.
> @@ -338,6 +333,16 @@ Decl *Parser::ParseObjCAtInterfaceDeclar
> /*ForObjCContainer=*/true,
> &ProtocolIdents[0], ProtocolIdents.size(),
> ProtocolRefs);
> + } else if (auto protocols = superClassDS.getProtocolQualifiers()) {
> + // We already parsed the protocols named when we thought we had a
> + // type argument list (for a specialized superclass). Treat them
> + // as actual protocol references.
> + unsigned numProtocols = superClassDS.getNumProtocolQualifiers();
> + ProtocolRefs.append(protocols, protocols + numProtocols);
> + ProtocolLocs.append(superClassDS.getProtocolLocs(),
> + superClassDS.getProtocolLocs() + numProtocols);
> + LAngleLoc = superClassDS.getProtocolLAngleLoc();
> + EndProtoLoc = superClassDS.getLocEnd();
> } else if (Tok.is(tok::less) &&
> ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
> LAngleLoc, EndProtoLoc)) {
> @@ -348,8 +353,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclar
> Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
>
> Decl *ClsType =
> - Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc, typeParameterList,
> - superClassId, superClassLoc,
> + Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc,
> + typeParameterList, superClassId,
> + superClassLoc,
> + superClassDS.getObjCTypeArgs(),
> + superClassDS.getObjCTypeArgsRange(),
> ProtocolRefs.data(), ProtocolRefs.size(),
> ProtocolLocs.data(),
> EndProtoLoc, attrs.getList());
> @@ -1554,8 +1562,7 @@ bool Parser::ParseObjCProtocolQualifiers
> SmallVector<Decl *, 8> ProtocolDecl;
> SmallVector<SourceLocation, 8> ProtocolLocs;
> bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
> - false,
> - LAngleLoc, EndProtoLoc);
> + false, LAngleLoc, EndProtoLoc);
> DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
> ProtocolLocs.data(), LAngleLoc);
> if (EndProtoLoc.isValid())
> @@ -1563,6 +1570,111 @@ bool Parser::ParseObjCProtocolQualifiers
> return Result;
> }
>
> +/// Parse Objective-C type arguments or protocol qualifiers.
> +///
> +/// objc-type-arguments:
> +/// '<' type-name (',' type-name)* '>'
> +///
> +void Parser::ParseObjCTypeArgsOrProtocolQualifiers(
> + DeclSpec &DS,
> + bool warnOnIncompleteProtocols) {
> + assert(Tok.is(tok::less) && "Not at the start of type args or protocols");
> + SourceLocation lAngleLoc = ConsumeToken();
> +
> + // Whether all of the elements we've parsed thus far are single
> + // identifiers, which might be types or might be protocols.
> + bool allSingleIdentifiers = true;
> + SmallVector<IdentifierInfo *, 4> identifiers;
> + SmallVector<SourceLocation, 4> identifierLocs;
> +
> + // Parse a list of comma-separated identifiers, bailing out if we
> + // see something different.
> + do {
> + // Parse a single identifier.
> + if (Tok.is(tok::identifier) &&
> + (NextToken().is(tok::comma) ||
> + NextToken().is(tok::greater) ||
> + NextToken().is(tok::greatergreater))) {
> + identifiers.push_back(Tok.getIdentifierInfo());
> + identifierLocs.push_back(ConsumeToken());
> + continue;
> + }
> +
> + if (Tok.is(tok::code_completion)) {
> + // FIXME: Also include types here.
> + SmallVector<IdentifierLocPair, 4> identifierLocPairs;
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
> + identifierLocs[i]));
> + }
> +
> + Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(),
> + identifierLocPairs.size());
> + cutOffParsing();
> + return;
> + }
> +
> + allSingleIdentifiers = false;
> + break;
> + } while (TryConsumeToken(tok::comma));
> +
> + // If we parsed an identifier list, semantic analysis sorts out
> + // whether it refers to protocols or to type arguments.
> + if (allSingleIdentifiers) {
> + // Parse the closing '>'.
> + SourceLocation rAngleLoc;
> + (void)ParseGreaterThanInTemplateList(rAngleLoc, /*ConsumeLastToken=*/true,
> + /*ObjCGenericList=*/true);
> +
> + // Let Sema figure out what we parsed.
> + Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(),
> + DS,
> + lAngleLoc,
> + identifiers,
> + identifierLocs,
> + rAngleLoc,
> + warnOnIncompleteProtocols);
> + return;
> + }
> +
> + // We syntactically matched a type argument, so commit to parsing
> + // type arguments.
> + SmallVector<ParsedType, 4> typeArgs;
> +
> + // Convert the identifiers into type arguments.
> + bool invalid = false;
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + ParsedType typeArg
> + = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());
> + if (typeArg) {
> + typeArgs.push_back(typeArg);
> + } else {
> + invalid = true;
> + }
> + }
> +
> + // Continue parsing type-names.
> + do {
> + TypeResult typeArg = ParseTypeName();
> + if (typeArg.isUsable()) {
> + typeArgs.push_back(typeArg.get());
> + } else {
> + invalid = true;
> + }
> + } while (TryConsumeToken(tok::comma));
> +
> + // Parse the closing '>'.
> + SourceLocation rAngleLoc;
> + (void)ParseGreaterThanInTemplateList(rAngleLoc, /*ConsumeLastToken=*/true,
> + /*ObjCGenericList=*/true);
> +
> + if (invalid)
> + return;
> +
> + // Update the DeclSpec appropriately.
> + DS.setObjCTypeArgs(lAngleLoc, typeArgs, rAngleLoc);
> +}
> +
> void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
> BalancedDelimiterTracker &T,
> SmallVectorImpl<Decl *> &AllIvarDecls,
>
> Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseTentative.cpp Mon Jul 6 22:57:35 2015
> @@ -1384,7 +1384,7 @@ Parser::isCXXDeclarationSpecifier(Parser
> case_typename:
> // In Objective-C, we might have a protocol-qualified type.
> if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
> - // Tentatively parse the
> + // Tentatively parse the protocol qualifiers.
> TentativeParsingAction PA(*this);
> ConsumeToken(); // The type token
>
>
> Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/DeclSpec.cpp Mon Jul 6 22:57:35 2015
> @@ -893,6 +893,7 @@ bool DeclSpec::SetConstexprSpec(SourceLo
> return false;
> }
>
> +
> bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
> unsigned &DiagID) {
> if (Concept_specified) {
> @@ -905,6 +906,16 @@ bool DeclSpec::SetConceptSpec(SourceLoca
> return false;
> }
>
> +void DeclSpec::setObjCTypeArgs(SourceLocation lAngleLoc,
> + ArrayRef<ParsedType> args,
> + SourceLocation rAngleLoc) {
> + ParsedType *argsCopy = new ParsedType[args.size()];
> + memcpy(argsCopy, args.data(), args.size() * sizeof(ParsedType));
> + ObjCTypeArgs = llvm::makeArrayRef(argsCopy, args.size());
> + ObjCTypeArgsLAngleLoc = lAngleLoc;
> + ObjCTypeArgsRAngleLoc = rAngleLoc;
> +}
> +
> void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
> unsigned NP,
> SourceLocation *ProtoLocs,
>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jul 6 22:57:35 2015
> @@ -464,6 +464,142 @@ static void diagnoseUseOfProtocols(Sema
> }
> }
>
> +void Sema::
> +ActOnSuperClassOfClassInterface(Scope *S,
> + SourceLocation AtInterfaceLoc,
> + ObjCInterfaceDecl *IDecl,
> + IdentifierInfo *ClassName,
> + SourceLocation ClassLoc,
> + IdentifierInfo *SuperName,
> + SourceLocation SuperLoc,
> + ArrayRef<ParsedType> SuperTypeArgs,
> + SourceRange SuperTypeArgsRange) {
> + // Check if a different kind of symbol declared in this scope.
> + NamedDecl *PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
> + LookupOrdinaryName);
> +
> + if (!PrevDecl) {
> + // Try to correct for a typo in the superclass name without correcting
> + // to the class we're defining.
> + if (TypoCorrection Corrected = CorrectTypo(
> + DeclarationNameInfo(SuperName, SuperLoc),
> + LookupOrdinaryName, TUScope,
> + NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
> + CTK_ErrorRecovery)) {
> + diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
> + << SuperName << ClassName);
> + PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
> + }
> + }
> +
> + if (declaresSameEntity(PrevDecl, IDecl)) {
> + Diag(SuperLoc, diag::err_recursive_superclass)
> + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
> + IDecl->setEndOfDefinitionLoc(ClassLoc);
> + } else {
> + ObjCInterfaceDecl *SuperClassDecl =
> + dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
> + QualType SuperClassType;
> +
> + // Diagnose classes that inherit from deprecated classes.
> + if (SuperClassDecl) {
> + (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
> + SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
> + }
> +
> + if (PrevDecl && SuperClassDecl == 0) {
> + // The previous declaration was not a class decl. Check if we have a
> + // typedef. If we do, get the underlying class type.
> + if (const TypedefNameDecl *TDecl =
> + dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
> + QualType T = TDecl->getUnderlyingType();
> + if (T->isObjCObjectType()) {
> + if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
> + SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
> + SuperClassType = Context.getTypeDeclType(TDecl);
> +
> + // This handles the following case:
> + // @interface NewI @end
> + // typedef NewI DeprI __attribute__((deprecated("blah")))
> + // @interface SI : DeprI /* warn here */ @end
> + (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
> + }
> + }
> + }
> +
> + // This handles the following case:
> + //
> + // typedef int SuperClass;
> + // @interface MyClass : SuperClass {} @end
> + //
> + if (!SuperClassDecl) {
> + Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
> + Diag(PrevDecl->getLocation(), diag::note_previous_definition);
> + }
> + }
> +
> + if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
> + if (!SuperClassDecl)
> + Diag(SuperLoc, diag::err_undef_superclass)
> + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
> + else if (RequireCompleteType(SuperLoc,
> + SuperClassType,
> + diag::err_forward_superclass,
> + SuperClassDecl->getDeclName(),
> + ClassName,
> + SourceRange(AtInterfaceLoc, ClassLoc))) {
> + SuperClassDecl = 0;
> + SuperClassType = QualType();
> + }
> + }
> +
> + if (SuperClassType.isNull()) {
> + assert(!SuperClassDecl && "Failed to set SuperClassType?");
> + return;
> + }
> +
> + // Handle type arguments on the superclass.
> + TypeSourceInfo *SuperClassTInfo = nullptr;
> + if (!SuperTypeArgs.empty()) {
> + // Form declaration specifiers naming this superclass type with
> + // type arguments.
> + AttributeFactory attrFactory;
> + DeclSpec DS(attrFactory);
> + const char* prevSpec; // unused
> + unsigned diagID; // unused
> + TypeSourceInfo *parsedTSInfo
> + = Context.getTrivialTypeSourceInfo(SuperClassType, SuperLoc);
> + ParsedType parsedType = CreateParsedType(SuperClassType, parsedTSInfo);
> +
> + DS.SetTypeSpecType(DeclSpec::TST_typename, SuperLoc, prevSpec, diagID,
> + parsedType, Context.getPrintingPolicy());
> + DS.SetRangeStart(SuperLoc);
> + DS.SetRangeEnd(SuperLoc);
> + DS.setObjCTypeArgs(SuperTypeArgsRange.getBegin(),
> + SuperTypeArgs,
> + SuperTypeArgsRange.getEnd());
> +
> + // Form the declarator.
> + Declarator D(DS, Declarator::TypeNameContext);
> +
> + TypeResult fullSuperClassType = ActOnTypeName(S, D);
> + if (!fullSuperClassType.isUsable())
> + return;
> +
> + SuperClassType = GetTypeFromParser(fullSuperClassType.get(),
> + &SuperClassTInfo);
> + }
> +
> + if (!SuperClassTInfo) {
> + SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
> + SuperLoc);
> + }
> +
> + IDecl->setSuperClass(SuperClassTInfo);
> + IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getLocEnd());
> + }
> +}
> +
> DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName,
> SourceLocation paramLoc,
> SourceLocation colonLoc,
> @@ -499,7 +635,7 @@ DeclResult Sema::actOnObjCTypeParam(Scop
> // Form the new type source information.
> typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);
> } else {
> - // Not a
> + // Not a valid type bound.
> Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
> diag::err_objc_type_param_bound_nonobject)
> << typeBound << paramName;
> @@ -669,10 +805,12 @@ static bool checkTypeParamListConsistenc
> }
>
> Decl *Sema::
> -ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
> +ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
> IdentifierInfo *ClassName, SourceLocation ClassLoc,
> ObjCTypeParamList *typeParamList,
> IdentifierInfo *SuperName, SourceLocation SuperLoc,
> + ArrayRef<ParsedType> SuperTypeArgs,
> + SourceRange SuperTypeArgsRange,
> Decl * const *ProtoRefs, unsigned NumProtoRefs,
> const SourceLocation *ProtoLocs,
> SourceLocation EndProtoLoc, AttributeList *AttrList) {
> @@ -767,84 +905,13 @@ ActOnStartClassInterface(SourceLocation
> IDecl->startDefinition();
>
> if (SuperName) {
> - // Check if a different kind of symbol declared in this scope.
> - PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
> - LookupOrdinaryName);
> -
> - if (!PrevDecl) {
> - // Try to correct for a typo in the superclass name without correcting
> - // to the class we're defining.
> - if (TypoCorrection Corrected =
> - CorrectTypo(DeclarationNameInfo(SuperName, SuperLoc),
> - LookupOrdinaryName, TUScope, nullptr,
> - llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
> - CTK_ErrorRecovery)) {
> - diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
> - << SuperName << ClassName);
> - PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
> - }
> - }
> -
> - if (declaresSameEntity(PrevDecl, IDecl)) {
> - Diag(SuperLoc, diag::err_recursive_superclass)
> - << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
> - IDecl->setEndOfDefinitionLoc(ClassLoc);
> - } else {
> - ObjCInterfaceDecl *SuperClassDecl =
> - dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
> -
> - // Diagnose availability in the context of the @interface.
> - ContextRAII SavedContext(*this, IDecl);
> - // Diagnose classes that inherit from deprecated classes.
> - if (SuperClassDecl)
> - (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
> -
> - if (PrevDecl && !SuperClassDecl) {
> - // The previous declaration was not a class decl. Check if we have a
> - // typedef. If we do, get the underlying class type.
> - if (const TypedefNameDecl *TDecl =
> - dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
> - QualType T = TDecl->getUnderlyingType();
> - if (T->isObjCObjectType()) {
> - if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
> - SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
> - // This handles the following case:
> - // @interface NewI @end
> - // typedef NewI DeprI __attribute__((deprecated("blah")))
> - // @interface SI : DeprI /* warn here */ @end
> - (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
> - }
> - }
> - }
> -
> - // This handles the following case:
> - //
> - // typedef int SuperClass;
> - // @interface MyClass : SuperClass {} @end
> - //
> - if (!SuperClassDecl) {
> - Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
> - Diag(PrevDecl->getLocation(), diag::note_previous_definition);
> - }
> - }
> + // Diagnose availability in the context of the @interface.
> + ContextRAII SavedContext(*this, IDecl);
>
> - if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
> - if (!SuperClassDecl)
> - Diag(SuperLoc, diag::err_undef_superclass)
> - << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
> - else if (RequireCompleteType(SuperLoc,
> - Context.getObjCInterfaceType(SuperClassDecl),
> - diag::err_forward_superclass,
> - SuperClassDecl->getDeclName(),
> - ClassName,
> - SourceRange(AtInterfaceLoc, ClassLoc))) {
> - SuperClassDecl = nullptr;
> - }
> - }
> - IDecl->setSuperClass(SuperClassDecl);
> - IDecl->setSuperClassLoc(SuperLoc);
> - IDecl->setEndOfDefinitionLoc(SuperLoc);
> - }
> + ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
> + ClassName, ClassLoc,
> + SuperName, SuperLoc, SuperTypeArgs,
> + SuperTypeArgsRange);
> } else { // we have a root class.
> IDecl->setEndOfDefinitionLoc(ClassLoc);
> }
> @@ -1091,6 +1158,325 @@ Sema::FindProtocolDeclaration(bool WarnO
> }
> }
>
> +// Callback to only accept typo corrections that are either
> +// Objective-C protocols or valid Objective-C type arguments.
> +class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback {
> + ASTContext &Context;
> + Sema::LookupNameKind LookupKind;
> + public:
> + ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,
> + Sema::LookupNameKind lookupKind)
> + : Context(context), LookupKind(lookupKind) { }
> +
> + bool ValidateCandidate(const TypoCorrection &candidate) override {
> + // If we're allowed to find protocols and we have a protocol, accept it.
> + if (LookupKind != Sema::LookupOrdinaryName) {
> + if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())
> + return true;
> + }
> +
> + // If we're allowed to find type names and we have one, accept it.
> + if (LookupKind != Sema::LookupObjCProtocolName) {
> + // If we have a type declaration, we might accept this result.
> + if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {
> + // If we found a tag declaration outside of C++, skip it. This
> + // can happy because we look for any name when there is no
> + // bias to protocol or type names.
> + if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)
> + return false;
> +
> + // Make sure the type is something we would accept as a type
> + // argument.
> + auto type = Context.getTypeDeclType(typeDecl);
> + if (type->isObjCObjectPointerType() ||
> + type->isBlockPointerType() ||
> + type->isDependentType() ||
> + type->isObjCObjectType())
> + return true;
> +
> + return false;
> + }
> +
> + // If we have an Objective-C class type, accept it; there will
> + // be another fix to add the '*'.
> + if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())
> + return true;
> +
> + return false;
> + }
> +
> + return false;
> + }
> +};
> +
> +void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
> + Scope *S,
> + DeclSpec &DS,
> + SourceLocation lAngleLoc,
> + ArrayRef<IdentifierInfo *> identifiers,
> + ArrayRef<SourceLocation> identifierLocs,
> + SourceLocation rAngleLoc,
> + bool warnOnIncompleteProtocols) {
> + // Local function that updates the declaration specifiers with
> + // protocol information.
> + SmallVector<ObjCProtocolDecl *, 4> protocols;
> + unsigned numProtocolsResolved = 0;
> + auto resolvedAsProtocols = [&] {
> + assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");
> +
> + for (unsigned i = 0, n = protocols.size(); i != n; ++i) {
> + ObjCProtocolDecl *&proto = protocols[i];
> + // For an objc container, delay protocol reference checking until after we
> + // can set the objc decl as the availability context, otherwise check now.
> + if (!warnOnIncompleteProtocols) {
> + (void)DiagnoseUseOfDecl(proto, identifierLocs[i]);
> + }
> +
> + // If this is a forward protocol declaration, get its definition.
> + if (!proto->isThisDeclarationADefinition() && proto->getDefinition())
> + proto = proto->getDefinition();
> +
> + // If this is a forward declaration and we are supposed to warn in this
> + // case, do it.
> + // FIXME: Recover nicely in the hidden case.
> + ObjCProtocolDecl *forwardDecl = nullptr;
> + if (warnOnIncompleteProtocols &&
> + NestedProtocolHasNoDefinition(proto, forwardDecl)) {
> + Diag(identifierLocs[i], diag::warn_undef_protocolref)
> + << proto->getDeclName();
> + Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)
> + << forwardDecl;
> + }
> + }
> +
> + DS.setProtocolQualifiers((Decl * const *)(protocols.data()),
> + protocols.size(),
> + const_cast<SourceLocation *>(identifierLocs.data()),
> + lAngleLoc);
> + if (rAngleLoc.isValid())
> + DS.SetRangeEnd(rAngleLoc);
> + };
> +
> + // Attempt to resolve all of the identifiers as protocols.
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);
> + protocols.push_back(proto);
> + if (proto)
> + ++numProtocolsResolved;
> + }
> +
> + // If all of the names were protocols, these were protocol qualifiers.
> + if (numProtocolsResolved == identifiers.size())
> + return resolvedAsProtocols();
> +
> + // Attempt to resolve all of the identifiers as type names or
> + // Objective-C class names. The latter is technically ill-formed,
> + // but is probably something like \c NSArray<NSView *> missing the
> + // \c*.
> + typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;
> + SmallVector<TypeOrClassDecl, 4> typeDecls;
> + unsigned numTypeDeclsResolved = 0;
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + NamedDecl *decl = LookupSingleName(S, identifiers[i], identifierLocs[i],
> + LookupOrdinaryName);
> + if (!decl) {
> + typeDecls.push_back(TypeOrClassDecl());
> + continue;
> + }
> +
> + if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
> + typeDecls.push_back(typeDecl);
> + ++numTypeDeclsResolved;
> + continue;
> + }
> +
> + if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {
> + typeDecls.push_back(objcClass);
> + ++numTypeDeclsResolved;
> + continue;
> + }
> +
> + typeDecls.push_back(TypeOrClassDecl());
> + }
> +
> + AttributeFactory attrFactory;
> +
> + // Local function that forms a reference to the given type or
> + // Objective-C class declaration.
> + auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
> + -> TypeResult {
> + // Form declaration specifiers. They simply refer to the type.
> + DeclSpec DS(attrFactory);
> + const char* prevSpec; // unused
> + unsigned diagID; // unused
> + QualType type;
> + if (auto *actualTypeDecl = typeDecl.dyn_cast<TypeDecl *>())
> + type = Context.getTypeDeclType(actualTypeDecl);
> + else
> + type = Context.getObjCInterfaceType(typeDecl.get<ObjCInterfaceDecl *>());
> + TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);
> + ParsedType parsedType = CreateParsedType(type, parsedTSInfo);
> + DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,
> + parsedType, Context.getPrintingPolicy());
> + // Use the identifier location for the type source range.
> + DS.SetRangeStart(loc);
> + DS.SetRangeEnd(loc);
> +
> + // Form the declarator.
> + Declarator D(DS, Declarator::TypeNameContext);
> +
> + // If we have a typedef of an Objective-C class type that is missing a '*',
> + // add the '*'.
> + if (type->getAs<ObjCInterfaceType>()) {
> + SourceLocation starLoc = PP.getLocForEndOfToken(loc);
> + ParsedAttributes parsedAttrs(attrFactory);
> + D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
> + SourceLocation(),
> + SourceLocation(),
> + SourceLocation(),
> + SourceLocation()),
> + parsedAttrs,
> + starLoc);
> +
> + // Diagnose the missing '*'.
> + Diag(loc, diag::err_objc_type_arg_missing_star)
> + << type
> + << FixItHint::CreateInsertion(starLoc, " *");
> + }
> +
> + // Convert this to a type.
> + return ActOnTypeName(S, D);
> + };
> +
> + // Local function that updates the declaration specifiers with
> + // type argument information.
> + auto resolvedAsTypeDecls = [&] {
> + assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl");
> + // Map type declarations to type arguments.
> + SmallVector<ParsedType, 4> typeArgs;
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + // Map type reference to a type.
> + TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]);
> + if (!type.isUsable())
> + return;
> +
> + typeArgs.push_back(type.get());
> + }
> +
> + // Record the Objective-C type arguments.
> + DS.setObjCTypeArgs(lAngleLoc, typeArgs, rAngleLoc);
> + };
> +
> + // If all of the identifiers can be resolved as type names or
> + // Objective-C class names, we have type arguments.
> + if (numTypeDeclsResolved == identifiers.size())
> + return resolvedAsTypeDecls();
> +
> + // Error recovery: some names weren't found, or we have a mix of
> + // type and protocol names. Go resolve all of the unresolved names
> + // and complain if we can't find a consistent answer.
> + LookupNameKind lookupKind = LookupAnyName;
> + for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
> + // If we already have a protocol or type. Check whether it is the
> + // right thing.
> + if (protocols[i] || typeDecls[i]) {
> + // If we haven't figured out whether we want types or protocols
> + // yet, try to figure it out from this name.
> + if (lookupKind == LookupAnyName) {
> + // If this name refers to both a protocol and a type (e.g., \c
> + // NSObject), don't conclude anything yet.
> + if (protocols[i] && typeDecls[i])
> + continue;
> +
> + // Otherwise, let this name decide whether we'll be correcting
> + // toward types or protocols.
> + lookupKind = protocols[i] ? LookupObjCProtocolName
> + : LookupOrdinaryName;
> + continue;
> + }
> +
> + // If we want protocols and we have a protocol, there's nothing
> + // more to do.
> + if (lookupKind == LookupObjCProtocolName && protocols[i])
> + continue;
> +
> + // If we want types and we have a type declaration, there's
> + // nothing more to do.
> + if (lookupKind == LookupOrdinaryName && typeDecls[i])
> + continue;
> +
> + // We have a conflict: some names refer to protocols and others
> + // refer to types.
> + Diag(identifierLocs[i], diag::err_objc_type_args_and_protocols)
> + << (protocols[i] != nullptr)
> + << identifiers[i]
> + << identifiers[0]
> + << SourceRange(identifierLocs[0]);
> +
> + return;
> + }
> +
> + // Perform typo correction on the name.
> + TypoCorrection corrected = CorrectTypo(
> + DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,
> + nullptr,
> + llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(Context,
> + lookupKind),
> + CTK_ErrorRecovery);
> + if (corrected) {
> + // Did we find a protocol?
> + if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
> + diagnoseTypo(corrected,
> + PDiag(diag::err_undeclared_protocol_suggest)
> + << identifiers[i]);
> + lookupKind = LookupObjCProtocolName;
> + protocols[i] = proto;
> + ++numProtocolsResolved;
> + continue;
> + }
> +
> + // Did we find a type?
> + if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {
> + diagnoseTypo(corrected,
> + PDiag(diag::err_unknown_typename_suggest)
> + << identifiers[i]);
> + lookupKind = LookupOrdinaryName;
> + typeDecls[i] = typeDecl;
> + ++numTypeDeclsResolved;
> + continue;
> + }
> +
> + // Did we find an Objective-C class?
> + if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
> + diagnoseTypo(corrected,
> + PDiag(diag::err_unknown_type_or_class_name_suggest)
> + << identifiers[i] << true);
> + lookupKind = LookupOrdinaryName;
> + typeDecls[i] = objcClass;
> + ++numTypeDeclsResolved;
> + continue;
> + }
> + }
> +
> + // We couldn't find anything.
> + Diag(identifierLocs[i],
> + (lookupKind == LookupAnyName ? diag::err_objc_type_arg_missing
> + : lookupKind == LookupObjCProtocolName ? diag::err_undeclared_protocol
> + : diag::err_unknown_typename))
> + << identifiers[i];
> + return;
> + }
> +
> + // If all of the names were (corrected to) protocols, these were
> + // protocol qualifiers.
> + if (numProtocolsResolved == identifiers.size())
> + return resolvedAsProtocols();
> +
> + // Otherwise, all of the names were (corrected to) types.
> + assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");
> + return resolvedAsTypeDecls();
> +}
> +
> /// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
> /// a class method in its extension.
> ///
> @@ -1374,8 +1760,9 @@ Decl *Sema::ActOnStartClassImplementatio
> true);
> IDecl->startDefinition();
> if (SDecl) {
> - IDecl->setSuperClass(SDecl);
> - IDecl->setSuperClassLoc(SuperClassLoc);
> + IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(
> + Context.getObjCInterfaceType(SDecl),
> + SuperClassLoc));
> IDecl->setEndOfDefinitionLoc(SuperClassLoc);
> } else {
> IDecl->setEndOfDefinitionLoc(ClassLoc);
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jul 6 22:57:35 2015
> @@ -5826,36 +5826,6 @@ static QualType checkConditionalPointerC
> return ResultTy;
> }
>
> -/// \brief Returns true if QT is quelified-id and implements 'NSObject' and/or
> -/// 'NSCopying' protocols (and nothing else); or QT is an NSObject and optionally
> -/// implements 'NSObject' and/or NSCopying' protocols (and nothing else).
> -static bool isObjCPtrBlockCompatible(Sema &S, ASTContext &C, QualType QT) {
> - if (QT->isObjCIdType())
> - return true;
> -
> - const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
> - if (!OPT)
> - return false;
> -
> - if (ObjCInterfaceDecl *ID = OPT->getInterfaceDecl())
> - if (ID->getIdentifier() != &C.Idents.get("NSObject"))
> - return false;
> -
> - ObjCProtocolDecl* PNSCopying =
> - S.LookupProtocol(&C.Idents.get("NSCopying"), SourceLocation());
> - ObjCProtocolDecl* PNSObject =
> - S.LookupProtocol(&C.Idents.get("NSObject"), SourceLocation());
> -
> - for (auto *Proto : OPT->quals()) {
> - if ((PNSCopying && declaresSameEntity(Proto, PNSCopying)) ||
> - (PNSObject && declaresSameEntity(Proto, PNSObject)))
> - ;
> - else
> - return false;
> - }
> - return true;
> -}
> -
> /// \brief Return the resulting type when the operands are both block pointers.
> static QualType checkConditionalBlockPointerCompatibility(Sema &S,
> ExprResult &LHS,
> @@ -7008,8 +6978,8 @@ Sema::CheckAssignmentConstraints(QualTyp
> }
>
> // Only under strict condition T^ is compatible with an Objective-C pointer.
> - if (RHSType->isBlockPointerType() &&
> - isObjCPtrBlockCompatible(*this, Context, LHSType)) {
> + if (RHSType->isBlockPointerType() &&
> + LHSType->isBlockCompatibleObjCPointerType(Context)) {
> maybeExtendBlockObject(*this, RHS);
> Kind = CK_BlockPointerToObjCPointerCast;
> return Compatible;
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Jul 6 22:57:35 2015
> @@ -959,8 +959,10 @@ ExprResult Sema::BuildObjCDictionaryLite
> LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
> ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
> QIDNSCopying =
> - Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
> - (ObjCProtocolDecl**) PQ,1);
> + Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
> + llvm::makeArrayRef(
> + (ObjCProtocolDecl**) PQ,
> + 1));
> QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
> }
> }
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Jul 6 22:57:35 2015
> @@ -738,6 +738,160 @@ static void diagnoseAndRemoveTypeQualifi
> }
> }
>
> +/// Apply Objective-C type arguments to the given type.
> +static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
> + ArrayRef<ParsedType> typeArgs,
> + SourceRange typeArgsRange) {
> + // We can only apply type arguments to an Objective-C class type.
> + const auto *objcObjectType = type->getAs<ObjCObjectType>();
> + if (!objcObjectType || !objcObjectType->getInterface()) {
> + S.Diag(loc, diag::err_objc_type_args_non_class)
> + << type
> + << typeArgsRange;
> + return type;
> + }
> +
> + // The class type must be parameterized.
> + ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
> + ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
> + if (!typeParams) {
> + S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
> + << objcClass->getDeclName()
> + << FixItHint::CreateRemoval(typeArgsRange);
> + return type;
> + }
> +
> + // The type must not already be specialized.
> + if (objcObjectType->isSpecialized()) {
> + S.Diag(loc, diag::err_objc_type_args_specialized_class)
> + << type
> + << FixItHint::CreateRemoval(typeArgsRange);
> + return type;
> + }
> +
> + // Make sure that we have the right number of type arguments.
> + if (typeArgs.size() != typeParams->size()) {
> + S.Diag(loc, diag::err_objc_type_args_wrong_arity)
> + << (typeArgs.size() < typeParams->size())
> + << objcClass->getDeclName()
> + << (unsigned)typeArgs.size()
> + << (unsigned)typeParams->size();
> + S.Diag(objcClass->getLocation(), diag::note_previous_decl)
> + << objcClass;
> + return type;
> + }
> +
> + // Check the type arguments.
> + SmallVector<QualType, 4> finalTypeArgs;
> + for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
> + TypeSourceInfo *typeArgInfo = nullptr;
> + QualType typeArg = S.GetTypeFromParser(typeArgs[i], &typeArgInfo);
> + finalTypeArgs.push_back(typeArg);
> +
> + // Objective-C object pointer types must be substitutable for the bounds.
> + if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
> + // Retrieve the bound.
> + ObjCTypeParamDecl *typeParam = typeParams->begin()[i];
> + QualType bound = typeParam->getUnderlyingType();
> + const auto *boundObjC = bound->getAs<ObjCObjectPointerType>();
> +
> + // Determine whether the type argument is substitutable for the bound.
> + if (typeArgObjC->isObjCIdType()) {
> + // When the type argument is 'id', the only acceptable type
> + // parameter bound is 'id'.
> + if (boundObjC->isObjCIdType())
> + continue;
> + } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
> + // Otherwise, we follow the assignability rules.
> + continue;
> + }
> +
> + // Diagnose the mismatch.
> + S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
> + diag::err_objc_type_arg_does_not_match_bound)
> + << typeArg << bound << typeParam->getDeclName();
> + S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
> + << typeParam->getDeclName();
> +
> + return type;
> + }
> +
> + // Block pointer types are permitted for unqualified 'id' bounds.
> + if (typeArg->isBlockPointerType()) {
> + // Retrieve the bound.
> + ObjCTypeParamDecl *typeParam = typeParams->begin()[i];
> + QualType bound = typeParam->getUnderlyingType();
> + if (bound->isBlockCompatibleObjCPointerType(S.Context))
> + continue;
> +
> + // Diagnose the mismatch.
> + S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
> + diag::err_objc_type_arg_does_not_match_bound)
> + << typeArg << bound << typeParam->getDeclName();
> + S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
> + << typeParam->getDeclName();
> +
> + return type;
> + }
> +
> + // Dependent types will be checked at instantiation time.
> + if (typeArg->isDependentType()) {
> + continue;
> + }
> +
> + // Diagnose non-id-compatible type arguments.
> + S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
> + diag::err_objc_type_arg_not_id_compatible)
> + << typeArg
> + << typeArgInfo->getTypeLoc().getSourceRange();
> + return type;
> + }
> +
> + // Success. Form the specialized type.
> + return S.Context.getObjCObjectType(type, finalTypeArgs, { });
> +}
> +
> +/// Apply Objective-C protocol qualifiers to the given type.
> +static QualType applyObjCProtocolQualifiers(
> + Sema &S, SourceLocation loc, SourceRange range, QualType type,
> + ArrayRef<ObjCProtocolDecl *> protocols,
> + const SourceLocation *protocolLocs) {
> + ASTContext &ctx = S.Context;
> + if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
> + // FIXME: Check for protocols to which the class type is already
> + // known to conform.
> +
> + return ctx.getObjCObjectType(objT->getBaseType(),
> + objT->getTypeArgsAsWritten(),
> + protocols);
> + }
> +
> + if (type->isObjCObjectType()) {
> + // Silently overwrite any existing protocol qualifiers.
> + // TODO: determine whether that's the right thing to do.
> +
> + // FIXME: Check for protocols to which the class type is already
> + // known to conform.
> + return ctx.getObjCObjectType(type, { }, protocols);
> + }
> +
> + // id<protocol-list>
> + if (type->isObjCIdType()) {
> + type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols);
> + return ctx.getObjCObjectPointerType(type);
> + }
> +
> + // Class<protocol-list>
> + if (type->isObjCClassType()) {
> + type = ctx.getObjCObjectType(ctx.ObjCBuiltinClassTy, { }, protocols);
> + return ctx.getObjCObjectPointerType(type);
> + }
> +
> + S.Diag(loc, diag::err_invalid_protocol_qualifiers)
> + << range;
> + return type;
> +}
> +
> /// \brief Convert the specified declspec to the appropriate type
> /// object.
> /// \param state Specifies the declarator containing the declaration specifier
> @@ -803,9 +957,10 @@ static QualType ConvertDeclSpecToType(Ty
> case DeclSpec::TST_unspecified:
> // "<proto1,proto2>" is an objc qualified ID with a missing id.
> if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
> - Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
> - (ObjCProtocolDecl*const*)PQ,
> - DS.getNumProtocolQualifiers());
> + Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
> + llvm::makeArrayRef(
> + (ObjCProtocolDecl*const*)PQ,
> + DS.getNumProtocolQualifiers()));
> Result = Context.getObjCObjectPointerType(Result);
> break;
> }
> @@ -967,37 +1122,8 @@ static QualType ConvertDeclSpecToType(Ty
> DS.getTypeSpecSign() == 0 &&
> "Can't handle qualifiers on typedef names yet!");
> Result = S.GetTypeFromParser(DS.getRepAsType());
> - if (Result.isNull())
> + if (Result.isNull()) {
> declarator.setInvalidType(true);
> - else if (DeclSpec::ProtocolQualifierListTy PQ
> - = DS.getProtocolQualifiers()) {
> - if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
> - // Silently drop any existing protocol qualifiers.
> - // TODO: determine whether that's the right thing to do.
> - if (ObjT->getNumProtocols())
> - Result = ObjT->getBaseType();
> -
> - if (DS.getNumProtocolQualifiers())
> - Result = Context.getObjCObjectType(Result,
> - (ObjCProtocolDecl*const*) PQ,
> - DS.getNumProtocolQualifiers());
> - } else if (Result->isObjCIdType()) {
> - // id<protocol-list>
> - Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
> - (ObjCProtocolDecl*const*) PQ,
> - DS.getNumProtocolQualifiers());
> - Result = Context.getObjCObjectPointerType(Result);
> - } else if (Result->isObjCClassType()) {
> - // Class<protocol-list>
> - Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
> - (ObjCProtocolDecl*const*) PQ,
> - DS.getNumProtocolQualifiers());
> - Result = Context.getObjCObjectPointerType(Result);
> - } else {
> - S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
> - << DS.getSourceRange();
> - declarator.setInvalidType(true);
> - }
> } else if (S.getLangOpts().OpenCL) {
> if (const AtomicType *AT = Result->getAs<AtomicType>()) {
> const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>();
> @@ -1022,6 +1148,21 @@ static QualType ConvertDeclSpecToType(Ty
> declarator.setInvalidType(true);
> }
> }
> + } else {
> + // Apply Objective-C type arguments.
> + if (DS.hasObjCTypeArgs()) {
> + Result = applyObjCTypeArgs(S, DeclLoc, Result, DS.getObjCTypeArgs(),
> + DS.getObjCTypeArgsRange());
> + }
> +
> + // Apply Objective-C protocol qualifiers.
> + if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
> + Result = applyObjCProtocolQualifiers(
> + S, DeclLoc, DS.getSourceRange(), Result,
> + llvm::makeArrayRef((ObjCProtocolDecl * const *)PQ,
> + DS.getNumProtocolQualifiers()),
> + DS.getProtocolLocs());
> + }
> }
>
> // TypeQuals handled by caller.
> @@ -4138,18 +4279,33 @@ namespace {
> Visit(TL.getBaseLoc());
> }
>
> + // Type arguments.
> + if (TL.getNumTypeArgs() > 0) {
> + assert(TL.getNumTypeArgs() == DS.getObjCTypeArgs().size());
> + TL.setTypeArgsLAngleLoc(DS.getObjCTypeArgsLAngleLoc());
> + TL.setTypeArgsRAngleLoc(DS.getObjCTypeArgsRAngleLoc());
> + for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) {
> + TypeSourceInfo *typeArgInfo = nullptr;
> + (void)Sema::GetTypeFromParser(DS.getObjCTypeArgs()[i], &typeArgInfo);
> + TL.setTypeArgTInfo(i, typeArgInfo);
> + }
> + } else {
> + TL.setTypeArgsLAngleLoc(SourceLocation());
> + TL.setTypeArgsRAngleLoc(SourceLocation());
> + }
> +
> // Protocol qualifiers.
> if (DS.getProtocolQualifiers()) {
> assert(TL.getNumProtocols() > 0);
> assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
> - TL.setLAngleLoc(DS.getProtocolLAngleLoc());
> - TL.setRAngleLoc(DS.getSourceRange().getEnd());
> + TL.setProtocolLAngleLoc(DS.getProtocolLAngleLoc());
> + TL.setProtocolRAngleLoc(DS.getSourceRange().getEnd());
> for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
> TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
> } else {
> assert(TL.getNumProtocols() == 0);
> - TL.setLAngleLoc(SourceLocation());
> - TL.setRAngleLoc(SourceLocation());
> + TL.setProtocolLAngleLoc(SourceLocation());
> + TL.setProtocolRAngleLoc(SourceLocation());
> }
> }
> void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Jul 6 22:57:35 2015
> @@ -5263,11 +5263,15 @@ QualType ASTReader::readTypeRecord(unsig
> case TYPE_OBJC_OBJECT: {
> unsigned Idx = 0;
> QualType Base = readType(*Loc.F, Record, Idx);
> + unsigned NumTypeArgs = Record[Idx++];
> + SmallVector<QualType, 4> TypeArgs;
> + for (unsigned I = 0; I != NumTypeArgs; ++I)
> + TypeArgs.push_back(readType(*Loc.F, Record, Idx));
> unsigned NumProtos = Record[Idx++];
> SmallVector<ObjCProtocolDecl*, 4> Protos;
> for (unsigned I = 0; I != NumProtos; ++I)
> Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
> - return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
> + return Context.getObjCObjectType(Base, TypeArgs, Protos);
> }
>
> case TYPE_OBJC_OBJECT_POINTER: {
> @@ -5646,8 +5650,12 @@ void TypeLocReader::VisitObjCInterfaceTy
> }
> void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
> TL.setHasBaseTypeAsWritten(Record[Idx++]);
> - TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
> - TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
> + TL.setTypeArgsLAngleLoc(ReadSourceLocation(Record, Idx));
> + TL.setTypeArgsRAngleLoc(ReadSourceLocation(Record, Idx));
> + for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
> + TL.setTypeArgTInfo(i, Reader.GetTypeSourceInfo(F, Record, Idx));
> + TL.setProtocolLAngleLoc(ReadSourceLocation(Record, Idx));
> + TL.setProtocolRAngleLoc(ReadSourceLocation(Record, Idx));
> for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
> TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
> }
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Jul 6 22:57:35 2015
> @@ -953,8 +953,7 @@ void ASTDeclReader::VisitObjCInterfaceDe
> ObjCInterfaceDecl::DefinitionData &Data = ID->data();
>
> // Read the superclass.
> - Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
> - Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
> + Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx);
>
> Data.EndLoc = ReadSourceLocation(Record, Idx);
> Data.HasDesignatedInitializers = Record[Idx++];
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Jul 6 22:57:35 2015
> @@ -421,6 +421,9 @@ void ASTTypeWriter::VisitObjCInterfaceTy
>
> void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
> Writer.AddTypeRef(T->getBaseType(), Record);
> + Record.push_back(T->getTypeArgs().size());
> + for (auto TypeArg : T->getTypeArgs())
> + Writer.AddTypeRef(TypeArg, Record);
> Record.push_back(T->getNumProtocols());
> for (const auto *I : T->quals())
> Writer.AddDeclRef(I, Record);
> @@ -648,8 +651,12 @@ void TypeLocWriter::VisitObjCInterfaceTy
> }
> void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
> Record.push_back(TL.hasBaseTypeAsWritten());
> - Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
> - Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
> + Writer.AddSourceLocation(TL.getTypeArgsLAngleLoc(), Record);
> + Writer.AddSourceLocation(TL.getTypeArgsRAngleLoc(), Record);
> + for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
> + Writer.AddTypeSourceInfo(TL.getTypeArgTInfo(i), Record);
> + Writer.AddSourceLocation(TL.getProtocolLAngleLoc(), Record);
> + Writer.AddSourceLocation(TL.getProtocolRAngleLoc(), Record);
> for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
> Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
> }
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Mon Jul 6 22:57:35 2015
> @@ -604,8 +604,7 @@ void ASTDeclWriter::VisitObjCInterfaceDe
> // Write the DefinitionData
> ObjCInterfaceDecl::DefinitionData &Data = D->data();
>
> - Writer.AddDeclRef(D->getSuperClass(), Record);
> - Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
> + Writer.AddTypeSourceInfo(D->getSuperClassTInfo(), Record);
> Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record);
> Record.push_back(Data.HasDesignatedInitializers);
>
>
> Added: cfe/trunk/test/Index/annotate-parameterized-classes.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-parameterized-classes.m?rev=241542&view=auto
> ==============================================================================
> --- cfe/trunk/test/Index/annotate-parameterized-classes.m (added)
> +++ cfe/trunk/test/Index/annotate-parameterized-classes.m Mon Jul 6 22:57:35 2015
> @@ -0,0 +1,42 @@
> + at protocol NSObject
> + at end
> +
> + at interface NSObject
> + at end
> +
> + at interface A<T : id, U : NSObject *> : NSObject
> + at end
> +
> + at interface A<T : id, U : NSObject *> (Cat1)
> + at end
> +
> +typedef A<id<NSObject>, NSObject *> ASpecialization1;
> +
> + at interface B<T : id, U : NSObject *> : A<T, U>
> + at end
> +
> +// RUN: c-index-test -test-annotate-tokens=%s:7:1:9:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-INTERFACE-DECL %s
> +// CHECK-INTERFACE-DECL: Identifier: "T" [7:14 - 7:15] TemplateTypeParameter=T:7:14
> +// FIXME: Should be a type reference
> +// CHECK-INTERFACE-DECL: Identifier: "id" [7:18 - 7:20] TemplateTypeParameter=T:7:14
> +// CHECK-INTERFACE-DECL: Identifier: "U" [7:22 - 7:23] TemplateTypeParameter=U:7:22
> +// FIXME: Should be a class reference
> +// CHECK-INTERFACE-DECL: Identifier: "NSObject" [7:26 - 7:34] TemplateTypeParameter=U:7:22
> +
> +// RUN: c-index-test -test-annotate-tokens=%s:10:1:12:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-CATEGORY-DECL %s
> +// CHECK-CATEGORY-DECL: Identifier: "T" [10:14 - 10:15] TemplateTypeParameter=T:10:14
> +// FIXME: Should be a type reference
> +// CHECK-CATEGORY-DECL: Identifier: "id" [10:18 - 10:20] TemplateTypeParameter=T:10:14
> +// CHECK-CATEGORY-DECL: Identifier: "U" [10:22 - 10:23] TemplateTypeParameter=U:10:22
> +// FIXME: Should be a class reference
> +// CHECK-CATEGORY-DECL: Identifier: "NSObject" [10:26 - 10:34] TemplateTypeParameter=U:10:22
> +
> +// RUN: c-index-test -test-annotate-tokens=%s:13:1:14:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-SPECIALIZATION %s
> +// CHECK-SPECIALIZATION: Identifier: "id" [13:11 - 13:13] TypeRef=id:0:0
> +// CHECK-SPECIALIZATION: Identifier: "NSObject" [13:14 - 13:22] ObjCProtocolRef=NSObject:1:11
> +// CHECK-SPECIALIZATION: Identifier: "NSObject" [13:25 - 13:33] ObjCClassRef=NSObject:4:12
> +
> +// RUN: c-index-test -test-annotate-tokens=%s:15:1:16:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-SUPER %s
> +// CHECK-SUPER: Identifier: "A" [15:40 - 15:41] ObjCSuperClassRef=A:7:12
> +// CHECK-SUPER: Identifier: "T" [15:42 - 15:43] TypeRef=T:15:14
> +// CHECK-SUPER: Identifier: "U" [15:45 - 15:46] TypeRef=U:15:22
>
> Modified: cfe/trunk/test/Index/complete-method-decls.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-method-decls.m?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/test/Index/complete-method-decls.m (original)
> +++ cfe/trunk/test/Index/complete-method-decls.m Mon Jul 6 22:57:35 2015
> @@ -208,8 +208,7 @@ typedef A *MyObjectRef;
>
> // RUN: c-index-test -code-completion-at=%s:85:2 %s | FileCheck -check-prefix=CHECK-CLASSTY %s
> // CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text Class<P1>}{RightParen )}{TypedText meth}
> -// FIXME: It should be "MyObject <P1> *""
> -// CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text A<P1> *}{RightParen )}{TypedText meth2}
> +// CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text MyObject<P1> *}{RightParen )}{TypedText meth2}
> // CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text MyObjectRef}{RightParen )}{TypedText meth3}
>
> // RUN: c-index-test -code-completion-at=%s:93:2 %s | FileCheck -check-prefix=CHECK-NULLABILITY %s
>
> Modified: cfe/trunk/test/PCH/objc_parameterized_classes.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_parameterized_classes.m?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/test/PCH/objc_parameterized_classes.m (original)
> +++ cfe/trunk/test/PCH/objc_parameterized_classes.m Mon Jul 6 22:57:35 2015
> @@ -19,6 +19,8 @@ __attribute__((objc_root_class))
> @interface PC1<T, U : NSObject *> (Cat1)
> @end
>
> +typedef PC1<id, NSObject *> PC1Specialization1;
> +
> #else
>
> @interface PC1<T : NSObject *, // expected-error{{type bound 'NSObject *' for type parameter 'T' conflicts with implicit bound 'id}}
> @@ -27,4 +29,6 @@ __attribute__((objc_root_class))
> // expected-note at 15{{type parameter 'U' declared here}}
> @end
>
> +typedef PC1Specialization1<id, NSObject *> PC1Specialization2; // expected-error{{type arguments cannot be applied to already-specialized class type 'PC1Specialization1' (aka 'PC1<id,NSObject *>')}}
> +
> #endif
>
> Modified: cfe/trunk/test/Parser/objcxx11-protocol-in-template.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-protocol-in-template.mm?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/objcxx11-protocol-in-template.mm (original)
> +++ cfe/trunk/test/Parser/objcxx11-protocol-in-template.mm Mon Jul 6 22:57:35 2015
> @@ -4,12 +4,7 @@
> template<class T> class vector {};
> @protocol P @end
>
> -#if __cplusplus >= 201103L
> - // expected-no-diagnostics
> -#else
> - // expected-error at 14{{a space is required between consecutive right angle brackets}}
> - // expected-error at 15{{a space is required between consecutive right angle brackets}}
> -#endif
> +// expected-no-diagnostics
>
> vector<id<P>> v;
> vector<vector<id<P>>> v2;
>
> Modified: cfe/trunk/test/SemaObjC/interface-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/interface-1.m?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/interface-1.m (original)
> +++ cfe/trunk/test/SemaObjC/interface-1.m Mon Jul 6 22:57:35 2015
> @@ -3,7 +3,7 @@
>
> @interface NSWhatever :
> NSObject // expected-error {{cannot find interface declaration for 'NSObject'}}
> -<NSCopying> // expected-error {{cannot find protocol declaration for 'NSCopying'}}
> +<NSCopying> // expected-error {{no type or protocol named 'NSCopying'}}
> @end
>
>
>
> Modified: cfe/trunk/test/SemaObjC/parameterized_classes.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/parameterized_classes.m?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/parameterized_classes.m (original)
> +++ cfe/trunk/test/SemaObjC/parameterized_classes.m Mon Jul 6 22:57:35 2015
> @@ -1,13 +1,16 @@
> -// RUN: %clang_cc1 %s -verify
> +// RUN: %clang_cc1 -fblocks %s -verify
>
> - at protocol NSObject
> + at protocol NSObject // expected-note{{'NSObject' declared here}}
> + at end
> +
> + at protocol NSCopying // expected-note{{'NSCopying' declared here}}
> @end
>
> __attribute__((objc_root_class))
> @interface NSObject <NSObject> // expected-note{{'NSObject' defined here}}
> @end
>
> - at interface NSString : NSObject
> + at interface NSString : NSObject <NSCopying>
> @end
>
> // --------------------------------------------------------------------------
> @@ -15,13 +18,14 @@ __attribute__((objc_root_class))
> // --------------------------------------------------------------------------
>
> // Parse type parameters with a bound
> - at interface PC1<T, U : NSObject*> : NSObject
> + at interface PC1<T, U : NSObject*> : NSObject // expected-note{{'PC1' declared here}}
> // expected-note at -1{{type parameter 'T' declared here}}
> // expected-note at -2{{type parameter 'U' declared here}}
> +// expected-note at -3{{type parameter 'U' declared here}}
> @end
>
> // Parse a type parameter with a bound that terminates in '>>'.
> - at interface PC2<T : id<NSObject>> : NSObject // expected-error{{a space is required between consecutive right angle brackets (use '> >')}}
> + at interface PC2<T : id<NSObject>> : NSObject
> @end
>
> // Parse multiple type parameters.
> @@ -29,11 +33,11 @@ __attribute__((objc_root_class))
> @end
>
> // Parse multiple type parameters--grammatically ambiguous with protocol refs.
> - at interface PC4<T, U, V> : NSObject
> + at interface PC4<T, U, V> : NSObject // expected-note 2{{'PC4' declared here}}
> @end
>
> // Parse a type parameter list without a superclass.
> - at interface PC5<T : id> // expected-error{{parameterized Objective-C class 'PC5' must have a superclass}}
> + at interface PC5<T : id>
> @end
>
> // Parse a type parameter with name conflicts.
> @@ -92,6 +96,7 @@ __attribute__((objc_root_class))
>
> // Parameterized forward declaration a class that is not parameterized.
> @class NSObject<T>; // expected-error{{forward declaration of non-parameterized class 'NSObject' cannot have type parameters}}
> +// expected-note at -1{{'NSObject' declared here}}
>
> // Parameterized forward declaration preceding the definition (that is
> // not parameterized).
> @@ -190,3 +195,131 @@ void test_PC20_unspecialized(PC20 *pc20)
> ip = [pc20 extMethod: 0]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'X' (aka 'id')}}
> [pc20 extMethod: ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'Y' (aka 'NSObject *')}}
> }
> +
> +// --------------------------------------------------------------------------
> +// Parsing type arguments.
> +// --------------------------------------------------------------------------
> +
> +typedef NSString * ObjCStringRef; // expected-note{{'ObjCStringRef' declared here}}
> +
> +// Type arguments with a mix of identifiers and type-names.
> +typedef PC4<id, NSObject *, NSString *> typeArgs1;
> +
> +// Type arguments with only identifiers.
> +typedef PC4<id, id, id> typeArgs2;
> +
> +// Type arguments with only identifiers; one is ambiguous (resolved as
> +// types).
> +typedef PC4<NSObject, id, id> typeArgs3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}}
> +
> +// Type arguments with only identifiers; one is ambiguous (resolved as
> +// protocol qualifiers).
> +typedef PC4<NSObject, NSCopying> protocolQuals1;
> +
> +// Type arguments and protocol qualifiers.
> +typedef PC4<id, NSObject *, id><NSObject, NSCopying> typeArgsAndProtocolQuals1;
> +
> +// Type arguments and protocol qualifiers in the wrong order.
> +typedef PC4<NSObject, NSCopying><id, NSObject *, id> typeArgsAndProtocolQuals2; // expected-error{{protocol qualifiers must precede type arguments}}
> +
> +// Type arguments and protocol qualifiers (identifiers).
> +typedef PC4<id, NSObject, id><NSObject, NSCopying> typeArgsAndProtocolQuals3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}}
> +
> +// Typo correction: protocol bias.
> +typedef PC4<NSCopying, NSObjec> protocolQuals2; // expected-error{{cannot find protocol declaration for 'NSObjec'; did you mean 'NSObject'?}}
> +
> +// Typo correction: type bias.
> +typedef PC4<id, id, NSObjec> typeArgs4; // expected-error{{unknown class name 'NSObjec'; did you mean 'NSObject'?}}
> +// expected-error at -1{{type argument 'NSObject' must be a pointer (requires a '*')}}
> +
> +// Typo correction: bias set by correction itself to a protocol.
> +typedef PC4<NSObject, NSObject, NSCopyin> protocolQuals3; // expected-error{{cannot find protocol declaration for 'NSCopyin'; did you mean 'NSCopying'?}}
> +
> +// Typo correction: bias set by correction itself to a type.
> +typedef PC4<NSObject, NSObject, ObjCStringref> typeArgs5; // expected-error{{unknown type name 'ObjCStringref'; did you mean 'ObjCStringRef'?}}
> +// expected-error at -1{{type argument 'NSObject' must be a pointer (requires a '*')}}
> +// expected-error at -2{{type argument 'NSObject' must be a pointer (requires a '*')}}
> +
> +// Type/protocol conflict.
> +typedef PC4<NSCopying, ObjCStringRef> typeArgsProtocolQualsConflict1; // expected-error{{angle brackets contain both a type ('ObjCStringRef') and a protocol ('NSCopying')}}
> +
> +// Handling the '>>' in type argument lists.
> +typedef PC4<id<NSCopying>, NSObject *, id<NSObject>> typeArgs6;
> +
> +// --------------------------------------------------------------------------
> +// Checking type arguments.
> +// --------------------------------------------------------------------------
> +
> + at interface PC15<T : id, U : NSObject *, V : id<NSCopying>> : NSObject
> +// expected-note at -1{{type parameter 'V' declared here}}
> +// expected-note at -2{{type parameter 'V' declared here}}
> +// expected-note at -3{{type parameter 'U' declared here}}
> + at end
> +
> +typedef PC4<NSString *> tooFewTypeArgs1; // expected-error{{too few type arguments for class 'PC4' (have 1, expected 3)}}
> +
> +typedef PC4<NSString *, NSString *, NSString *, NSString *> tooManyTypeArgs1; // expected-error{{too many type arguments for class 'PC4' (have 4, expected 3)}}
> +
> +typedef PC15<int (^)(int, int), // block pointers as 'id'
> + NSString *, // subclass
> + NSString *> typeArgs7; // class that conforms to the protocol
> +
> +typedef PC15<NSObject *, NSObject *, id<NSCopying>> typeArgs8;
> +
> +typedef PC15<NSObject *, NSObject *,
> + NSObject *> typeArgs8b; // expected-error{{type argument 'NSObject *' does not satisy the bound ('id<NSCopying>') of type parameter 'V'}}
> +
> +typedef PC15<id,
> + id, // expected-error{{type argument 'id' does not satisy the bound ('NSObject *') of type parameter 'U'}}
> + id> typeArgs9;
> +
> +typedef PC15<id, NSObject *,
> + id> typeArgs10; // expected-error{{type argument 'id' does not satisy the bound ('id<NSCopying>') of type parameter 'V'}}
> +
> +typedef PC15<id,
> + int (^)(int, int), // okay
> + id<NSCopying, NSObject>> typeArgs11;
> +
> +typedef PC15<id, NSString *, int (^)(int, int)> typeArgs12; // okay
> +
> +typedef NSObject<id, id> typeArgs13; // expected-error{{type arguments cannot be applied to non-parameterized class 'NSObject'}}
> +
> +typedef id<id, id> typeArgs14; // expected-error{{type arguments cannot be applied to non-class type 'id'}}
> +
> +typedef PC1<NSObject *, NSString *> typeArgs15;
> +
> +typedef PC1<NSObject *, NSString *><NSCopying> typeArgsAndProtocolQuals4;
> +
> +typedef typeArgs15<NSCopying> typeArgsAndProtocolQuals5;
> +
> +typedef typeArgs15<NSObject *, NSString *> typeArgs16; // expected-error{{type arguments cannot be applied to already-specialized class type 'typeArgs15' (aka 'PC1<NSObject *,NSString *>')}}
> +
> +typedef typeArgs15<NSObject> typeArgsAndProtocolQuals6;
> +
> +void testSpecializedTypePrinting() {
> + int *ip;
> +
> + ip = (typeArgs15*)0; // expected-warning{{'typeArgs15 *' (aka 'PC1<NSObject *,NSString *> *')}}
> + ip = (typeArgsAndProtocolQuals4*)0; // expected-warning{{'typeArgsAndProtocolQuals4 *' (aka 'PC1<NSObject *,NSString *><NSCopying> *')}}
> + ip = (typeArgsAndProtocolQuals5*)0; // expected-warning{{'typeArgsAndProtocolQuals5 *' (aka 'typeArgs15<NSCopying> *')}}
> + ip = (typeArgsAndProtocolQuals6)0; // expected-error{{used type 'typeArgsAndProtocolQuals6' (aka 'typeArgs15<NSObject>')}}
> + ip = (typeArgsAndProtocolQuals6*)0;// expected-warning{{'typeArgsAndProtocolQuals6 *' (aka 'typeArgs15<NSObject> *')}}
> +}
> +
> +// --------------------------------------------------------------------------
> +// Specialized superclasses
> +// --------------------------------------------------------------------------
> + at interface PC21<T : NSObject *> : PC1<T, T>
> + at end
> +
> + at interface PC22<T : NSObject *> : PC1<T> // expected-error{{too few type arguments for class 'PC1' (have 1, expected 2)}}
> + at end
> +
> + at interface PC23<T : NSObject *> : PC1<T, U> // expected-error{{unknown type name 'U'}}
> + at end
> +
> + at interface PC24<T> : PC1<T, T> // expected-error{{type argument 'T' (aka 'id') does not satisy the bound ('NSObject *') of type parameter 'U'}}
> + at end
> +
> + at interface NSFoo : PC1<NSObject *, NSObject *> // okay
> + at end
>
> Added: cfe/trunk/test/SemaObjCXX/parameterized_classes.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/parameterized_classes.mm?rev=241542&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/parameterized_classes.mm (added)
> +++ cfe/trunk/test/SemaObjCXX/parameterized_classes.mm Mon Jul 6 22:57:35 2015
> @@ -0,0 +1,26 @@
> +// RUN: %clang_cc1 -std=c++11 %s -verify
> +
> +// expected-no-diagnostics
> + at protocol NSObject
> + at end
> +
> + at protocol NSCopying
> + at end
> +
> +__attribute__((objc_root_class))
> + at interface NSObject <NSObject>
> + at end
> +
> + at interface NSString : NSObject
> + at end
> +
> +// --------------------------------------------------------------------------
> +// Parsing parameterized classes.
> +// --------------------------------------------------------------------------
> + at interface PC1<T, U, V> : NSObject
> + at end
> +
> +// --------------------------------------------------------------------------
> +// Parsing type arguments.
> +// --------------------------------------------------------------------------
> +typedef PC1<::NSString *, NSString *, id<NSCopying>> typeArgs1;
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Mon Jul 6 22:57:35 2015
> @@ -1021,6 +1021,9 @@ bool CursorVisitor::VisitObjCCategoryDec
> TU)))
> return true;
>
> + if (VisitObjCTypeParamList(ND->getTypeParamList()))
> + return true;
> +
> ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
> for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
> E = ND->protocol_end(); I != E; ++I, ++PL)
> @@ -1080,12 +1083,37 @@ bool CursorVisitor::VisitObjCPropertyDec
> return false;
> }
>
> +bool CursorVisitor::VisitObjCTypeParamList(ObjCTypeParamList *typeParamList) {
> + if (!typeParamList)
> + return false;
> +
> + for (auto *typeParam : *typeParamList) {
> + // Visit the type parameter.
> + if (Visit(MakeCXCursor(typeParam, TU, RegionOfInterest)))
> + return true;
> +
> + // Visit the bound, if it's explicit.
> + if (typeParam->hasExplicitBound()) {
> + if (auto TInfo = typeParam->getTypeSourceInfo()) {
> + if (Visit(TInfo->getTypeLoc()))
> + return true;
> + }
> + }
> + }
> +
> + return false;
> +}
> +
> bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
> if (!D->isThisDeclarationADefinition()) {
> // Forward declaration is treated like a reference.
> return Visit(MakeCursorObjCClassRef(D, D->getLocation(), TU));
> }
>
> + // Objective-C type parameters.
> + if (VisitObjCTypeParamList(D->getTypeParamListAsWritten()))
> + return true;
> +
> // Issue callbacks for super class.
> if (D->getSuperClass() &&
> Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
> @@ -1093,6 +1121,10 @@ bool CursorVisitor::VisitObjCInterfaceDe
> TU)))
> return true;
>
> + if (TypeSourceInfo *SuperClassTInfo = D->getSuperClassTInfo())
> + if (Visit(SuperClassTInfo->getTypeLoc()))
> + return true;
> +
> ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
> for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
> E = D->protocol_end(); I != E; ++I, ++PL)
> @@ -1486,6 +1518,11 @@ bool CursorVisitor::VisitObjCObjectTypeL
> if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
> return true;
>
> + for (unsigned I = 0, N = TL.getNumTypeArgs(); I != N; ++I) {
> + if (Visit(TL.getTypeArgTInfo(I)->getTypeLoc()))
> + return true;
> + }
> +
> for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
> if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
> TU)))
> @@ -4411,7 +4448,12 @@ static enum CXChildVisitResult GetCursor
> *BestCursor = getTypeRefedCallExprCursor(*BestCursor);
> return CXChildVisit_Recurse;
> }
> -
> +
> + // If we already have an Objective-C superclass reference, don't
> + // update it further.
> + if (BestCursor->kind == CXCursor_ObjCSuperClassRef)
> + return CXChildVisit_Break;
> +
> *BestCursor = cursor;
> return CXChildVisit_Recurse;
> }
>
> Modified: cfe/trunk/tools/libclang/CursorVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CursorVisitor.h?rev=241542&r1=241541&r2=241542&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CursorVisitor.h (original)
> +++ cfe/trunk/tools/libclang/CursorVisitor.h Mon Jul 6 22:57:35 2015
> @@ -222,6 +222,7 @@ public:
> bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
> bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
> bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
> + bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
> bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
> bool VisitObjCImplDecl(ObjCImplDecl *D);
> bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list