SemaExprObjC.cpp revision fd5b2ce150185d8d8fc3d7789983bbd2b0b8103f
185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// 285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// 385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// The LLVM Compiler Infrastructure 485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// 585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// This file is distributed under the University of Illinois Open Source 685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// License. See LICENSE.TXT for details. 785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// 885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner//===----------------------------------------------------------------------===// 985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// 1085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// This file implements semantic analysis for Objective-C expressions. 1185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// 1285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner//===----------------------------------------------------------------------===// 1385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 1485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner#include "Sema.h" 1585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner#include "clang/AST/ASTContext.h" 1685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner#include "clang/AST/DeclObjC.h" 17f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#include "clang/AST/ExprObjC.h" 1885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattnerusing namespace clang; 1985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 2085a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, 2185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ExprTy **Strings, 2285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner unsigned NumStrings) { 2385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation AtLoc = AtLocs[0]; 2485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner StringLiteral* S = static_cast<StringLiteral *>(Strings[0]); 2585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (NumStrings > 1) { 2685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // Concatenate objc strings. 2785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]); 2885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation EndLoc = ES->getSourceRange().getEnd(); 2985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner unsigned Length = 0; 3085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner for (unsigned i = 0; i < NumStrings; i++) 3185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Length += static_cast<StringLiteral *>(Strings[i])->getByteLength(); 3285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner char *strBuf = new char [Length]; 3385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner char *p = strBuf; 3485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner bool isWide = false; 3585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner for (unsigned i = 0; i < NumStrings; i++) { 3685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner S = static_cast<StringLiteral *>(Strings[i]); 3785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (S->isWide()) 3885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner isWide = true; 3985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner memcpy(p, S->getStrData(), S->getByteLength()); 4085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner p += S->getByteLength(); 4185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner delete S; 4285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 4385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner S = new StringLiteral(strBuf, Length, 4485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner isWide, Context.getPointerType(Context.CharTy), 4585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner AtLoc, EndLoc); 4685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 4785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 4885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (CheckBuiltinCFStringArgument(S)) 4985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 5085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 51a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (Context.getObjCConstantStringInterface().isNull()) { 5285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // Initialize the constant string interface lazily. This assumes 5385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // the NSConstantString interface is seen in this translation unit. 5485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); 55b327ce02959d4e6224732e1c362e7f8e0688581fSteve Naroff Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, TUScope); 56a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace); 5785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!strIFace) 5885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return Diag(S->getLocStart(), diag::err_undef_interface, 5985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner NSIdent->getName()); 60a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Context.setObjCConstantStringInterface(strIFace); 6185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 62a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType t = Context.getObjCConstantStringInterface(); 6385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner t = Context.getPointerType(t); 6485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCStringLiteral(S, t, AtLoc); 6585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 6685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 6785a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, 6885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation EncodeLoc, 6985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 7085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner TypeTy *Ty, 7185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 7285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType EncodedType = QualType::getFromOpaquePtr(Ty); 7385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 7485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType t = Context.getPointerType(Context.CharTy); 7585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc); 7685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 7785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 7885a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 7985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation AtLoc, 8085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation SelLoc, 8185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 8285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 83a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType t = Context.getObjCSelType(); 8485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc); 8585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 8685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 8785a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 8885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation AtLoc, 8985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation ProtoLoc, 9085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 9185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 92a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId]; 9385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!PDecl) { 9485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName()); 9585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 9685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 9785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 98a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType t = Context.getObjCProtoType(); 9985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (t.isNull()) 10085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 10185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner t = Context.getPointerType(t); 10285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); 10385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 10485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 10585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattnerbool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 106a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *Method) { 10785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner bool anyIncompatibleArgs = false; 10885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 10985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner for (unsigned i = 0; i < NumArgs; i++) { 11085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr *argExpr = Args[i]; 11185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 11285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 11385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType lhsType = Method->getParamDecl(i)->getType(); 11485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType rhsType = argExpr->getType(); 11585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 11685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 117987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner if (lhsType->isArrayType()) 118987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner lhsType = Context.getArrayDecayedType(lhsType); 11985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner else if (lhsType->isFunctionType()) 12085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner lhsType = Context.getPointerType(lhsType); 12185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 122987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner AssignConvertType Result = 123987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner CheckSingleAssignmentConstraints(lhsType, argExpr); 12485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (Args[i] != argExpr) // The expression was converted. 12585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Args[i] = argExpr; // Make sure we store the converted expression. 12685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 12785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner anyIncompatibleArgs |= 12885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 12985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner argExpr, "sending"); 13085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 13185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return anyIncompatibleArgs; 13285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 13385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 13485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ActOnClassMessage - used for both unary and keyword messages. 13585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ArgExprs is optional - if it is present, the number of expressions 13685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// is obtained from Sel.getNumArgs(). 13785a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ActOnClassMessage( 13885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Scope *S, 13985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner IdentifierInfo *receiverName, Selector Sel, 14085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 14185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner{ 14285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(receiverName && "missing receiver class name"); 14385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 14485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 145a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl* ClassDecl = 0; 14685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) { 14785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass(); 14895110968dcd6ba2baef2a23549cd5592f01eca59Steve Naroff if (!ClassDecl) 14995110968dcd6ba2baef2a23549cd5592f01eca59Steve Naroff return Diag(lbrac, diag::error_no_super_class, 15095110968dcd6ba2baef2a23549cd5592f01eca59Steve Naroff CurMethodDecl->getClassInterface()->getName()); 15195110968dcd6ba2baef2a23549cd5592f01eca59Steve Naroff if (CurMethodDecl->isInstance()) { 15285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // Synthesize a cast to the super class. This hack allows us to loosely 15385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // represent super without creating a special expression node. 15485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner IdentifierInfo &II = Context.Idents.get("self"); 15585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false); 156a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType superTy = Context.getObjCInterfaceType(ClassDecl); 15785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner superTy = Context.getPointerType(superTy); 15885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(), 15985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation(), ReceiverExpr.Val); 16085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // We are really in an instance method, redirect. 16185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac, 16285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Args, NumArgs); 16385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 16485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // We are sending a message to 'super' within a class method. Do nothing, 16585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // the receiver will pass through as 'super' (how convenient:-). 16685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else 16785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ClassDecl = getObjCInterfaceDecl(receiverName); 16885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 16985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // FIXME: can ClassDecl ever be null? 170a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *Method = ClassDecl->lookupClassMethod(Sel); 17185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType returnType; 17285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 1739ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff // If we have an implementation in scope, check "private" methods. 1749ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff if (!Method) { 1759ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff if (ObjCImplementationDecl *ImpDecl = 1769ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff ObjCImplementations[ClassDecl->getIdentifier()]) 1779ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff Method = ImpDecl->getClassMethod(Sel); 1789ad23d6f454e64b2ff960721becc5b90dea4d353Steve Naroff } 17985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // Before we give up, check if the selector is an instance method. 18085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) 18185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Method = ClassDecl->lookupInstanceMethod(Sel); 18285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) { 18385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(), 18485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceRange(lbrac, rbrac)); 185a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context.getObjCIdType(); 18685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else { 18785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner returnType = Method->getResultType(); 18885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (Sel.getNumArgs()) { 18985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 19085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 19185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 19285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 19385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCMessageExpr(receiverName, Sel, returnType, Method, 19485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner lbrac, rbrac, ArgExprs, NumArgs); 19585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 19685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 19785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ActOnInstanceMessage - used for both unary and keyword messages. 19885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ArgExprs is optional - if it is present, the number of expressions 19985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// is obtained from Sel.getNumArgs(). 20085a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ActOnInstanceMessage( 20185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ExprTy *receiver, Selector Sel, 20285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 20385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner{ 20485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(receiver && "missing receiver expression"); 20585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 20685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 20785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr *RExpr = static_cast<Expr *>(receiver); 20894a82c930278809a04976ee13013e6e980b18345Steve Naroff QualType receiverType; 20985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType returnType; 210a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *Method = 0; 21194a82c930278809a04976ee13013e6e980b18345Steve Naroff 21294a82c930278809a04976ee13013e6e980b18345Steve Naroff receiverType = RExpr->getType().getCanonicalType().getUnqualifiedType(); 21385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 2146e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner if (receiverType == Context.getObjCIdType().getCanonicalType() || 2156e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner receiverType == Context.getObjCClassType().getCanonicalType()) { 21685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Method = InstanceMethodPool[Sel].Method; 2176e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner if (!Method) 2186e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner Method = FactoryMethodPool[Sel].Method; 21985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) { 22085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 22185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceRange(lbrac, rbrac)); 222a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context.getObjCIdType(); 22385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else { 22485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner returnType = Method->getResultType(); 22585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (Sel.getNumArgs()) 22685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 22785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 22885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 22985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else { 230a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType); 23185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // FIXME (snaroff): checking in this code from Patrick. Needs to be 23285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // revisited. how do we get the ClassDecl from the receiver expression? 23385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!receiverIsQualId) 234fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner while (const PointerType *PTy = receiverType->getAsPointerType()) 235fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner receiverType = PTy->getPointeeType(); 236fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner 237a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl* ClassDecl = 0; 238a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCQualifiedInterfaceType *QIT = 239a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) { 24085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ClassDecl = QIT->getDecl(); 24185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Method = ClassDecl->lookupInstanceMethod(Sel); 24285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) { 24385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // search protocols 24485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 245a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 24685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 24785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner break; 24885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 24985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 25085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) 25185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(lbrac, diag::warn_method_not_found_in_protocol, 25285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner std::string("-"), Sel.getName(), 25385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceRange(lbrac, rbrac)); 25485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 255a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek else if (ObjCQualifiedIdType *QIT = 256a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek dyn_cast<ObjCQualifiedIdType>(receiverType)) { 25785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // search protocols 25885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 259a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 26085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 26185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner break; 26285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 26385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) 26485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(lbrac, diag::warn_method_not_found_in_protocol, 26585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner std::string("-"), Sel.getName(), 26685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceRange(lbrac, rbrac)); 26785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 26885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner else { 269fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType); 270fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner if (OCIReceiver == 0) { 2716e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner Diag(lbrac, diag::error_bad_receiver_type, 2726e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner RExpr->getType().getAsString()); 2731dad5b2f0e5737afe6847b97a18492bab93517d5Fariborz Jahanian return true; 2741dad5b2f0e5737afe6847b97a18492bab93517d5Fariborz Jahanian } 275fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner ClassDecl = OCIReceiver->getDecl(); 27685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // FIXME: consider using InstanceMethodPool, since it will be faster 27785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // than the following method (which can do *many* linear searches). The 27885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // idea is to add class info to InstanceMethodPool... 27985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Method = ClassDecl->lookupInstanceMethod(Sel); 28085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 28185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) { 28285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // If we have an implementation in scope, check "private" methods. 28385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (ClassDecl) 284a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCImplementationDecl *ImpDecl = 285a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCImplementations[ClassDecl->getIdentifier()]) 28685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Method = ImpDecl->getInstanceMethod(Sel); 287c81c8144a661a49d7b9dae8d2080dee2e43186ecChris Lattner // If we still haven't found a method, look in the global pool. This 288c81c8144a661a49d7b9dae8d2080dee2e43186ecChris Lattner // behavior isn't very desirable, however we need it for GCC 28985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // compatibility. 290c81c8144a661a49d7b9dae8d2080dee2e43186ecChris Lattner if (!Method) 291c81c8144a661a49d7b9dae8d2080dee2e43186ecChris Lattner Method = InstanceMethodPool[Sel].Method; 29285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 29385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!Method) { 29485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 29585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceRange(lbrac, rbrac)); 296a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context.getObjCIdType(); 29785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else { 29885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner returnType = Method->getResultType(); 29985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (Sel.getNumArgs()) 30085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 30185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 30285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 30385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 30485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, 30585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ArgExprs, NumArgs); 30685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 307eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 308eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner//===----------------------------------------------------------------------===// 309eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 310eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner//===----------------------------------------------------------------------===// 311eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 312eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 313eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// inheritance hierarchy of 'rProto'. 314eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerstatic bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 315eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *rProto) { 316eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (lProto == rProto) 317eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 318eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); 319eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) 320eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) 321eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 322eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 323eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 324eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 325eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// ClassImplementsProtocol - Checks that 'lProto' protocol 326eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// has been implemented in IDecl class, its super class or categories (if 327eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// lookupCategory is true). 328eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerstatic bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 329eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCInterfaceDecl *IDecl, 33026631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian bool lookupCategory, 33126631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian bool RHSIsQualifiedID = false) { 332eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 333eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 1st, look up the class. 334eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); 335eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { 336eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 337eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 33826631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // This is dubious and is added to be compatible with gcc. 33926631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // In gcc, it is also allowed assigning a protocol-qualified 'id' 34026631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // type to a LHS object when protocol in qualified LHS is in list 34126631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // of protocols in the rhs 'id' object. This IMO, should be a bug. 342fd5b2ce150185d8d8fc3d7789983bbd2b0b8103fTed Kremenek // FIXME: Treat this as an extension, and flag this as an error when 343fd5b2ce150185d8d8fc3d7789983bbd2b0b8103fTed Kremenek // GCC extensions are not enabled. 34426631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian else if (RHSIsQualifiedID && 34526631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian ProtocolCompatibleWithProtocol(protoList[i], lProto)) 34626631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian return true; 347eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 348eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 349eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 2nd, look up the category. 350eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (lookupCategory) 351eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 352eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner CDecl = CDecl->getNextClassCategory()) { 353eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner protoList = CDecl->getReferencedProtocols(); 354eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { 355eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 356eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 357eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 358eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 359eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 360eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 3rd, look up the super class(s) 361eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (IDecl->getSuperClass()) 362eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return 36326631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 36426631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian RHSIsQualifiedID); 365eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 366eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 367eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 368eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 369b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 370b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner/// ObjCQualifiedIDType. 371eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerbool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 372eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner bool compare) { 373eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // Allow id<P..> and an 'id' or void* type in all cases. 374eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (const PointerType *PT = lhs->getAsPointerType()) { 375eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner QualType PointeeTy = PT->getPointeeType(); 376eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 377eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 378eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } else if (const PointerType *PT = rhs->getAsPointerType()) { 379eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner QualType PointeeTy = PT->getPointeeType(); 380eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 381eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 382eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 383eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 384b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 385b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 386b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedInterfaceType *rhsQI = 0; 387289d9f243d9074513368d27eef3b647f72a38324Steve Naroff QualType rtype; 388289d9f243d9074513368d27eef3b647f72a38324Steve Naroff 389b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!rhsQID) { 390b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // Not comparing two ObjCQualifiedIdType's? 391b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!rhs->isPointerType()) return false; 392289d9f243d9074513368d27eef3b647f72a38324Steve Naroff 393289d9f243d9074513368d27eef3b647f72a38324Steve Naroff rtype = rhs->getAsPointerType()->getPointeeType(); 394eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 395b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (rhsQI == 0) { 396289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // If the RHS is a unqualified interface pointer "NSString*", 397289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // make sure we check the class hierarchy. 398b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 399b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCInterfaceDecl *rhsID = IT->getDecl(); 400b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 401b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // when comparing an id<P> on lhs with a static type on rhs, 402b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // see if static class implements all of id's protocols, directly or 403b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // through its super class and categories. 404b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 405b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 406b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 407b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 408b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 409b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 410eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 411eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 412eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 413289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 414eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoI = rhsQI->qual_begin(); 415eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoE = rhsQI->qual_end(); 416289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 417eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoI = rhsQID->qual_begin(); 418eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoE = rhsQID->qual_end(); 419b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } else { 420b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 421eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 422eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 423eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 424eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 425eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner bool match = false; 426eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 427eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // when comparing an id<P> on lhs with a static type on rhs, 428eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // see if static class implements all of id's protocols, directly or 429eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // through its super class and categories. 430b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 431b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *rhsProto = *RHSProtoI; 432b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 433b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 434eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner match = true; 435b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner break; 436eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 437eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 438289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (rhsQI) { 439289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // If the RHS is a qualified interface pointer "NSString<P>*", 440289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // make sure we check the class hierarchy. 441289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 442289d9f243d9074513368d27eef3b647f72a38324Steve Naroff ObjCInterfaceDecl *rhsID = IT->getDecl(); 443289d9f243d9074513368d27eef3b647f72a38324Steve Naroff for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 444289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // when comparing an id<P> on lhs with a static type on rhs, 445289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // see if static class implements all of id's protocols, directly or 446289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // through its super class and categories. 447289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 448289d9f243d9074513368d27eef3b647f72a38324Steve Naroff match = true; 449289d9f243d9074513368d27eef3b647f72a38324Steve Naroff break; 450289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 451289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 452289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 453289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 454eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (!match) 455eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 456eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 457eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 458b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 459b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 460b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 461b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 462b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner assert(rhsQID && "One of the LHS/RHS should be id<x>"); 463eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 464b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!lhs->isPointerType()) 465b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 466b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 467b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner QualType ltype = lhs->getAsPointerType()->getPointeeType(); 468b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCQualifiedInterfaceType *lhsQI = 469b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ltype->getAsObjCQualifiedInterfaceType()) { 470b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 471b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 472b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 473b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner bool match = false; 474b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *lhsProto = *LHSProtoI; 475eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 476eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 477b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 478b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 479eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner match = true; 480eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner break; 481eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 482eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 483b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!match) 484b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 485eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 486b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 487b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 488b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 489b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 490b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // for static type vs. qualified 'id' type, check that class implements 491b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // all of 'id's protocols. 492b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCInterfaceDecl *lhsID = IT->getDecl(); 493b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 494b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 49526631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 496b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 497b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 498b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 499eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 500b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 501eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 502eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 503