diff options
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 5 | ||||
-rw-r--r-- | clang/include/clang/AST/RecursiveASTVisitor.h | 4 | ||||
-rw-r--r-- | clang/include/clang/AST/Type.h | 49 | ||||
-rw-r--r-- | clang/include/clang/AST/TypeLoc.h | 83 | ||||
-rw-r--r-- | clang/include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 4 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 38 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 17 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 27 | ||||
-rw-r--r-- | clang/lib/AST/TypeLoc.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 23 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 52 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 17 | ||||
-rw-r--r-- | clang/tools/libclang/CIndex.cpp | 12 |
22 files changed, 411 insertions, 1 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 86a014fd431..0a184bc2e37 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -114,6 +114,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; + mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes; mutable llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; mutable llvm::FoldingSet<SubstTemplateTypeParmPackType> @@ -1328,6 +1329,10 @@ public: ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) const; + + QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef<ObjCProtocolDecl *> protocols, + QualType Canonical = QualType()) const; bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 77decd798ff..a034a0855a1 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1044,6 +1044,8 @@ DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) +DEF_TRAVERSE_TYPE(ObjCTypeParamType, {}) + DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPE(ObjCObjectType, { @@ -1275,6 +1277,8 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(PackExpansionType, { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) +DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {}) + DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPELOC(ObjCObjectType, { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index ed74832c016..54435502c25 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -88,6 +88,7 @@ namespace clang { class ObjCInterfaceDecl; class ObjCProtocolDecl; class ObjCMethodDecl; + class ObjCTypeParamDecl; class UnresolvedUsingTypenameDecl; class Expr; class Stmt; @@ -4752,6 +4753,49 @@ public: } }; +/// Represents a type parameter type in Objective C. It can take +/// a list of protocols. +class ObjCTypeParamType : public Type, + public ObjCProtocolQualifiers<ObjCTypeParamType>, + public llvm::FoldingSetNode { + friend class ASTContext; + friend class ObjCProtocolQualifiers<ObjCTypeParamType>; + + /// 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, + ArrayRef<ObjCProtocolDecl *> protocols); +public: + bool isSugared() const { return true; } + QualType desugar() const { return getCanonicalTypeInternal(); } + + 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<ObjCProtocolDecl *> 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 @@ -4959,6 +5003,11 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorageImpl() { getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); } +inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { + return reinterpret_cast<ObjCProtocolDecl**>( + static_cast<ObjCTypeParamType*>(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 diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 67adf4a638b..5d7770d8054 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -693,6 +693,89 @@ public: TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; +struct ObjCTypeParamTypeLocInfo { + SourceLocation NameLoc; +}; + +/// ProtocolLAngleLoc, ProtocolRAngleLoc, and the source locations for +/// protocol qualifiers are stored after Info. +class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCTypeParamTypeLoc, + ObjCTypeParamType, + ObjCTypeParamTypeLocInfo> { + // SourceLocations are stored after Info, one for each protocol qualifier. + SourceLocation *getProtocolLocArray() const { + return (SourceLocation*)this->getExtraLocalData() + 2; + } + +public: + ObjCTypeParamDecl *getDecl() const { return getTypePtr()->getDecl(); } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceLocation getProtocolLAngleLoc() const { + return getNumProtocols() ? + *((SourceLocation*)this->getExtraLocalData()) : + SourceLocation(); + } + void setProtocolLAngleLoc(SourceLocation Loc) { + *((SourceLocation*)this->getExtraLocalData()) = Loc; + } + + SourceLocation getProtocolRAngleLoc() const { + return getNumProtocols() ? + *((SourceLocation*)this->getExtraLocalData() + 1) : + SourceLocation(); + } + void setProtocolRAngleLoc(SourceLocation Loc) { + *((SourceLocation*)this->getExtraLocalData() + 1) = 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<SourceLocation> getProtocolLocs() const { + return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc); + + unsigned getExtraLocalDataSize() const { + if (!this->getNumProtocols()) return 0; + return this->getNumProtocols() * sizeof(SourceLocation) ; + } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf<SourceLocation>(); + } + SourceRange getLocalSourceRange() const { + SourceLocation start = getNameLoc(); + SourceLocation end = getProtocolRAngleLoc(); + if (end.isInvalid()) return SourceRange(start, start); + return SourceRange(start, end); + } +}; + /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, diff --git a/clang/include/clang/AST/TypeNodes.def b/clang/include/clang/AST/TypeNodes.def index 8caf1024142..27ab21bf7fc 100644 --- a/clang/include/clang/AST/TypeNodes.def +++ b/clang/include/clang/AST/TypeNodes.def @@ -101,6 +101,7 @@ DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) DEPENDENT_TYPE(DependentTemplateSpecialization, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type) +NON_CANONICAL_TYPE(ObjCTypeParam, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ccf466302fc..92d669c7491 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7534,6 +7534,14 @@ public: ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc); + /// Build an Objective-C type parameter type. + QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError = false); + /// Build an Objective-C object pointer type. QualType BuildObjCObjectType(QualType BaseType, SourceLocation Loc, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 510c1c4b9de..32e075b7599 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -902,7 +902,9 @@ namespace clang { /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, /// \brief A PipeType record. - TYPE_PIPE = 43 + TYPE_PIPE = 43, + /// \brief An ObjCTypeParamType record. + TYPE_OBJC_TYPE_PARAM = 44 }; /// \brief The type IDs for special types constructed by semantic diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 697d4c1a526..2ea0f516ea8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1860,6 +1860,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::ObjCTypeParam: + return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); + case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -3941,6 +3944,41 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, return type; } +QualType +ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef<ObjCProtocolDecl *> protocols, + QualType Canonical) 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); + + if (Canonical.isNull()) { + // We canonicalize to the underlying type. + Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (!protocols.empty()) { + // Apply the protocol qualifers. + bool hasError; + Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, + true/*allowOnPointerType*/); + assert(!hasError && "Error when apply protocol qualifier to bound type"); + } + } + + unsigned size = sizeof(ObjCTypeParamType); + size += protocols.size() * sizeof(ObjCProtocolDecl *); + void *mem = Allocate(size, TypeAlignment); + ObjCTypeParamType *newType = new (mem) + ObjCTypeParamType(Decl, Canonical, protocols); + + 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. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 76b495f84d5..7c0a87d0163 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -897,6 +897,23 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::ObjCTypeParam: { + const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1); + const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(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<ObjCObjectType>(T1); const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 67d217e7a66..2f9123cc001 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1839,6 +1839,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, 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"); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 2629aecbe59..556d225612a 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -531,6 +531,18 @@ bool Type::isObjCInertUnsafeUnretainedType() const { } } +ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, + QualType can, + ArrayRef<ObjCProtocolDecl *> protocols) + : Type(ObjCTypeParam, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) +{ + initialize(protocols); +} + ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, @@ -879,6 +891,7 @@ public: } TRIVIAL_TYPE_CLASS(Typedef) + TRIVIAL_TYPE_CLASS(ObjCTypeParam) QualType VisitAdjustedType(const AdjustedType *T) { QualType originalType = recurse(T->getOriginalType()); @@ -3208,6 +3221,20 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { isKindOfTypeAsWritten()); } +void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID, + const ObjCTypeParamDecl *OTPDecl, + ArrayRef<ObjCProtocolDecl *> 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. diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index b5c7271b99f..7b94a0e067b 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -388,6 +388,17 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const { return TypeLoc(); } +void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setNameLoc(Loc); + if (!getNumProtocols()) return; + + 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); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 065a2db0914..6d5e8787c2e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -194,6 +194,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, 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::printObjCInterfaceBefore(const ObjCInterfaceType *T, 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() && diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 5e3e975a778..6016c82d25a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1829,6 +1829,18 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty, 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) { @@ -2481,6 +2493,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); case Type::ObjCObject: return CreateType(cast<ObjCObjectType>(Ty), Unit); + case Type::ObjCTypeParam: + return CreateType(cast<ObjCTypeParamType>(Ty), Unit); case Type::ObjCInterface: return CreateType(cast<ObjCInterfaceType>(Ty), Unit); case Type::Builtin: diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 486eb2a3fa4..cc9bb995f9d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -156,6 +156,8 @@ class CGDebugInfo { 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); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 116079e4a7f..0b9fe29a9ce 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1717,6 +1717,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::Enum: case Type::Elaborated: case Type::TemplateSpecialization: + case Type::ObjCTypeParam: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ce371e023c9..31db29a18e3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3876,6 +3876,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, 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: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 696586af9a2..9ce7f95e555 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1000,6 +1000,29 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false); } +QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError) { + QualType Result = QualType(Decl->getTypeForDecl(), 0); + if (!Protocols.empty()) { + bool HasError; + Result = Context.applyObjCProtocolQualifiers(Result, Protocols, + HasError); + if (HasError) { + Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers) + << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); + if (FailOnError) Result = QualType(); + } + if (FailOnError && Result.isNull()) + return QualType(); + } + + return Result; +} + QualType Sema::BuildObjCObjectType(QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c53505d10ab..ef3740b7177 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -699,6 +699,12 @@ public: QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, SourceLocation Sigil); + QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc); + /// \brief Build an Objective-C object type. /// /// By default, performs semantic analysis when building the object type. @@ -5944,6 +5950,39 @@ TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB, template<typename Derived> QualType +TreeTransform<Derived>::TransformObjCTypeParamType(TypeLocBuilder &TLB, + ObjCTypeParamTypeLoc TL) { + const ObjCTypeParamType *T = TL.getTypePtr(); + ObjCTypeParamDecl *OTP = cast_or_null<ObjCTypeParamDecl>( + 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<ObjCTypeParamTypeLoc>(Result); + if (TL.getNumProtocols()) { + 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<typename Derived> +QualType TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB, ObjCObjectTypeLoc TL) { // Transform base type. @@ -11501,6 +11540,19 @@ TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, } template<typename Derived> +QualType TreeTransform<Derived>::RebuildObjCTypeParamType( + const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef<ObjCProtocolDecl *> Protocols, + ArrayRef<SourceLocation> ProtocolLocs, + SourceLocation ProtocolRAngleLoc) { + return SemaRef.BuildObjCTypeParamType(Decl, + ProtocolLAngleLoc, Protocols, + ProtocolLocs, ProtocolRAngleLoc, + /*FailOnError=*/true); +} + +template<typename Derived> QualType TreeTransform<Derived>::RebuildObjCObjectType( QualType BaseType, SourceLocation Loc, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 96a2693ade1..9b51f3dae52 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5638,6 +5638,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getObjCInterfaceType(ItfD->getCanonicalDecl()); } + case TYPE_OBJC_TYPE_PARAM: { + unsigned Idx = 0; + ObjCTypeParamDecl *Decl + = ReadDeclAs<ObjCTypeParamDecl>(*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.getObjCTypeParamType(Decl, Protos); + } case TYPE_OBJC_OBJECT: { unsigned Idx = 0; QualType Base = readType(*Loc.F, Record, Idx); @@ -6070,6 +6080,15 @@ void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } +void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { + if (TL.getNumProtocols()) { + 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)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index be93ca6f4d2..0866e3a81c6 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -481,6 +481,14 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { 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()); @@ -636,6 +644,14 @@ void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { + if (TL.getNumProtocols()) { + 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()); @@ -1137,6 +1153,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_ATOMIC); RECORD(TYPE_DECAYED); RECORD(TYPE_ADJUSTED); + RECORD(TYPE_OBJC_TYPE_PARAM); RECORD(LOCAL_REDECLARATIONS); RECORD(DECL_TYPEDEF); RECORD(DECL_TYPEALIAS); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 8cbedd0ad80..14eac44d771 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1535,6 +1535,18 @@ bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { 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; |