TypeName, Tagged, ExtQual,
TemplateTypeParm, ClassTemplateSpecialization,
ObjCInterface, ObjCQualifiedInterface,
- ObjCQualifiedId,
+ ObjCQualifiedId, ObjCQualifiedClass,
TypeOfExp, TypeOfTyp, // GNU typeof extension.
BlockPointer, // C extension
FixedWidthInt
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
ObjCQualifiedClassType(ObjCProtocolDecl **Protos, unsigned NumP)
- : Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
+ : Type(ObjCQualifiedClass, QualType()/*these are always canonical*/,
/*Dependent=*/false),
Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these.
ObjCProtocolDecl **protocols, unsigned NumProtocols);
static bool classof(const Type *T) {
- return T->getTypeClass() == ObjCQualifiedId;
+ return T->getTypeClass() == ObjCQualifiedClass;
}
static bool classof(const ObjCQualifiedClassType *) { return true; }
/// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
/// ID type).
bool ASTContext::isObjCObjectPointerType(QualType Ty) const {
- if (Ty->isObjCQualifiedIdType())
+ if (Ty->isObjCQualifiedIdType() || Ty->isObjCQualifiedClassType())
return true;
// Blocks are objects.
isa<BlockPointerType>(CanonicalType) ||
isa<MemberPointerType>(CanonicalType) ||
isa<ComplexType>(CanonicalType) ||
- isa<ObjCQualifiedIdType>(CanonicalType);
+ isa<ObjCQualifiedIdType>(CanonicalType) ||
+ isa<ObjCQualifiedClassType>(CanonicalType);
}
/// \brief Determines whether the type is a C++ aggregate type or C
}
case Type::ObjCQualifiedId:
+ case Type::ObjCQualifiedClass:
// Protocols don't influence the LLVM type.
return ConvertTypeRecursive(Context.getObjCIdType());
// C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant.
- if ((lhsType->isPointerType() || lhsType->isObjCQualifiedIdType() ||
+ if ((lhsType->isPointerType() ||
+ lhsType->isObjCQualifiedIdType() ||
+ lhsType->isObjCQualifiedClassType() ||
lhsType->isBlockPointerType())
&& rExpr->isNullPointerConstant(Context)) {
ImpCastExprToType(rExpr, lhsType);
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
if (ObjCQualifiedIdType *QIT = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) {
- // Search protocols
+ // Search protocols for instance methods.
+ ReceiverCType.dump();
for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
if (!Method)
Diag(lbrac, diag::warn_method_not_found_in_protocol)
<< Sel << RExpr->getSourceRange();
+ // Check for GCC extension "Class<foo>".
+ } else if (ObjCQualifiedClassType *QIT =
+ dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) {
+ // Search protocols for class methods.
+ for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
+ ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
+ if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
+ break;
+ }
+ if (!Method)
+ Diag(lbrac, diag::warn_method_not_found_in_protocol)
+ << Sel << RExpr->getSourceRange();
} else if (const ObjCInterfaceType *OCIReceiver =
ReceiverCType->getAsPointerToObjCInterfaceType()) {
// We allow sending a message to a pointer to an interface (an object).