More work to integrate newly added ObjCQualifiedClassType into the type system.

This is necessary 'plumbing' to fix <rdar://problem/6497631> Message lookup is sometimes different than gcc's.

llvm-svn: 65248
This commit is contained in:
Steve Naroff 2009-02-21 21:17:01 +00:00
parent 3283ff5088
commit 8487e3e541
6 changed files with 24 additions and 7 deletions

View File

@ -270,7 +270,7 @@ public:
TypeName, Tagged, ExtQual,
TemplateTypeParm, ClassTemplateSpecialization,
ObjCInterface, ObjCQualifiedInterface,
ObjCQualifiedId,
ObjCQualifiedId, ObjCQualifiedClass,
TypeOfExp, TypeOfTyp, // GNU typeof extension.
BlockPointer, // C extension
FixedWidthInt
@ -1758,7 +1758,7 @@ class ObjCQualifiedClassType : public Type,
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.
@ -1785,7 +1785,7 @@ public:
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; }

View File

@ -2408,7 +2408,7 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const {
/// 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.

View File

@ -693,7 +693,8 @@ bool Type::isScalarType() const {
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

View File

@ -290,6 +290,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
}
case Type::ObjCQualifiedId:
case Type::ObjCQualifiedClass:
// Protocols don't influence the LLVM type.
return ConvertTypeRecursive(Context.getObjCIdType());

View File

@ -2734,7 +2734,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// 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);

View File

@ -391,7 +391,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// 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)))
@ -400,6 +401,18 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector 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).