SemaExprObjC.cpp revision b327ce02959d4e6224732e1c362e7f8e0688581f
1269f91e066c5991a4d4aa2945ea2c285f8589b12Greg Clayton//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
2363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//
3363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//                     The LLVM Compiler Infrastructure
4363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//
5363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton// This file is distributed under the University of Illinois Open Source
6363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton// License. See LICENSE.TXT for details.
7363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//
8363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//===----------------------------------------------------------------------===//
9363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//
10363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//  This file implements semantic analysis for Objective-C expressions.
11363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//
12363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton//===----------------------------------------------------------------------===//
13363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton
14fac2e62f08719ba800a440b7ad0d5a55a26dc620Jason Molenda#include "Sema.h"
15363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton#include "clang/AST/ASTContext.h"
16363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton#include "clang/AST/DeclObjC.h"
17363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton#include "clang/AST/Expr.h"
18363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Claytonusing namespace clang;
190fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
200fa512447e00da09d300fbabd18b5ce94f52fdaaGreg ClaytonSema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
21363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                                              ExprTy **Strings,
22d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                              unsigned NumStrings) {
231e5b02176d6952d0679479926fa557534313472bGreg Clayton  SourceLocation AtLoc = AtLocs[0];
24363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  StringLiteral* S = static_cast<StringLiteral *>(Strings[0]);
250fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton  if (NumStrings > 1) {
26fac2e62f08719ba800a440b7ad0d5a55a26dc620Jason Molenda    // Concatenate objc strings.
27363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]);
28363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    SourceLocation EndLoc = ES->getSourceRange().getEnd();
29363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    unsigned Length = 0;
30363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    for (unsigned i = 0; i < NumStrings; i++)
31363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      Length += static_cast<StringLiteral *>(Strings[i])->getByteLength();
32363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    char *strBuf = new char [Length];
33363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    char *p = strBuf;
34363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    bool isWide = false;
35363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    for (unsigned i = 0; i < NumStrings; i++) {
36363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      S = static_cast<StringLiteral *>(Strings[i]);
37363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (S->isWide())
38363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        isWide = true;
39363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      memcpy(p, S->getStrData(), S->getByteLength());
40363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      p += S->getByteLength();
41363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      delete S;
42363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    }
430fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton    S = new StringLiteral(strBuf, Length,
44d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                          isWide, Context.getPointerType(Context.CharTy),
4552fbbd224d4ba741d5f717e1683c5daa21fe8710Jason Molenda                          AtLoc, EndLoc);
46363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  }
473acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton
48d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  if (CheckBuiltinCFStringArgument(S))
49d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    return true;
50d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton
51d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  if (Context.getObjCConstantStringInterface().isNull()) {
52d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    // Initialize the constant string interface lazily. This assumes
53d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    // the NSConstantString interface is seen in this translation unit.
54d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
55d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, TUScope);
56363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
57363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!strIFace)
58363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      return Diag(S->getLocStart(), diag::err_undef_interface,
59363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                  NSIdent->getName());
60363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    Context.setObjCConstantStringInterface(strIFace);
61363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  }
62363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  QualType t = Context.getObjCConstantStringInterface();
63363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  t = Context.getPointerType(t);
64363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  return new ObjCStringLiteral(S, t, AtLoc);
65363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton}
66363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton
67363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg ClaytonSema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
68363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                                                 SourceLocation EncodeLoc,
69363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                                                 SourceLocation LParenLoc,
701e5b02176d6952d0679479926fa557534313472bGreg Clayton                                                 TypeTy *Ty,
71d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                 SourceLocation RParenLoc) {
72363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  QualType EncodedType = QualType::getFromOpaquePtr(Ty);
73363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton
741e5b02176d6952d0679479926fa557534313472bGreg Clayton  QualType t = Context.getPointerType(Context.CharTy);
75363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
76363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton}
77d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton
78d52d00f4edb746ba458a3e659699160952dc925eGreg ClaytonSema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
79d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation AtLoc,
80d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation SelLoc,
81d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation LParenLoc,
82d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation RParenLoc) {
83d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  QualType t = Context.getObjCSelType();
84d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
85d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton}
861e5b02176d6952d0679479926fa557534313472bGreg Clayton
87307c7fdc58d19f734991a176db972cc61d9ada16Greg ClaytonSema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
88d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation AtLoc,
89d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                   SourceLocation ProtoLoc,
90363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                                                   SourceLocation LParenLoc,
911e5b02176d6952d0679479926fa557534313472bGreg Clayton                                                   SourceLocation RParenLoc) {
92d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId];
93d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  if (!PDecl) {
94d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName());
95d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    return true;
96363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  }
97363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton
98d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  QualType t = Context.getObjCProtoType();
99d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  if (t.isNull())
100d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton    return true;
101d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  t = Context.getPointerType(t);
102d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc);
1033acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton}
1043acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton
105952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Claytonbool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
1063acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton                                     ObjCMethodDecl *Method) {
1073acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton  bool anyIncompatibleArgs = false;
1083acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton
1093acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton  for (unsigned i = 0; i < NumArgs; i++) {
1103acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    Expr *argExpr = Args[i];
1113acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
1123acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton
1133acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    QualType lhsType = Method->getParamDecl(i)->getType();
114d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    QualType rhsType = argExpr->getType();
1153acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton
1163acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
1173acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    if (const ArrayType *ary = lhsType->getAsArrayType())
1183acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton      lhsType = Context.getPointerType(ary->getElementType());
1193acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton    else if (lhsType->isFunctionType())
120d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton      lhsType = Context.getPointerType(lhsType);
121d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton
122d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton    AssignConvertType Result = CheckSingleAssignmentConstraints(lhsType,
123d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton                                                                argExpr);
124d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton    if (Args[i] != argExpr) // The expression was converted.
125d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton      Args[i] = argExpr; // Make sure we store the converted expression.
126d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton
1277efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    anyIncompatibleArgs |=
128d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
1297efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton                               argExpr, "sending");
1303acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton  }
1317efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  return anyIncompatibleArgs;
132ea4626053e22d06f145ccbf3b154cc04eea8e770Greg Clayton}
1337efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton
134d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton// ActOnClassMessage - used for both unary and keyword messages.
135d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton// ArgExprs is optional - if it is present, the number of expressions
1367efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton// is obtained from Sel.getNumArgs().
1377efa0885bbb5c2cc57d30242f63c154f6a25d372Greg ClaytonSema::ExprResult Sema::ActOnClassMessage(
1387efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  Scope *S,
1397efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  IdentifierInfo *receiverName, Selector Sel,
1407efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
1417efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton{
1427efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  assert(receiverName && "missing receiver class name");
1437efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton
1447efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
1457efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  ObjCInterfaceDecl* ClassDecl = 0;
1467efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) {
1477efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass();
1487efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    if (!ClassDecl)
1497efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      return Diag(lbrac, diag::error_no_super_class,
150d2f3b42f70f309f548c2b618c5991a905a00ec3aGreg Clayton                  CurMethodDecl->getClassInterface()->getName());
1517efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    if (CurMethodDecl->isInstance()) {
1527efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      // Synthesize a cast to the super class. This hack allows us to loosely
1537efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      // represent super without creating a special expression node.
1547efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      IdentifierInfo &II = Context.Idents.get("self");
1557efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false);
1567efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      QualType superTy = Context.getObjCInterfaceType(ClassDecl);
1577efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      superTy = Context.getPointerType(superTy);
1587efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(),
1597efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton                                   SourceLocation(), ReceiverExpr.Val);
1607efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      // We are really in an instance method, redirect.
1617efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton      return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac,
1627efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton                                  Args, NumArgs);
1637efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    }
1647efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    // We are sending a message to 'super' within a class method. Do nothing,
1657efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    // the receiver will pass through as 'super' (how convenient:-).
1667efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton  } else
1677efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton    ClassDecl = getObjCInterfaceDecl(receiverName);
1687efa0885bbb5c2cc57d30242f63c154f6a25d372Greg Clayton
1693acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton  // FIXME: can ClassDecl ever be null?
170d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  ObjCMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
171d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  QualType returnType;
172d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton
173d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  // Before we give up, check if the selector is an instance method.
174d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  if (!Method)
175d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    Method = ClassDecl->lookupInstanceMethod(Sel);
176363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  if (!Method) {
1771e5b02176d6952d0679479926fa557534313472bGreg Clayton    Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
178d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton         SourceRange(lbrac, rbrac));
179363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    returnType = Context.getObjCIdType();
180363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  } else {
181363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    returnType = Method->getResultType();
1821e5b02176d6952d0679479926fa557534313472bGreg Clayton    if (Sel.getNumArgs()) {
1831e5b02176d6952d0679479926fa557534313472bGreg Clayton      if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
184363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        return true;
185952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton    }
186363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  }
187363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
1880fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                             lbrac, rbrac, ArgExprs, NumArgs);
1890fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton}
1900fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
191363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton// ActOnInstanceMessage - used for both unary and keyword messages.
1921e5b02176d6952d0679479926fa557534313472bGreg Clayton// ArgExprs is optional - if it is present, the number of expressions
193363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton// is obtained from Sel.getNumArgs().
1941e5b02176d6952d0679479926fa557534313472bGreg ClaytonSema::ExprResult Sema::ActOnInstanceMessage(
1951e5b02176d6952d0679479926fa557534313472bGreg Clayton  ExprTy *receiver, Selector Sel,
1961e5b02176d6952d0679479926fa557534313472bGreg Clayton  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
1971e5b02176d6952d0679479926fa557534313472bGreg Clayton{
1981e5b02176d6952d0679479926fa557534313472bGreg Clayton  assert(receiver && "missing receiver expression");
1991e5b02176d6952d0679479926fa557534313472bGreg Clayton
2001e5b02176d6952d0679479926fa557534313472bGreg Clayton  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
2011e5b02176d6952d0679479926fa557534313472bGreg Clayton  Expr *RExpr = static_cast<Expr *>(receiver);
2021e5b02176d6952d0679479926fa557534313472bGreg Clayton  QualType receiverType = RExpr->getType().getCanonicalType();
2035f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea  QualType returnType;
2041e5b02176d6952d0679479926fa557534313472bGreg Clayton  ObjCMethodDecl *Method = 0;
2051e5b02176d6952d0679479926fa557534313472bGreg Clayton
206363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  // FIXME: This code is not stripping off type qualifiers! Should it?
207363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton  if (receiverType == Context.getObjCIdType().getCanonicalType() ||
208363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      receiverType == Context.getObjCClassType().getCanonicalType()) {
209516f0849819d094d4eab39a1f27b770259103ff8Greg Clayton    Method = InstanceMethodPool[Sel].Method;
210363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!Method)
2111b584ebc1de8b50fe375cffb5fb33ad13be10046Jim Ingham      Method = FactoryMethodPool[Sel].Method;
212363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!Method) {
213363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
214363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton           SourceRange(lbrac, rbrac));
215363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      returnType = Context.getObjCIdType();
216363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    } else {
217363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      returnType = Method->getResultType();
2183acaa926c8f0d32da48db61a5fcb95276e6a4006Greg Clayton      if (Sel.getNumArgs())
219363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
220363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          return true;
221363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    }
222d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  } else {
223363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType);
224363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    // FIXME (snaroff): checking in this code from Patrick. Needs to be
225363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    // revisited. how do we get the ClassDecl from the receiver expression?
226363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!receiverIsQualId)
227363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      while (const PointerType *PTy = receiverType->getAsPointerType())
228363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        receiverType = PTy->getPointeeType();
229d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton
230363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    ObjCInterfaceDecl* ClassDecl = 0;
231363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (ObjCQualifiedInterfaceType *QIT =
232363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) {
233363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      ClassDecl = QIT->getDecl();
234952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton      Method = ClassDecl->lookupInstanceMethod(Sel);
235363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (!Method) {
236363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        // search protocols
237363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
238d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton          ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
239363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
240363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton            break;
241363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        }
242363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      }
2431e3a522380565640ec900979b8532500bd3004c5Johnny Chen      if (!Method)
244363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        Diag(lbrac, diag::warn_method_not_found_in_protocol,
245363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             std::string("-"), Sel.getName(),
246363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             SourceRange(lbrac, rbrac));
2475f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea    }
248363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    else if (ObjCQualifiedIdType *QIT =
249363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             dyn_cast<ObjCQualifiedIdType>(receiverType)) {
250363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      // search protocols
251363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
252851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton        ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
253363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
254363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          break;
255363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      }
256363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (!Method)
257d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton        Diag(lbrac, diag::warn_method_not_found_in_protocol,
258363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             std::string("-"), Sel.getName(),
259363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             SourceRange(lbrac, rbrac));
260363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    }
261363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    else {
262363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType);
263363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (OCIReceiver == 0) {
264363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        Diag(lbrac, diag::error_bad_receiver_type,
265363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton             RExpr->getType().getAsString());
266363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        return true;
267363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      }
268363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      ClassDecl = OCIReceiver->getDecl();
269363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      // FIXME: consider using InstanceMethodPool, since it will be faster
270363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      // than the following method (which can do *many* linear searches). The
271363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      // idea is to add class info to InstanceMethodPool...
272363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      Method = ClassDecl->lookupInstanceMethod(Sel);
273363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    }
274363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!Method) {
275363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      // If we have an implementation in scope, check "private" methods.
276363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (ClassDecl)
277363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        if (ObjCImplementationDecl *ImpDecl =
278363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton            ObjCImplementations[ClassDecl->getIdentifier()])
279363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          Method = ImpDecl->getInstanceMethod(Sel);
280363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          // If we still haven't found a method, look in the global pool. This
281363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          // behavior isn't very desirable, however we need it for GCC
282363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          // compatibility.
283363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          if (!Method)
284d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton            Method = InstanceMethodPool[Sel].Method;
285363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    }
286363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    if (!Method) {
287363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
288363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton           SourceRange(lbrac, rbrac));
289952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton      returnType = Context.getObjCIdType();
290363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton    } else {
291363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      returnType = Method->getResultType();
292363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton      if (Sel.getNumArgs())
293363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
294363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton          return true;
295d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton    }
2968d2ea2888a4acb7f140f9af64ddd2b16b2dee870Greg Clayton  }
297d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton  return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac,
298363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton                             ArgExprs, NumArgs);
299363be3fc515bea8baf2c5031f3c62f6326d9e1b8Greg Clayton}
300d52d00f4edb746ba458a3e659699160952dc925eGreg Clayton