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