Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -114,6 +114,7 @@ mutable llvm::FoldingSet DependentTypeOfExprTypes; mutable llvm::FoldingSet DependentDecltypeTypes; mutable llvm::FoldingSet TemplateTypeParmTypes; + mutable llvm::FoldingSet ObjCTypeParamTypes; mutable llvm::FoldingSet SubstTemplateTypeParmTypes; mutable llvm::FoldingSet @@ -1309,6 +1310,9 @@ ArrayRef typeArgs, ArrayRef protocols, bool isKindOf) const; + + QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef protocols) const; bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1034,6 +1034,8 @@ DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) +DEF_TRAVERSE_TYPE(ObjCTypeParamType, {}) + DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPE(ObjCObjectType, { @@ -1265,6 +1267,8 @@ DEF_TRAVERSE_TYPELOC(PackExpansionType, { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) +DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {}) + DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPELOC(ObjCObjectType, { Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -88,6 +88,7 @@ class ObjCInterfaceDecl; class ObjCProtocolDecl; class ObjCMethodDecl; + class ObjCTypeParamDecl; class UnresolvedUsingTypenameDecl; class Expr; class Stmt; @@ -4753,6 +4754,49 @@ } }; +/// Represents a type parameter type in Objective C. It can take +/// a list of protocols. +class ObjCTypeParamType : public Type, + public ObjCProtocolQualifiers, + public llvm::FoldingSetNode { + friend class ASTContext; + friend class ObjCProtocolQualifiers; + + /// The number of protocols stored on this type. + unsigned NumProtocols : 6; + + ObjCTypeParamDecl *OTPDecl; + /// The protocols are stored after the ObjCTypeParamType node. In the + /// canonical type, the list of protocols are sorted alphabetically + /// and uniqued. + ObjCProtocolDecl **getProtocolStorageImpl(); + /// Return the number of qualifying protocols in this interface type, + /// or 0 if there are none. + unsigned getNumProtocolsImpl() const { + return NumProtocols; + } + void setNumProtocolsImpl(unsigned N) { + NumProtocols = N; + } + ObjCTypeParamType(const ObjCTypeParamDecl *D, + QualType can, QualType bound, + ArrayRef protocols); +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCTypeParam; + } + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + const ObjCTypeParamDecl *OTPDecl, + ArrayRef protocols); + + ObjCTypeParamDecl *getDecl() const { return OTPDecl; } +}; + /// Represents a class type in Objective C. /// /// Every Objective C type is a combination of a base type, a set of @@ -4960,6 +5004,11 @@ getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); } +inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { + return reinterpret_cast( + static_cast(this)+1); +} + /// Interfaces are the core concept in Objective-C for object oriented design. /// They basically correspond to C++ classes. There are two kinds of interface /// types: normal interfaces like `NSString`, and qualified interfaces, which Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -693,6 +693,74 @@ TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; +struct ObjCTypeParamTypeLocInfo { + SourceLocation ProtocolLAngleLoc; + SourceLocation ProtocolRAngleLoc; +}; + +class ObjCTypeParamTypeLoc : public ConcreteTypeLoc { + // SourceLocations are stored after Info, one for each protocol qualifier. + SourceLocation *getProtocolLocArray() const { + return (SourceLocation*)this->getExtraLocalData(); + } + +public: + ObjCTypeParamDecl *getDecl() const { return getTypePtr()->getDecl(); } + + 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 { + return this->getTypePtr()->getNumProtocols(); + } + + SourceLocation getProtocolLoc(unsigned i) const { + assert(i < getNumProtocols() && "Index is out of bounds!"); + return getProtocolLocArray()[i]; + } + void setProtocolLoc(unsigned i, SourceLocation Loc) { + assert(i < getNumProtocols() && "Index is out of bounds!"); + getProtocolLocArray()[i] = Loc; + } + + ObjCProtocolDecl *getProtocol(unsigned i) const { + assert(i < getNumProtocols() && "Index is out of bounds!"); + return *(this->getTypePtr()->qual_begin() + i); + } + + ArrayRef getProtocolLocs() const { + return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc); + + unsigned getExtraLocalDataSize() const { + return this->getNumProtocols() * sizeof(SourceLocation); + } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + SourceRange getLocalSourceRange() const { + SourceLocation start = getProtocolLAngleLoc(); + SourceLocation end = getProtocolRAngleLoc(); + return SourceRange(start, end); + } +}; + /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc ProtocolLocs, SourceLocation ProtocolRAngleLoc); + /// Build an Objective-C type parameter type. + QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError = false); + /// Build an Objective-C object pointer type. QualType BuildObjCObjectType(QualType BaseType, SourceLocation Loc, Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -902,7 +902,8 @@ /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, /// \brief A PipeType record. - TYPE_PIPE = 43 + TYPE_PIPE = 43, + TYPE_OBJC_TYPE_PARAM = 44 }; /// \brief The type IDs for special types constructed by semantic Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1856,6 +1856,15 @@ case Type::Paren: return getTypeInfo(cast(T)->getInnerType().getTypePtr()); + case Type::ObjCTypeParam: { + const ObjCTypeParamDecl *OTP = cast(T)->getDecl(); + TypeInfo Info = getTypeInfo(OTP->getUnderlyingType().getTypePtr()); + Align = Info.Align; + AlignIsRequired = Info.AlignIsRequired; + Width = Info.Width; + break; + } + case Type::Typedef: { const TypedefNameDecl *Typedef = cast(T)->getDecl(); TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -2709,6 +2718,7 @@ case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Record: case Type::Enum: case Type::UnresolvedUsing: @@ -3867,6 +3877,47 @@ return QualType(T, 0); } +QualType +ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef protocols) const { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + ObjCTypeParamType::Profile(ID, Decl, protocols); + void *InsertPos = nullptr; + if (ObjCTypeParamType *TypeParam = + ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TypeParam, 0); + + // Sort the protocols to generate the canonical representation. + bool protocolsSorted = areSortedAndUniqued(protocols); + QualType canonical; + if (!protocolsSorted) { + // Determine the canonical protocol qualifiers. + ArrayRef canonProtocols; + SmallVector canonProtocolsVec; + + canonProtocolsVec.append(protocols.begin(), protocols.end()); + SortAndUniqueProtocols(canonProtocolsVec); + canonProtocols = canonProtocolsVec; + + canonical = getObjCTypeParamType(Decl, canonProtocols); + + // Regenerate InsertPos. + ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos); + } + + unsigned size = sizeof(ObjCTypeParamType); + size += protocols.size() * sizeof(ObjCProtocolDecl *); + void *mem = Allocate(size, TypeAlignment); + ObjCTypeParamType *newType = new (mem) + ObjCTypeParamType(Decl, canonical, Decl->getUnderlyingType(), protocols); + + Decl->TypeForDecl = newType; + Types.push_back(newType); + ObjCTypeParamTypes.InsertNode(newType, InsertPos); + return QualType(newType, 0); +} + /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's /// protocol list adopt all protocols in QT's qualified-id protocol /// list. @@ -6016,6 +6067,7 @@ return; case Type::Pipe: + case Type::ObjCTypeParam: #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) #define DEPENDENT_TYPE(KIND, BASE) \ @@ -7954,6 +8006,15 @@ return QualType(); } + case Type::ObjCTypeParam: { + const auto *LHSTPT = LHS->getAs(); + const auto *RHSTPT = RHS->getAs(); + QualType mT = mergeTypes(LHSTPT->getDecl()->getUnderlyingType(), + RHSTPT->getDecl()->getUnderlyingType(), + false, Unqualified); + if (mT.isNull()) return QualType(); + return LHS; + } case Type::ObjCObjectPointer: { if (OfBlockPointer) { if (canAssignObjCInterfacesInBlockPointer( Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -897,6 +897,23 @@ break; } + case Type::ObjCTypeParam: { + const ObjCTypeParamType *Obj1 = cast(T1); + const ObjCTypeParamType *Obj2 = cast(T2); + if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), + Obj2->getDecl())) + return false; + + if (Obj1->getNumProtocols() != Obj2->getNumProtocols()) + return false; + for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Obj1->getProtocol(I), + Obj2->getProtocol(I))) + return false; + } + break; + } case Type::ObjCObject: { const ObjCObjectType *Obj1 = cast(T1); const ObjCObjectType *Obj2 = cast(T2); Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -6500,6 +6500,7 @@ case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Pipe: case Type::Atomic: llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -1836,6 +1836,7 @@ case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Atomic: case Type::Pipe: llvm_unreachable("type is illegal as a nested name specifier"); @@ -2900,6 +2901,21 @@ mangleSourceName(T->getDecl()->getIdentifier()); } +void CXXNameMangler::mangleType(const ObjCTypeParamType *T) { + if (!T->qual_empty()) { + // Mangle protocol qualifiers. + SmallString<64> QualStr; + llvm::raw_svector_ostream QualOS(QualStr); + QualOS << "objcproto"; + for (const auto *I : T->quals()) { + StringRef name = I->getName(); + QualOS << name.size() << name; + } + Out << 'U' << QualStr.size() << QualStr; + } + mangleSourceName(T->getDecl()->getIdentifier()); +} + void CXXNameMangler::mangleType(const ObjCObjectType *T) { // Treat __kindof as a vendor extended type qualifier. if (T->isKindOfType()) Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -2313,6 +2313,11 @@ mangleName(T->getDecl()); } +void MicrosoftCXXNameMangler::mangleType(const ObjCTypeParamType *T, Qualifiers, + SourceRange Range) { + mangleType(T->getDecl()->getUnderlyingType(), Range); +} + void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, SourceRange Range) { // We don't allow overloading by different protocol qualification, Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -531,6 +531,19 @@ } } +ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, + QualType can, QualType bound, + ArrayRef protocols) + : Type(ObjCTypeParam, can.isNull() ? QualType(this, 0) : can, + bound->isDependentType(), + bound->isInstantiationDependentType(), + bound->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast(D)) +{ + initialize(protocols); +} + ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef typeArgs, ArrayRef protocols, @@ -879,6 +892,7 @@ } TRIVIAL_TYPE_CLASS(Typedef) + TRIVIAL_TYPE_CLASS(ObjCTypeParam) QualType VisitAdjustedType(const AdjustedType *T) { QualType originalType = recurse(T->getOriginalType()); @@ -3208,6 +3222,20 @@ isKindOfTypeAsWritten()); } +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID, + const ObjCTypeParamDecl *OTPDecl, + ArrayRef protocols) { + ID.AddPointer(OTPDecl); + ID.AddInteger(protocols.size()); + for (auto proto : protocols) + ID.AddPointer(proto); +} + +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getDecl(), + llvm::makeArrayRef(qual_begin(), getNumProtocols())); +} + namespace { /// \brief The cached properties of a type. @@ -3359,6 +3387,8 @@ return Cache::get(cast(T)->getBaseType()); case Type::ObjCObjectPointer: return Cache::get(cast(T)->getPointeeType()); + case Type::ObjCTypeParam: + llvm_unreachable("didn't expect objc type param type here"); case Type::Atomic: return Cache::get(cast(T)->getValueType()); case Type::Pipe: @@ -3443,6 +3473,8 @@ return computeLinkageInfo(cast(T)->getBaseType()); case Type::ObjCObjectPointer: return computeLinkageInfo(cast(T)->getPointeeType()); + case Type::ObjCTypeParam: + llvm_unreachable("didn't expect objc type param type here"); case Type::Atomic: return computeLinkageInfo(cast(T)->getValueType()); case Type::Pipe: @@ -3508,6 +3540,7 @@ case Type::BlockPointer: case Type::MemberPointer: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: return true; // Dependent types that could instantiate to pointer types. Index: lib/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -388,6 +388,14 @@ return TypeLoc(); } +void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setProtocolLAngleLoc(Loc); + setProtocolRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); +} + void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -194,6 +194,7 @@ case Type::DependentName: case Type::DependentTemplateSpecialization: case Type::ObjCObject: + case Type::ObjCTypeParam: case Type::ObjCInterface: case Type::Atomic: case Type::Pipe: @@ -1368,6 +1369,28 @@ void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T, raw_ostream &OS) { } +void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T, + raw_ostream &OS) { + OS << T->getDecl()->getName(); + if (!T->qual_empty()) { + bool isFirst = true; + OS << '<'; + for (const auto *I : T->quals()) { + if (isFirst) + isFirst = false; + else + OS << ','; + OS << I->getName(); + } + OS << '>'; + } + + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T, + raw_ostream &OS) { } + void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T, raw_ostream &OS) { if (T->qual_empty() && T->isUnspecializedAsWritten() && Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -156,6 +156,8 @@ llvm::DIFile *F); /// Get Objective-C object type. llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F); + llvm::DIType *CreateType(const ObjCTypeParamType *Ty, llvm::DIFile *Unit); + llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const LValueReferenceType *Ty, llvm::DIFile *F); Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -1774,6 +1774,18 @@ return getOrCreateType(Ty->getBaseType(), Unit); } +llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty, + llvm::DIFile *Unit) { + // Ignore protocols. + SourceLocation Loc = Ty->getDecl()->getLocation(); + + // Use Typedefs to represent ObjCTypeParamType. + return DBuilder.createTypedef( + getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit), + Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc), + getDeclContextDescriptor(Ty->getDecl())); +} + /// \return true if Getter has the default name for the property PD. static bool hasDefaultGetterName(const ObjCPropertyDecl *PD, const ObjCMethodDecl *Getter) { @@ -2420,6 +2432,8 @@ return CreateType(cast(Ty), Unit); case Type::ObjCObject: return CreateType(cast(Ty), Unit); + case Type::ObjCTypeParam: + return CreateType(cast(Ty), Unit); case Type::ObjCInterface: return CreateType(cast(Ty), Unit); case Type::Builtin: Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -195,6 +195,7 @@ case Type::FunctionNoProto: case Type::Enum: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Pipe: return TEK_Scalar; @@ -1692,6 +1693,7 @@ case Type::Enum: case Type::Elaborated: case Type::TemplateSpecialization: + case Type::ObjCTypeParam: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -576,6 +576,11 @@ break; } + case Type::ObjCTypeParam: + ResultType = ConvertType( + cast(Ty)->getDecl()->getUnderlyingType()); + break; + case Type::ObjCObjectPointer: { // Protocol qualifications do not influence the LLVM type, we just return a // pointer to the underlying interface type. We don't need to worry about Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2742,6 +2742,9 @@ #include "clang/AST/TypeNodes.def" llvm_unreachable("Non-canonical and dependent types shouldn't get here"); + case Type::ObjCTypeParam: + llvm_unreachable("objc type param types shouldn't get here"); + case Type::LValueReference: case Type::RValueReference: llvm_unreachable("References shouldn't get here"); @@ -2959,6 +2962,9 @@ #include "clang/AST/TypeNodes.def" llvm_unreachable("Non-canonical and dependent types shouldn't get here"); + case Type::ObjCTypeParam: + llvm_unreachable("objc type param types shouldn't get here"); + // GCC treats vector types as fundamental types. case Type::Builtin: case Type::Vector: Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -3865,6 +3865,7 @@ case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::Pipe: llvm_unreachable("type class is never variably-modified!"); case Type::Adjusted: Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -2694,6 +2694,7 @@ case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl()); break; Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -4172,6 +4172,11 @@ return false; } +bool UnnamedLocalNoLinkageFinder::VisitObjCTypeParamType( + const ObjCTypeParamType*) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType( const SubstTemplateTypeParmPackType *) { return false; Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -1208,6 +1208,7 @@ case Type::Enum: case Type::ObjCObject: case Type::ObjCInterface: + case Type::ObjCTypeParam: case Type::ObjCObjectPointer: { if (TDF & TDF_SkipNonDependent) return Sema::TDK_Success; @@ -4949,6 +4950,7 @@ case Type::ObjCInterface: case Type::ObjCObject: case Type::ObjCObjectPointer: + case Type::ObjCTypeParam: case Type::UnresolvedUsing: case Type::Pipe: #define TYPE(Class, Base) Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1051,6 +1051,27 @@ return type; } +QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError) { + QualType Result = QualType(Decl->getTypeForDecl(), 0); + if (!Protocols.empty()) { + Result = applyObjCProtocolQualifiers(*this, SourceLocation(), + SourceRange(ProtocolLAngleLoc, + ProtocolRAngleLoc), + Result, Protocols, + ProtocolLocs.data(), + FailOnError); + if (FailOnError && Result.isNull()) + return QualType(); + } + + return Result; +} + QualType Sema::BuildObjCObjectType(QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -699,6 +699,12 @@ QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, SourceLocation Sigil); + QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc); + /// \brief Build an Objective-C object type. /// /// By default, performs semantic analysis when building the object type. @@ -5946,6 +5952,37 @@ template QualType +TreeTransform::TransformObjCTypeParamType(TypeLocBuilder &TLB, + ObjCTypeParamTypeLoc TL) { + const ObjCTypeParamType *T = TL.getTypePtr(); + ObjCTypeParamDecl *OTP = cast_or_null( + getDerived().TransformDecl(T->getDecl()->getLocation(), T->getDecl())); + if (!OTP) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + OTP != T->getDecl()) { + Result = getDerived().RebuildObjCTypeParamType(OTP, + TL.getProtocolLAngleLoc(), + llvm::makeArrayRef(TL.getTypePtr()->qual_begin(), + TL.getNumProtocols()), + TL.getProtocolLocs(), + TL.getProtocolRAngleLoc()); + if (Result.isNull()) + return QualType(); + } + + ObjCTypeParamTypeLoc NewTL = TLB.push(Result); + NewTL.setProtocolLAngleLoc(TL.getProtocolLAngleLoc()); + for (unsigned i = 0, n = TL.getNumProtocols(); i != n; ++i) + NewTL.setProtocolLoc(i, TL.getProtocolLoc(i)); + NewTL.setProtocolRAngleLoc(TL.getProtocolRAngleLoc()); + return Result; +} + +template +QualType TreeTransform::TransformObjCObjectType(TypeLocBuilder &TLB, ObjCObjectTypeLoc TL) { // Transform base type. @@ -11489,6 +11526,19 @@ } template +QualType TreeTransform::RebuildObjCTypeParamType( + const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc) { + return SemaRef.BuildObjCTypeParamType(Decl, + ProtocolLAngleLoc, Protocols, + ProtocolLocs, ProtocolRAngleLoc, + /*FailOnError=*/true); +} + +template QualType TreeTransform::RebuildObjCObjectType( QualType BaseType, SourceLocation Loc, Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5542,6 +5542,16 @@ return Context.getObjCInterfaceType(ItfD->getCanonicalDecl()); } + case TYPE_OBJC_TYPE_PARAM: { + unsigned Idx = 0; + ObjCTypeParamDecl *Decl + = ReadDeclAs(*Loc.F, Record, Idx); + unsigned NumProtos = Record[Idx++]; + SmallVector Protos; + for (unsigned I = 0; I != NumProtos; ++I) + Protos.push_back(ReadDeclAs(*Loc.F, Record, Idx)); + return Context.getObjCTypeParamType(Decl, Protos); + } case TYPE_OBJC_OBJECT: { unsigned Idx = 0; QualType Base = readType(*Loc.F, Record, Idx); @@ -5940,6 +5950,13 @@ void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } +void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { + 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)); +} + void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { TL.setHasBaseTypeAsWritten(Record[Idx++]); TL.setTypeArgsLAngleLoc(ReadSourceLocation(Record, Idx)); Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -450,6 +450,14 @@ Code = TYPE_OBJC_INTERFACE; } +void ASTTypeWriter::VisitObjCTypeParamType(const ObjCTypeParamType *T) { + Record.AddDeclRef(T->getDecl()); + Record.push_back(T->getNumProtocols()); + for (const auto *I : T->quals()) + Record.AddDeclRef(I); + Code = TYPE_OBJC_TYPE_PARAM; +} + void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { Record.AddTypeRef(T->getBaseType()); Record.push_back(T->getTypeArgsAsWritten().size()); @@ -587,6 +595,12 @@ void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { + Record.AddSourceLocation(TL.getProtocolLAngleLoc()); + Record.AddSourceLocation(TL.getProtocolRAngleLoc()); + for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) + Record.AddSourceLocation(TL.getProtocolLoc(i)); +} void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { Record.AddSourceLocation(TL.getTypeofLoc()); Record.AddSourceLocation(TL.getLParenLoc()); @@ -1066,6 +1080,7 @@ RECORD(TYPE_ATOMIC); RECORD(TYPE_DECAYED); RECORD(TYPE_ADJUSTED); + RECORD(TYPE_OBJC_TYPE_PARAM); RECORD(LOCAL_REDECLARATIONS); RECORD(DECL_TYPEDEF); RECORD(DECL_TYPEALIAS); Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1534,6 +1534,18 @@ return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)); } +bool CursorVisitor::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { + if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getLocStart(), TU))) + return true; + for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { + if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I), + TU))) + return true; + } + + return false; +} + bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc())) return true;