ObjectiveC generics: Add ObjCTypeParamType in the type system.

We also need to add ObjCTypeParamTypeLoc. ObjCTypeParamType supports the
representation of "T <protocol>" where T is a type parameter. Before this,
we use TypedefType to represent the type parameter for ObjC.

ObjCTypeParamType has "ObjCTypeParamDecl *OTPDecl" and it extends from
ObjCProtocolQualifiers. It is a non-canonical type and is canonicalized
to the underlying type with the protocol qualifiers.

rdar://24619481
rdar://25060179

Differential Revision: http://reviews.llvm.org/D23079

llvm-svn: 281355
This commit is contained in:
Manman Ren 2016-09-13 17:25:08 +00:00
parent bd28a85d14
commit e6be26c8d4
22 changed files with 411 additions and 1 deletions

View File

@ -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

View File

@ -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, {

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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");

View File

@ -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.

View File

@ -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);

View File

@ -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() &&

View File

@ -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:

View File

@ -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);

View File

@ -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:

View File

@ -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:

View File

@ -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,

View File

@ -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.
@ -5942,6 +5948,39 @@ TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
return TL.getType();
}
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,
@ -11500,6 +11539,19 @@ TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
getDerived().getBaseEntity());
}
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,

View File

@ -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));

View File

@ -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);

View File

@ -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;