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