diff options
Diffstat (limited to 'clang/lib')
-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 |
14 files changed, 246 insertions, 0 deletions
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); |