r241542 - Handle Objective-C type arguments.

Douglas Gregor dgregor at apple.com
Wed Jul 8 16:13:35 PDT 2015


Nice catch, thank you!

	- Doug

> On Jul 8, 2015, at 11:32 AM, Justin Bogner <mail at justinbogner.com> wrote:
> 
> Douglas Gregor <dgregor at apple.com <mailto: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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150708/e44fa1c6/attachment.html>


More information about the cfe-commits mailing list