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