SemaExprObjC.cpp revision e2af8b16cb66b59ac3570c5561289469bd852699
1//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file implements semantic analysis for Objective-C expressions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/ExprObjC.h"
18using namespace clang;
19
20Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
21                                              ExprTy **Strings,
22                                              unsigned NumStrings) {
23  SourceLocation AtLoc = AtLocs[0];
24  StringLiteral* S = static_cast<StringLiteral *>(Strings[0]);
25  if (NumStrings > 1) {
26    // Concatenate objc strings.
27    StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]);
28    SourceLocation EndLoc = ES->getSourceRange().getEnd();
29    unsigned Length = 0;
30    for (unsigned i = 0; i < NumStrings; i++)
31      Length += static_cast<StringLiteral *>(Strings[i])->getByteLength();
32    char *strBuf = new char [Length];
33    char *p = strBuf;
34    bool isWide = false;
35    for (unsigned i = 0; i < NumStrings; i++) {
36      S = static_cast<StringLiteral *>(Strings[i]);
37      if (S->isWide())
38        isWide = true;
39      memcpy(p, S->getStrData(), S->getByteLength());
40      p += S->getByteLength();
41      delete S;
42    }
43    S = new StringLiteral(strBuf, Length,
44                          isWide, Context.getPointerType(Context.CharTy),
45                          AtLoc, EndLoc);
46  }
47
48  if (CheckBuiltinCFStringArgument(S))
49    return true;
50
51  if (Context.getObjCConstantStringInterface().isNull()) {
52    // Initialize the constant string interface lazily. This assumes
53    // the NSConstantString interface is seen in this translation unit.
54    IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
55    Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, TUScope);
56    ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
57    if (!strIFace)
58      return Diag(S->getLocStart(), diag::err_undef_interface,
59                  NSIdent->getName());
60    Context.setObjCConstantStringInterface(strIFace);
61  }
62  QualType t = Context.getObjCConstantStringInterface();
63  t = Context.getPointerType(t);
64  return new ObjCStringLiteral(S, t, AtLoc);
65}
66
67Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
68                                                 SourceLocation EncodeLoc,
69                                                 SourceLocation LParenLoc,
70                                                 TypeTy *Ty,
71                                                 SourceLocation RParenLoc) {
72  QualType EncodedType = QualType::getFromOpaquePtr(Ty);
73
74  QualType t = Context.getPointerType(Context.CharTy);
75  return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
76}
77
78Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
79                                                   SourceLocation AtLoc,
80                                                   SourceLocation SelLoc,
81                                                   SourceLocation LParenLoc,
82                                                   SourceLocation RParenLoc) {
83  QualType t = Context.getObjCSelType();
84  return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
85}
86
87Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
88                                                   SourceLocation AtLoc,
89                                                   SourceLocation ProtoLoc,
90                                                   SourceLocation LParenLoc,
91                                                   SourceLocation RParenLoc) {
92  ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId];
93  if (!PDecl) {
94    Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName());
95    return true;
96  }
97
98  QualType t = Context.getObjCProtoType();
99  if (t.isNull())
100    return true;
101  t = Context.getPointerType(t);
102  return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc);
103}
104
105bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
106                                     ObjCMethodDecl *Method) {
107  bool anyIncompatibleArgs = false;
108
109  for (unsigned i = 0; i < NumArgs; i++) {
110    Expr *argExpr = Args[i];
111    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
112
113    QualType lhsType = Method->getParamDecl(i)->getType();
114    QualType rhsType = argExpr->getType();
115
116    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
117    if (lhsType->isArrayType())
118      lhsType = Context.getArrayDecayedType(lhsType);
119    else if (lhsType->isFunctionType())
120      lhsType = Context.getPointerType(lhsType);
121
122    AssignConvertType Result =
123      CheckSingleAssignmentConstraints(lhsType, argExpr);
124    if (Args[i] != argExpr) // The expression was converted.
125      Args[i] = argExpr; // Make sure we store the converted expression.
126
127    anyIncompatibleArgs |=
128      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
129                               argExpr, "sending");
130  }
131  return anyIncompatibleArgs;
132}
133
134// ActOnClassMessage - used for both unary and keyword messages.
135// ArgExprs is optional - if it is present, the number of expressions
136// is obtained from Sel.getNumArgs().
137Sema::ExprResult Sema::ActOnClassMessage(
138  Scope *S,
139  IdentifierInfo *receiverName, Selector Sel,
140  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
141{
142  assert(receiverName && "missing receiver class name");
143
144  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
145  ObjCInterfaceDecl* ClassDecl = 0;
146  if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) {
147    ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass();
148    if (!ClassDecl)
149      return Diag(lbrac, diag::error_no_super_class,
150                  CurMethodDecl->getClassInterface()->getName());
151    if (CurMethodDecl->isInstance()) {
152      // Synthesize a cast to the super class. This hack allows us to loosely
153      // represent super without creating a special expression node.
154      IdentifierInfo &II = Context.Idents.get("self");
155      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false);
156      QualType superTy = Context.getObjCInterfaceType(ClassDecl);
157      superTy = Context.getPointerType(superTy);
158      ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(),
159                                   SourceLocation(), ReceiverExpr.Val);
160      // We are really in an instance method, redirect.
161      return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac,
162                                  Args, NumArgs);
163    }
164    // We are sending a message to 'super' within a class method. Do nothing,
165    // the receiver will pass through as 'super' (how convenient:-).
166  } else
167    ClassDecl = getObjCInterfaceDecl(receiverName);
168
169  // ClassDecl is null in the following case.
170  //
171  //  typedef XCElementDisplayRect XCElementGraphicsRect;
172  //
173  //  @implementation XCRASlice
174  //  - whatever { // Note that XCElementGraphicsRect is a typedef name.
175  //    _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
176  //  }
177  //
178  // FIXME: Investigate why GCC allows the above.
179  ObjCMethodDecl *Method = 0;
180  QualType returnType;
181  if (ClassDecl) {
182    Method = ClassDecl->lookupClassMethod(Sel);
183
184    // If we have an implementation in scope, check "private" methods.
185    if (!Method) {
186      if (ObjCImplementationDecl *ImpDecl =
187          ObjCImplementations[ClassDecl->getIdentifier()])
188        Method = ImpDecl->getClassMethod(Sel);
189    }
190    // Before we give up, check if the selector is an instance method.
191    if (!Method)
192      Method = ClassDecl->lookupInstanceMethod(Sel);
193  }
194  if (!Method) {
195    Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
196         SourceRange(lbrac, rbrac));
197    returnType = Context.getObjCIdType();
198  } else {
199    returnType = Method->getResultType();
200    if (Sel.getNumArgs()) {
201      if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
202        return true;
203    }
204  }
205  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
206                             lbrac, rbrac, ArgExprs, NumArgs);
207}
208
209// ActOnInstanceMessage - used for both unary and keyword messages.
210// ArgExprs is optional - if it is present, the number of expressions
211// is obtained from Sel.getNumArgs().
212Sema::ExprResult Sema::ActOnInstanceMessage(
213  ExprTy *receiver, Selector Sel,
214  SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs)
215{
216  assert(receiver && "missing receiver expression");
217
218  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
219  Expr *RExpr = static_cast<Expr *>(receiver);
220  QualType receiverType;
221  QualType returnType;
222  ObjCMethodDecl *Method = 0;
223
224  receiverType = RExpr->getType().getCanonicalType().getUnqualifiedType();
225
226  if (receiverType == Context.getObjCIdType().getCanonicalType()) {
227    Method = InstanceMethodPool[Sel].Method;
228    if (!Method)
229      Method = FactoryMethodPool[Sel].Method;
230    if (!Method) {
231      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
232           SourceRange(lbrac, rbrac));
233      returnType = Context.getObjCIdType();
234    } else {
235      returnType = Method->getResultType();
236      if (Sel.getNumArgs())
237        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
238          return true;
239    }
240  } else if (receiverType == Context.getObjCClassType().getCanonicalType()) {
241    if (CurMethodDecl) {
242      ObjCInterfaceDecl* ClassDecl = CurMethodDecl->getClassInterface();
243      // If we have an implementation in scope, check "private" methods.
244      if (ClassDecl)
245        if (ObjCImplementationDecl *ImpDecl =
246            ObjCImplementations[ClassDecl->getIdentifier()])
247          Method = ImpDecl->getClassMethod(Sel);
248    }
249    if (!Method)
250      Method = FactoryMethodPool[Sel].Method;
251    if (!Method)
252      Method = InstanceMethodPool[Sel].Method;
253    if (!Method) {
254      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
255           SourceRange(lbrac, rbrac));
256      returnType = Context.getObjCIdType();
257    } else {
258      returnType = Method->getResultType();
259      if (Sel.getNumArgs())
260        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
261          return true;
262    }
263  } else {
264    bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType);
265    // FIXME (snaroff): checking in this code from Patrick. Needs to be
266    // revisited. how do we get the ClassDecl from the receiver expression?
267    if (!receiverIsQualId)
268      while (const PointerType *PTy = receiverType->getAsPointerType())
269        receiverType = PTy->getPointeeType();
270
271    ObjCInterfaceDecl* ClassDecl = 0;
272    if (ObjCQualifiedInterfaceType *QIT =
273        dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) {
274      ClassDecl = QIT->getDecl();
275      Method = ClassDecl->lookupInstanceMethod(Sel);
276      if (!Method) {
277        // search protocols
278        for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
279          ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
280          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
281            break;
282        }
283      }
284      if (!Method)
285        Diag(lbrac, diag::warn_method_not_found_in_protocol,
286             std::string("-"), Sel.getName(),
287             SourceRange(lbrac, rbrac));
288    }
289    else if (ObjCQualifiedIdType *QIT =
290             dyn_cast<ObjCQualifiedIdType>(receiverType)) {
291      // search protocols
292      for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
293        ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
294        if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
295          break;
296      }
297      if (!Method)
298        Diag(lbrac, diag::warn_method_not_found_in_protocol,
299             std::string("-"), Sel.getName(),
300             SourceRange(lbrac, rbrac));
301    }
302    else {
303      ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType);
304      if (OCIReceiver == 0) {
305        Diag(lbrac, diag::error_bad_receiver_type,
306             RExpr->getType().getAsString());
307        return true;
308      }
309      ClassDecl = OCIReceiver->getDecl();
310      // FIXME: consider using InstanceMethodPool, since it will be faster
311      // than the following method (which can do *many* linear searches). The
312      // idea is to add class info to InstanceMethodPool...
313      Method = ClassDecl->lookupInstanceMethod(Sel);
314    }
315    if (!Method) {
316      // If we have an implementation in scope, check "private" methods.
317      if (ClassDecl)
318        if (ObjCImplementationDecl *ImpDecl =
319            ObjCImplementations[ClassDecl->getIdentifier()])
320          Method = ImpDecl->getInstanceMethod(Sel);
321          // If we still haven't found a method, look in the global pool. This
322          // behavior isn't very desirable, however we need it for GCC
323          // compatibility.
324          if (!Method)
325            Method = InstanceMethodPool[Sel].Method;
326    }
327    if (!Method) {
328      Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
329           SourceRange(lbrac, rbrac));
330      returnType = Context.getObjCIdType();
331    } else {
332      returnType = Method->getResultType();
333      if (Sel.getNumArgs())
334        if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
335          return true;
336    }
337  }
338  return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac,
339                             ArgExprs, NumArgs);
340}
341
342//===----------------------------------------------------------------------===//
343// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
344//===----------------------------------------------------------------------===//
345
346/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
347/// inheritance hierarchy of 'rProto'.
348static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
349                                           ObjCProtocolDecl *rProto) {
350  if (lProto == rProto)
351    return true;
352  ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols();
353  for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++)
354    if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i]))
355      return true;
356  return false;
357}
358
359/// ClassImplementsProtocol - Checks that 'lProto' protocol
360/// has been implemented in IDecl class, its super class or categories (if
361/// lookupCategory is true).
362static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
363                                    ObjCInterfaceDecl *IDecl,
364                                    bool lookupCategory,
365                                    bool RHSIsQualifiedID = false) {
366
367  // 1st, look up the class.
368  ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols();
369  for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) {
370    if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
371      return true;
372    // This is dubious and is added to be compatible with gcc.
373    // In gcc, it is also allowed assigning a protocol-qualified 'id'
374    // type to a LHS object when protocol in qualified LHS is in list
375    // of protocols in the rhs 'id' object. This IMO, should be a bug.
376    // FIXME: Treat this as an extension, and flag this as an error when
377    //  GCC extensions are not enabled.
378    else if (RHSIsQualifiedID &&
379             ProtocolCompatibleWithProtocol(protoList[i], lProto))
380      return true;
381  }
382
383  // 2nd, look up the category.
384  if (lookupCategory)
385    for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
386         CDecl = CDecl->getNextClassCategory()) {
387      protoList = CDecl->getReferencedProtocols();
388      for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) {
389        if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
390          return true;
391      }
392    }
393
394  // 3rd, look up the super class(s)
395  if (IDecl->getSuperClass())
396    return
397      ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory,
398                              RHSIsQualifiedID);
399
400  return false;
401}
402
403/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
404/// ObjCQualifiedIDType.
405bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
406                                             bool compare) {
407  // Allow id<P..> and an 'id' or void* type in all cases.
408  if (const PointerType *PT = lhs->getAsPointerType()) {
409    QualType PointeeTy = PT->getPointeeType();
410    if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
411      return true;
412  } else if (const PointerType *PT = rhs->getAsPointerType()) {
413    QualType PointeeTy = PT->getPointeeType();
414    if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
415      return true;
416  }
417
418  if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
419    const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
420    const ObjCQualifiedInterfaceType *rhsQI = 0;
421    QualType rtype;
422
423    if (!rhsQID) {
424      // Not comparing two ObjCQualifiedIdType's?
425      if (!rhs->isPointerType()) return false;
426
427      rtype = rhs->getAsPointerType()->getPointeeType();
428      rhsQI = rtype->getAsObjCQualifiedInterfaceType();
429      if (rhsQI == 0) {
430        // If the RHS is a unqualified interface pointer "NSString*",
431        // make sure we check the class hierarchy.
432        if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
433          ObjCInterfaceDecl *rhsID = IT->getDecl();
434          for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) {
435            // when comparing an id<P> on lhs with a static type on rhs,
436            // see if static class implements all of id's protocols, directly or
437            // through its super class and categories.
438            if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true))
439              return false;
440          }
441          return true;
442        }
443      }
444    }
445
446    ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
447    if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *").
448      RHSProtoI = rhsQI->qual_begin();
449      RHSProtoE = rhsQI->qual_end();
450    } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *").
451      RHSProtoI = rhsQID->qual_begin();
452      RHSProtoE = rhsQID->qual_end();
453    } else {
454      return false;
455    }
456
457    for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
458      ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i);
459      bool match = false;
460
461      // when comparing an id<P> on lhs with a static type on rhs,
462      // see if static class implements all of id's protocols, directly or
463      // through its super class and categories.
464      for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
465        ObjCProtocolDecl *rhsProto = *RHSProtoI;
466        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
467            compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
468          match = true;
469          break;
470        }
471      }
472      if (rhsQI) {
473        // If the RHS is a qualified interface pointer "NSString<P>*",
474        // make sure we check the class hierarchy.
475        if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
476          ObjCInterfaceDecl *rhsID = IT->getDecl();
477          for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) {
478            // when comparing an id<P> on lhs with a static type on rhs,
479            // see if static class implements all of id's protocols, directly or
480            // through its super class and categories.
481            if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) {
482              match = true;
483              break;
484            }
485          }
486        }
487      }
488      if (!match)
489        return false;
490    }
491
492    return true;
493  }
494
495  const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
496  assert(rhsQID && "One of the LHS/RHS should be id<x>");
497
498  if (!lhs->isPointerType())
499    return false;
500
501  QualType ltype = lhs->getAsPointerType()->getPointeeType();
502  if (const ObjCQualifiedInterfaceType *lhsQI =
503         ltype->getAsObjCQualifiedInterfaceType()) {
504    ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin();
505    ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end();
506    for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
507      bool match = false;
508      ObjCProtocolDecl *lhsProto = *LHSProtoI;
509      for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
510        ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
511        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
512            compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
513          match = true;
514          break;
515        }
516      }
517      if (!match)
518        return false;
519    }
520    return true;
521  }
522
523  if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) {
524    // for static type vs. qualified 'id' type, check that class implements
525    // all of 'id's protocols.
526    ObjCInterfaceDecl *lhsID = IT->getDecl();
527    for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
528      ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
529      if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true))
530        return false;
531    }
532    return true;
533  }
534  return false;
535}
536
537