SemaExprObjC.cpp revision 8e2945ad9104f0ce4928c386faf458b6b83d9060
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" 1839c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner#include "llvm/ADT/SmallString.h" 1985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattnerusing namespace clang; 2085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 2185a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, 2239c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner ExprTy **strings, 2385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner unsigned NumStrings) { 2439c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings); 2539c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner 26f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner // Most ObjC strings are formed out of a single piece. However, we *can* 27f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner // have strings formed out of multiple @ strings with multiple pptokens in 28f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one 29f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner // StringLiteral for ObjCStringLiteral to hold onto. 3039c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner StringLiteral *S = Strings[0]; 31f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner 32f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner // If we have a multi-part string, merge it all together. 33f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner if (NumStrings != 1) { 3485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // Concatenate objc strings. 3539c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner llvm::SmallString<128> StrBuf; 3639c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner llvm::SmallVector<SourceLocation, 8> StrLocs; 37726e168dc09fb23f53c7b004f8e919421ee91806Chris Lattner 38726e168dc09fb23f53c7b004f8e919421ee91806Chris Lattner for (unsigned i = 0; i != NumStrings; ++i) { 3939c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner S = Strings[i]; 4039c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner 4139c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // ObjC strings can't be wide. 42f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner if (S->isWide()) { 43f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) 44f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner << S->getSourceRange(); 45f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner return true; 46f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner } 47f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner 4839c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // Get the string data. 4939c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength()); 5039c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner 5139c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // Get the locations of the string tokens. 5239c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner StrLocs.append(S->tokloc_begin(), S->tokloc_end()); 5339c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner 5439c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // Free the temporary string. 558189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek S->Destroy(Context); 5685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 5739c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner 5839c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // Create the aggregate string with the appropriate content and location 5939c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner // information. 6039c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false, 612085fd6cd22ec5c268175251db10d7c60caf7aaaChris Lattner Context.getPointerType(Context.CharTy), 6239c28bbbf235533e9ae7d06fb9b13371dfcc542dChris Lattner &StrLocs[0], StrLocs.size()); 6385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 6485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 65690398188ea5b428f06aa13c7d4ce6eb741ad4f9Chris Lattner // Verify that this composite string is acceptable for ObjC strings. 66690398188ea5b428f06aa13c7d4ce6eb741ad4f9Chris Lattner if (CheckObjCString(S)) 6785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 68a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner 69a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner // Initialize the constant string interface lazily. This assumes 70a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner // the NSConstantString interface is seen in this translation unit. 71a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner QualType Ty = Context.getObjCConstantStringInterface(); 72a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner if (!Ty.isNull()) { 73a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Ty = Context.getPointerType(Ty); 7413fd7e5111032f54b538dd66d035b0ccc1f82467Chris Lattner } else { 75a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); 76a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner NamedDecl *IF = LookupName(TUScope, NSIdent, LookupOrdinaryName); 77a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { 78a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Context.setObjCConstantStringInterface(StrIF); 79a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Ty = Context.getObjCConstantStringInterface(); 80a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Ty = Context.getPointerType(Ty); 81a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner } else { 82a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner // If there is no NSConstantString interface defined then treat constant 83a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner // strings as untyped objects and let the runtime figure it out later. 84a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Ty = Context.getObjCIdType(); 85a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner } 8613fd7e5111032f54b538dd66d035b0ccc1f82467Chris Lattner } 87a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner 88f4b136fb40aeedeaaa6ce7cdff22f375eb76c47bChris Lattner return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]); 8985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 9085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 9185a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, 9285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation EncodeLoc, 9385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 94a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner TypeTy *ty, 9585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 96a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner QualType EncodedType = QualType::getFromOpaquePtr(ty); 9785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 98eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner std::string Str; 99eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner Context.getObjCEncodingForType(EncodedType, Str); 100eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner 101eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner // The type of @encode is the same as the type of the corresponding string, 102eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner // which is an array type. 103eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner QualType StrTy = Context.CharTy; 104eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). 105eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner if (getLangOptions().CPlusPlus) 106eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner StrTy.addConst(); 107eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), 108eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner ArrayType::Normal, 0); 109eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner 110eaf2bb89eb2aad3b80673de30febe52df43c10ecChris Lattner return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc); 11185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 11285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 11385a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 11485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation AtLoc, 11585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation SelLoc, 11685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 11785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 118a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner QualType Ty = Context.getObjCSelType(); 119a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); 12085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 12185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 12285a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 12385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation AtLoc, 12485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation ProtoLoc, 12585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation LParenLoc, 12685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner SourceLocation RParenLoc) { 127a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId]; 12885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (!PDecl) { 1293c73c41cefcfe76f36b7bed72c9f1ec195490951Chris Lattner Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; 13085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 13185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 13285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 133a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner QualType Ty = Context.getObjCProtoType(); 134a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner if (Ty.isNull()) 13585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return true; 136a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner Ty = Context.getPointerType(Ty); 137a0af1fe67da29343cd182c51cd48d91b740ecef2Chris Lattner return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); 13885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 13985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 14091e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbarbool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 14191e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar Selector Sel, ObjCMethodDecl *Method, 142077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner bool isClassMessage, 143637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar SourceLocation lbrac, SourceLocation rbrac, 144637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar QualType &ReturnType) { 145637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar if (!Method) { 1466660c8a4cc2115929d92be83bbc54c307002a321Daniel Dunbar // Apply default argument promotion as for (C99 6.5.2.2p6). 1476660c8a4cc2115929d92be83bbc54c307002a321Daniel Dunbar for (unsigned i = 0; i != NumArgs; i++) 1486660c8a4cc2115929d92be83bbc54c307002a321Daniel Dunbar DefaultArgumentPromotion(Args[i]); 1496660c8a4cc2115929d92be83bbc54c307002a321Daniel Dunbar 150077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : 151077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner diag::warn_inst_method_not_found; 152077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Diag(lbrac, DiagID) 153077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner << Sel << isClassMessage << SourceRange(lbrac, rbrac); 154637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar ReturnType = Context.getObjCIdType(); 155637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar return false; 156637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar } 157077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner 158077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner ReturnType = Method->getResultType(); 159637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar 16091e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar unsigned NumNamedArgs = Sel.getNumArgs(); 16191e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); 16291e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar 16385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner bool anyIncompatibleArgs = false; 16491e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar for (unsigned i = 0; i < NumNamedArgs; i++) { 16585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr *argExpr = Args[i]; 16685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 16785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 16889951a86b594513c2a013532ed45d197413b1087Chris Lattner QualType lhsType = Method->param_begin()[i]->getType(); 16985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType rhsType = argExpr->getType(); 17085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 17185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 172987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner if (lhsType->isArrayType()) 173987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner lhsType = Context.getArrayDecayedType(lhsType); 17485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner else if (lhsType->isFunctionType()) 17585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner lhsType = Context.getPointerType(lhsType); 17685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 177987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner AssignConvertType Result = 178987798ad1d5db2a8ec26cd5bbe434b35ad32659cChris Lattner CheckSingleAssignmentConstraints(lhsType, argExpr); 17985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner if (Args[i] != argExpr) // The expression was converted. 18085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Args[i] = argExpr; // Make sure we store the converted expression. 18185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 18285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner anyIncompatibleArgs |= 18385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 18485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner argExpr, "sending"); 18585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 18691e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar 18791e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar // Promote additional arguments to variadic methods. 18891e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar if (Method->isVariadic()) { 189dce5e2cabf07ff25eb4d9e1859c0a21c69f588d2Anders Carlsson for (unsigned i = NumNamedArgs; i < NumArgs; ++i) 190dce5e2cabf07ff25eb4d9e1859c0a21c69f588d2Anders Carlsson DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); 19191e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar } else { 19291e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar // Check for extra arguments to non-variadic methods. 19391e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar if (NumArgs != NumNamedArgs) { 19491e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar Diag(Args[NumNamedArgs]->getLocStart(), 195fa25bbb351f4fdd977f51254119cdfc2b525ce90Chris Lattner diag::err_typecheck_call_too_many_args) 1962c21a073525cdfa68e4439b7af551385dc2796abChris Lattner << 2 /*method*/ << Method->getSourceRange() 197fa25bbb351f4fdd977f51254119cdfc2b525ce90Chris Lattner << SourceRange(Args[NumNamedArgs]->getLocStart(), 198fa25bbb351f4fdd977f51254119cdfc2b525ce90Chris Lattner Args[NumArgs-1]->getLocEnd()); 19991e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar } 20091e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar } 20191e19b2029447e75d2c7730ff888cc396874685bDaniel Dunbar 20285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner return anyIncompatibleArgs; 20385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 20485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 205f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff// Helper method for ActOnClassMethod/ActOnInstanceMethod. 206f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff// Will search "local" class/category implementations for a method decl. 207f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff// Returns 0 if no method is found. 208f1afaf6fe2d94ab265299853f288b676694f7554Steve NaroffObjCMethodDecl *Sema::LookupPrivateMethod(Selector Sel, 209f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff ObjCInterfaceDecl *ClassDecl) { 210f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff ObjCMethodDecl *Method = 0; 211f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff 212f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff if (ObjCImplementationDecl *ImpDecl = 213f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff ObjCImplementations[ClassDecl->getIdentifier()]) 214f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff Method = ImpDecl->getClassMethod(Sel); 215f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff 216f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff // Look through local category implementations associated with the class. 217f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff if (!Method) { 218f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { 219f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) 220f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff Method = ObjCCategoryImpls[i]->getClassMethod(Sel); 221f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff } 222f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff } 223f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff return Method; 224f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff} 225f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff 22685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ActOnClassMessage - used for both unary and keyword messages. 22785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ArgExprs is optional - if it is present, the number of expressions 22885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// is obtained from Sel.getNumArgs(). 22985a932e26f3c3faae6bad639a6d32e92794dfda9Chris LattnerSema::ExprResult Sema::ActOnClassMessage( 23085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Scope *S, 23185a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner IdentifierInfo *receiverName, Selector Sel, 232ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson SourceLocation lbrac, SourceLocation receiverLoc, 233ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson SourceLocation selectorLoc, SourceLocation rbrac, 2345cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff ExprTy **Args, unsigned NumArgs) 23585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner{ 23685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(receiverName && "missing receiver class name"); 23785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 23885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 239a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl* ClassDecl = 0; 240fc93d52ada07d52de0ad4fd051b6a08e21d421ffSteve Naroff bool isSuper = false; 241fc93d52ada07d52de0ad4fd051b6a08e21d421ffSteve Naroff 2428469265156c6344fa1100a6a7bf6349acc187d9fChris Lattner if (receiverName->isStr("super")) { 2435cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff if (getCurMethodDecl()) { 2445cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff isSuper = true; 2454b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface(); 2464b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian if (!OID) 2474b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian return Diag(lbrac, diag::error_no_super_class_message) 2484b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian << getCurMethodDecl()->getDeclName(); 2494b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian ClassDecl = OID->getSuperClass(); 2505cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff if (!ClassDecl) 2514b1e275eb743b46cd10153bb58743d89af7242eaFariborz Jahanian return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName(); 252f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (getCurMethodDecl()->isInstanceMethod()) { 2535cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff QualType superTy = Context.getObjCInterfaceType(ClassDecl); 2545cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff superTy = Context.getPointerType(superTy); 2558189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(), 2568189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek superTy); 2575cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // We are really in an instance method, redirect. 258ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 259ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson selectorLoc, rbrac, Args, NumArgs); 2605cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff } 2615cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // We are sending a message to 'super' within a class method. Do nothing, 2625cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // the receiver will pass through as 'super' (how convenient:-). 2635cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff } else { 2645cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // 'super' has been used outside a method context. If a variable named 2655cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // 'super' has been declared, redirect. If not, produce a diagnostic. 26647b9a1ca55e61e37f5a368740e29de190345acc6Douglas Gregor NamedDecl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); 2675cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl); 2685cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff if (VD) { 2698189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(), 2708189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek receiverLoc); 2715cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff // We are really in an instance method, redirect. 272ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 273ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson selectorLoc, rbrac, Args, NumArgs); 2745cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff } 27508631c5fa053867146b5ee8be658c229f6bf127cChris Lattner return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName; 2765cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022Steve Naroff } 27785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } else 27885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner ClassDecl = getObjCInterfaceDecl(receiverName); 27985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 2807c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff // The following code allows for the following GCC-ism: 281cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // 282cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // typedef XCElementDisplayRect XCElementGraphicsRect; 283cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // 284cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // @implementation XCRASlice 285cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // - whatever { // Note that XCElementGraphicsRect is a typedef name. 286cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; 287cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // } 288cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff // 2897c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff // If necessary, the following lookup could move to getObjCInterfaceDecl(). 2907c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff if (!ClassDecl) { 29147b9a1ca55e61e37f5a368740e29de190345acc6Douglas Gregor NamedDecl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); 2927c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) { 2937c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff const ObjCInterfaceType *OCIT; 2947c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType(); 295ebff1fed660fac9c50a7b7571da797bb489254a4Fariborz Jahanian if (!OCIT) 296ebff1fed660fac9c50a7b7571da797bb489254a4Fariborz Jahanian return Diag(receiverLoc, diag::err_invalid_receiver_to_message); 297ebff1fed660fac9c50a7b7571da797bb489254a4Fariborz Jahanian ClassDecl = OCIT->getDecl(); 2987c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff } 2997c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff } 3007c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff assert(ClassDecl && "missing interface declaration"); 301cb28be6e82809f9f514585ac2692fa04bb56978aSteve Naroff ObjCMethodDecl *Method = 0; 30285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType returnType; 3037c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff Method = ClassDecl->lookupClassMethod(Sel); 3047c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff 3057c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff // If we have an implementation in scope, check "private" methods. 306f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff if (!Method) 307f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff Method = LookupPrivateMethod(Sel, ClassDecl); 308f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff 3097c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff // Before we give up, check if the selector is an instance method. 3107c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff if (!Method) 3117c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff Method = ClassDecl->lookupInstanceMethod(Sel); 3127c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff 31348f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 31448f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor return true; 31559843ad8835d497cd3c17ff91aa039e31d607791Anders Carlsson 316077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true, 317637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar lbrac, rbrac, returnType)) 318637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar return true; 3194df728e368fa1f65ffc57572fed613dcca5b4fe8Ted Kremenek 3204df728e368fa1f65ffc57572fed613dcca5b4fe8Ted Kremenek // If we have the ObjCInterfaceDecl* for the class that is receiving 3214df728e368fa1f65ffc57572fed613dcca5b4fe8Ted Kremenek // the message, use that to construct the ObjCMessageExpr. Otherwise 3224df728e368fa1f65ffc57572fed613dcca5b4fe8Ted Kremenek // pass on the IdentifierInfo* for the class. 323fc93d52ada07d52de0ad4fd051b6a08e21d421ffSteve Naroff // FIXME: need to do a better job handling 'super' usage within a class 324fc93d52ada07d52de0ad4fd051b6a08e21d421ffSteve Naroff // For now, we simply pass the "super" identifier through (which isn't 325fc93d52ada07d52de0ad4fd051b6a08e21d421ffSteve Naroff // consistent with instance methods. 3267c778f1c549a8ae95d50a819fd537df78da16426Steve Naroff if (isSuper) 3278189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method, 3288189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek lbrac, rbrac, ArgExprs, NumArgs); 3294df728e368fa1f65ffc57572fed613dcca5b4fe8Ted Kremenek else 3308189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method, 3318189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek lbrac, rbrac, ArgExprs, NumArgs); 33285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 33385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 33485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ActOnInstanceMessage - used for both unary and keyword messages. 33585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// ArgExprs is optional - if it is present, the number of expressions 33685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner// is obtained from Sel.getNumArgs(). 3371565e0364b05d163640dd2b6feed43bae67df4fdChris LattnerSema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, 338b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner SourceLocation lbrac, 339ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson SourceLocation receiverLoc, 340b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner SourceLocation rbrac, 341b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner ExprTy **Args, unsigned NumArgs) { 34285a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner assert(receiver && "missing receiver expression"); 34385a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner 34485a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 34585a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner Expr *RExpr = static_cast<Expr *>(receiver); 34685a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner QualType returnType; 34794a82c930278809a04976ee13013e6e980b18345Steve Naroff 348b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner QualType ReceiverCType = 349b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner Context.getCanonicalType(RExpr->getType()).getUnqualifiedType(); 35087d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff 35187d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff // Handle messages to 'super'. 352279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff if (isa<ObjCSuperExpr>(RExpr)) { 35387d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff ObjCMethodDecl *Method = 0; 35487d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 35587d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff // If we have an interface in scope, check 'super' methods. 35687d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 35787d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) 35887d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff Method = SuperDecl->lookupInstanceMethod(Sel); 35987d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff } 360ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson 36148f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 36248f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor return true; 36359843ad8835d497cd3c17ff91aa039e31d607791Anders Carlsson 364077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 36587d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff lbrac, rbrac, returnType)) 36687d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff return true; 3678189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 3688189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek rbrac, ArgExprs, NumArgs); 36987d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff } 37087d3ef08d892df8264bd51adb6ddd4a22422cd29Steve Naroff 371fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner // Handle messages to id. 3726c4088e5fc0ce98bf3213d47f6f38bfbfa20c813Steve Naroff if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) || 3736c4088e5fc0ce98bf3213d47f6f38bfbfa20c813Steve Naroff ReceiverCType->getAsBlockPointerType()) { 374037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( 375037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff Sel, SourceRange(lbrac,rbrac)); 3766e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner if (!Method) 3776e10a08fe0427ab34c463dd59d9c0997d4f72170Chris Lattner Method = FactoryMethodPool[Sel].Method; 378077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 379637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar lbrac, rbrac, returnType)) 380637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar return true; 3818189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 3828189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek rbrac, ArgExprs, NumArgs); 383fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner } 384fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner 385fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner // Handle messages to Class. 386b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { 3872b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner ObjCMethodDecl *Method = 0; 3886562fdad21432377f0cc5e0c627c28f0c85df4ddChris Lattner if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 389d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { 390d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff // First check the public methods in the class interface. 391d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff Method = ClassDecl->lookupClassMethod(Sel); 392d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff 393f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff if (!Method) 394f1afaf6fe2d94ab265299853f288b676694f7554Steve Naroff Method = LookupPrivateMethod(Sel, ClassDecl); 395d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff } 39648f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 39748f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor return true; 398d526c2f2ef28643c15589135b59eb4a8d9f9414cSteve Naroff } 3991f484f4aef0ea52b920e568e0c1fa2cbdfe98957Steve Naroff // Look for any factory method named 'Sel'. 4001f484f4aef0ea52b920e568e0c1fa2cbdfe98957Steve Naroff if (!Method) 4011f484f4aef0ea52b920e568e0c1fa2cbdfe98957Steve Naroff Method = FactoryMethodPool[Sel].Method; 402e2af8b16cb66b59ac3570c5561289469bd852699Steve Naroff if (!Method) 403037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff Method = LookupInstanceMethodInGlobalPool( 404037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff Sel, SourceRange(lbrac,rbrac)); 405077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 406637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar lbrac, rbrac, returnType)) 407637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar return true; 4088189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 4098189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek rbrac, ArgExprs, NumArgs); 410fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner } 411fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner 4122b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner ObjCMethodDecl *Method = 0; 413fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner ObjCInterfaceDecl* ClassDecl = 0; 4142b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner 4152b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 4162b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner // long as one of the protocols implements the selector (if not, warn). 417b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner if (ObjCQualifiedIdType *QIT = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) { 418f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff // Search protocols for instance methods. 419fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 420fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 421fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 422fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner break; 423fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner } 424f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff // Check for GCC extension "Class<foo>". 425f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff } else if (ObjCQualifiedClassType *QIT = 426f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) { 427f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff // Search protocols for class methods. 428f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 429f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 430f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) 431f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff break; 432f7f52e7bf5a4dc36d45b98531e0b21e343fc19deSteve Naroff } 433279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff } else if (const ObjCInterfaceType *OCIType = 434b77792eabf5882cf9af8cc810599b20432fda6c2Chris Lattner ReceiverCType->getAsPointerToObjCInterfaceType()) { 4352b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner // We allow sending a message to a pointer to an interface (an object). 436fb8cc1dfd87a1cbbaa17d64ec753d3fe8a9e9c38Chris Lattner 437279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff ClassDecl = OCIType->getDecl(); 438037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be 439037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff // faster than the following method (which can do *many* linear searches). 440037cda5282e73f30bb09fa316047554b1af1e2efSteve Naroff // The idea is to add class info to InstanceMethodPool. 441fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner Method = ClassDecl->lookupInstanceMethod(Sel); 442fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner 443fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner if (!Method) { 444fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner // Search protocol qualifiers. 445279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff for (ObjCQualifiedInterfaceType::qual_iterator QI = OCIType->qual_begin(), 446279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff E = OCIType->qual_end(); QI != E; ++QI) { 447fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner if ((Method = (*QI)->lookupInstanceMethod(Sel))) 44885a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner break; 44985a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 45085a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner } 4510de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff if (!Method) { 4520de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff // If we have an implementation in scope, check "private" methods. 4530de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff if (ClassDecl) 4540de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff if (ObjCImplementationDecl *ImpDecl = 4550de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff ObjCImplementations[ClassDecl->getIdentifier()]) 4560de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff Method = ImpDecl->getInstanceMethod(Sel); 4570de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff // If we still haven't found a method, look in the global pool. This 4580de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff // behavior isn't very desirable, however we need it for GCC 4590de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff // compatibility. FIXME: should we deviate?? 460279d896d4972417f62537fe4a87a8c3c3d675108Steve Naroff if (!Method && OCIType->qual_empty()) 4610de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff Method = LookupInstanceMethodInGlobalPool( 4620de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff Sel, SourceRange(lbrac,rbrac)); 4630de21fd85d79bccd32f04256f5b3328ab5ed7c95Steve Naroff } 46448f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 46548f3bb9f780f6e64ab71ba0202ca04b07473805aDouglas Gregor return true; 4662b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner } else { 4678e2945ad9104f0ce4928c386faf458b6b83d9060Steve Naroff Diag(lbrac, diag::warn_bad_receiver_type) 468d162584991885ab004a02573a73ce06422b921fcChris Lattner << RExpr->getType() << RExpr->getSourceRange(); 4692b1cc8be4dda4cd122485be0168b3c43d7dff15fChris Lattner return true; 470fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner } 471fe1a553256b46fad3c0a9e9967481bcf571339ecChris Lattner 472077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 473637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar lbrac, rbrac, returnType)) 474637cebb67c59765e1412c589550c8c9ba001baebDaniel Dunbar return true; 4758189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 4768189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek rbrac, ArgExprs, NumArgs); 47785a932e26f3c3faae6bad639a6d32e92794dfda9Chris Lattner} 478eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 479eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner//===----------------------------------------------------------------------===// 480eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 481eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner//===----------------------------------------------------------------------===// 482eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 483eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 484eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// inheritance hierarchy of 'rProto'. 485eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerstatic bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 486eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *rProto) { 487eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (lProto == rProto) 488eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 489780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), 490780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner E = rProto->protocol_end(); PI != E; ++PI) 491780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner if (ProtocolCompatibleWithProtocol(lProto, *PI)) 492eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 493eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 494eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 495eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 496eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// ClassImplementsProtocol - Checks that 'lProto' protocol 497eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// has been implemented in IDecl class, its super class or categories (if 498eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner/// lookupCategory is true). 499eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerstatic bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 500eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCInterfaceDecl *IDecl, 50126631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian bool lookupCategory, 50226631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian bool RHSIsQualifiedID = false) { 503eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 504eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 1st, look up the class. 5053db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner const ObjCList<ObjCProtocolDecl> &Protocols = 5063db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner IDecl->getReferencedProtocols(); 5073db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner 5083db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(), 5093db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner E = Protocols.end(); PI != E; ++PI) { 5103db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner if (ProtocolCompatibleWithProtocol(lProto, *PI)) 511eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 51226631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // This is dubious and is added to be compatible with gcc. 51326631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // In gcc, it is also allowed assigning a protocol-qualified 'id' 51426631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // type to a LHS object when protocol in qualified LHS is in list 51526631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian // of protocols in the rhs 'id' object. This IMO, should be a bug. 516fd5b2ce150185d8d8fc3d7789983bbd2b0b8103fTed Kremenek // FIXME: Treat this as an extension, and flag this as an error when 517fd5b2ce150185d8d8fc3d7789983bbd2b0b8103fTed Kremenek // GCC extensions are not enabled. 5183db6cae19c236fe2cef343c90105ce7cca7de965Chris Lattner if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) 51926631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian return true; 520eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 521eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 522eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 2nd, look up the category. 523eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (lookupCategory) 524eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 525eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner CDecl = CDecl->getNextClassCategory()) { 526780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), 527780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner E = CDecl->protocol_end(); PI != E; ++PI) 528780f329cb011bff0da5763e2e9744eec093d0509Chris Lattner if (ProtocolCompatibleWithProtocol(lProto, *PI)) 529eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 530eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 531eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 532eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // 3rd, look up the super class(s) 533eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (IDecl->getSuperClass()) 534eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return 53526631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 53626631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian RHSIsQualifiedID); 537eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 538eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 539eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 540eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 541b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 542b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner/// ObjCQualifiedIDType. 543eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattnerbool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 544eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner bool compare) { 545eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // Allow id<P..> and an 'id' or void* type in all cases. 546eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (const PointerType *PT = lhs->getAsPointerType()) { 547eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner QualType PointeeTy = PT->getPointeeType(); 548389bf46ae41241a656ed71b00ac2177d7f385651Steve Naroff if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 549eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 550eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } else if (const PointerType *PT = rhs->getAsPointerType()) { 551eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner QualType PointeeTy = PT->getPointeeType(); 552389bf46ae41241a656ed71b00ac2177d7f385651Steve Naroff if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 553eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return true; 554eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 555eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 556b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 557b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 558b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedInterfaceType *rhsQI = 0; 559289d9f243d9074513368d27eef3b647f72a38324Steve Naroff QualType rtype; 560289d9f243d9074513368d27eef3b647f72a38324Steve Naroff 561b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!rhsQID) { 562b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // Not comparing two ObjCQualifiedIdType's? 563b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!rhs->isPointerType()) return false; 564289d9f243d9074513368d27eef3b647f72a38324Steve Naroff 565289d9f243d9074513368d27eef3b647f72a38324Steve Naroff rtype = rhs->getAsPointerType()->getPointeeType(); 566eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 567b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (rhsQI == 0) { 568289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // If the RHS is a unqualified interface pointer "NSString*", 569289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // make sure we check the class hierarchy. 570b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 571b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCInterfaceDecl *rhsID = IT->getDecl(); 572b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 573b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // when comparing an id<P> on lhs with a static type on rhs, 574b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // see if static class implements all of id's protocols, directly or 575b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // through its super class and categories. 576b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 577b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 578b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 579b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 580b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 581b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 582eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 583eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 584eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 585289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 586eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoI = rhsQI->qual_begin(); 587eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoE = rhsQI->qual_end(); 588289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 589eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoI = rhsQID->qual_begin(); 590eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner RHSProtoE = rhsQID->qual_end(); 591b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } else { 592b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 593eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 594eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 595eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 596eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 597eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner bool match = false; 598eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 599eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // when comparing an id<P> on lhs with a static type on rhs, 600eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // see if static class implements all of id's protocols, directly or 601eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner // through its super class and categories. 602b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 603b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *rhsProto = *RHSProtoI; 604b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 60582b4e768d38c12ceba7db23a96e8d845e00fdeb7Eli Friedman (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 606eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner match = true; 607b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner break; 608eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 609eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 610289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (rhsQI) { 611289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // If the RHS is a qualified interface pointer "NSString<P>*", 612289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // make sure we check the class hierarchy. 613289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 614289d9f243d9074513368d27eef3b647f72a38324Steve Naroff ObjCInterfaceDecl *rhsID = IT->getDecl(); 615289d9f243d9074513368d27eef3b647f72a38324Steve Naroff for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 616289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // when comparing an id<P> on lhs with a static type on rhs, 617289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // see if static class implements all of id's protocols, directly or 618289d9f243d9074513368d27eef3b647f72a38324Steve Naroff // through its super class and categories. 619289d9f243d9074513368d27eef3b647f72a38324Steve Naroff if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 620289d9f243d9074513368d27eef3b647f72a38324Steve Naroff match = true; 621289d9f243d9074513368d27eef3b647f72a38324Steve Naroff break; 622289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 623289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 624289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 625289d9f243d9074513368d27eef3b647f72a38324Steve Naroff } 626eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner if (!match) 627eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner return false; 628eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 629eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 630b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 631b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 632b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 633b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 634b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner assert(rhsQID && "One of the LHS/RHS should be id<x>"); 635eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 636b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!lhs->isPointerType()) 637b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 638b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 639b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner QualType ltype = lhs->getAsPointerType()->getPointeeType(); 640b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCQualifiedInterfaceType *lhsQI = 641b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ltype->getAsObjCQualifiedInterfaceType()) { 642b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 643b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 644b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 645b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner bool match = false; 646b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *lhsProto = *LHSProtoI; 647eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 648eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 649b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 65082b4e768d38c12ceba7db23a96e8d845e00fdeb7Eli Friedman (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 651eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner match = true; 652eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner break; 653eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 654eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 655b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (!match) 656b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 657eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 658b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 659b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 660b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner 661b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 662b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // for static type vs. qualified 'id' type, check that class implements 663b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner // all of 'id's protocols. 664b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCInterfaceDecl *lhsID = IT->getDecl(); 665b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 666b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 66726631704d15e2fe19bae8a22939e0a473407c20dFariborz Jahanian if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 668b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 669b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner } 670b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return true; 671eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner } 672b1698cf972be75084d760c82389ab5b49a386c31Chris Lattner return false; 673eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner} 674eca7be6b7ebd93682eeaab2c71d59f2995dacdccChris Lattner 675