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:
parent
bd28a85d14
commit
e6be26c8d4
|
@ -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
|
||||
|
|
|
@ -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, {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() &&
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue