zcov: / lib/Sema/SemaExprObjC.cpp


Files: 1 Branches Taken: 80.8% 252 / 312
Generated: 2010-02-10 01:31 Branches Executed: 97.4% 304 / 312
Line Coverage: 92.5% 282 / 305


Programs: 2 Runs 3018


       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"
      18                 : #include "llvm/ADT/SmallString.h"
      19                 : #include "clang/Lex/Preprocessor.h"
      20                 : 
      21                 : using namespace clang;
      22                 : 
      23                 : Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
      24                 :                                               ExprTy **strings,
      25              216:                                               unsigned NumStrings) {
      26              216:   StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
      27                 : 
      28                 :   // Most ObjC strings are formed out of a single piece.  However, we *can*
      29                 :   // have strings formed out of multiple @ strings with multiple pptokens in
      30                 :   // each one, e.g. @"foo" "bar" @"baz" "qux"   which need to be turned into one
      31                 :   // StringLiteral for ObjCStringLiteral to hold onto.
      32              216:   StringLiteral *S = Strings[0];
      33                 : 
      34                 :   // If we have a multi-part string, merge it all together.
                        7: branch 0 taken
                      209: branch 1 taken
      35              216:   if (NumStrings != 1) {
      36                 :     // Concatenate objc strings.
      37                7:     llvm::SmallString<128> StrBuf;
      38                7:     llvm::SmallVector<SourceLocation, 8> StrLocs;
      39                 : 
                       15: branch 0 taken
                        7: branch 1 taken
      40               22:     for (unsigned i = 0; i != NumStrings; ++i) {
      41               15:       S = Strings[i];
      42                 : 
      43                 :       // ObjC strings can't be wide.
                        0: branch 1 not taken
                       15: branch 2 taken
      44               15:       if (S->isWide()) {
      45                 :         Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
      46                0:           << S->getSourceRange();
      47                0:         return true;
      48                 :       }
      49                 : 
      50                 :       // Get the string data.
      51               15:       StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength());
      52                 : 
      53                 :       // Get the locations of the string tokens.
      54               15:       StrLocs.append(S->tokloc_begin(), S->tokloc_end());
      55                 : 
      56                 :       // Free the temporary string.
      57               15:       S->Destroy(Context);
      58                 :     }
      59                 : 
      60                 :     // Create the aggregate string with the appropriate content and location
      61                 :     // information.
      62                 :     S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
      63                 :                               Context.getPointerType(Context.CharTy),
                        7: branch 8 taken
                        0: branch 9 not taken
                        7: branch 11 taken
                        0: branch 12 not taken
      64                7:                               &StrLocs[0], StrLocs.size());
      65                 :   }
      66                 : 
      67                 :   // Verify that this composite string is acceptable for ObjC strings.
                        0: branch 1 not taken
                      216: branch 2 taken
      68              216:   if (CheckObjCString(S))
      69                0:     return true;
      70                 : 
      71                 :   // Initialize the constant string interface lazily. This assumes
      72                 :   // the NSString interface is seen in this translation unit. Note: We
      73                 :   // don't use NSConstantString, since the runtime team considers this
      74                 :   // interface private (even though it appears in the header files).
      75              216:   QualType Ty = Context.getObjCConstantStringInterface();
                      145: branch 1 taken
                       71: branch 2 taken
      76              216:   if (!Ty.isNull()) {
      77              145:     Ty = Context.getObjCObjectPointerType(Ty);
      78                 :   } else {
      79               71:     IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
      80               71:     NamedDecl *IF = LookupSingleName(TUScope, NSIdent, LookupOrdinaryName);
                       37: branch 1 taken
                       34: branch 2 taken
      81               71:     if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
      82               37:       Context.setObjCConstantStringInterface(StrIF);
      83               37:       Ty = Context.getObjCConstantStringInterface();
      84               37:       Ty = Context.getObjCObjectPointerType(Ty);
      85                 :     } else {
      86                 :       // If there is no NSString interface defined then treat constant
      87                 :       // strings as untyped objects and let the runtime figure it out later.
      88               34:       Ty = Context.getObjCIdType();
      89                 :     }
      90                 :   }
      91                 : 
                      216: branch 1 taken
                        0: branch 2 not taken
      92              216:   return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
      93                 : }
      94                 : 
      95                 : Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
      96                 :                                       QualType EncodedType,
      97               32:                                       SourceLocation RParenLoc) {
      98               32:   QualType StrTy;
                        1: branch 2 taken
                       31: branch 3 taken
      99               32:   if (EncodedType->isDependentType())
     100                1:     StrTy = Context.DependentTy;
     101                 :   else {
     102               31:     std::string Str;
     103               31:     Context.getObjCEncodingForType(EncodedType, Str);
     104                 : 
     105                 :     // The type of @encode is the same as the type of the corresponding string,
     106                 :     // which is an array type.
     107               31:     StrTy = Context.CharTy;
     108                 :     // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
                        2: branch 1 taken
                       29: branch 2 taken
     109               31:     if (getLangOptions().CPlusPlus)
     110                2:       StrTy.addConst();
     111                 :     StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
     112               31:                                          ArrayType::Normal, 0);
     113                 :   }
     114                 : 
                       32: branch 1 taken
                        0: branch 2 not taken
     115               32:   return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
     116                 : }
     117                 : 
     118                 : Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
     119                 :                                                  SourceLocation EncodeLoc,
     120                 :                                                  SourceLocation LParenLoc,
     121                 :                                                  TypeTy *ty,
     122               30:                                                  SourceLocation RParenLoc) {
     123                 :   // FIXME: Preserve type source info ?
     124               30:   QualType EncodedType = GetTypeFromParser(ty);
     125                 : 
     126               30:   return BuildObjCEncodeExpression(AtLoc, EncodedType, RParenLoc);
     127                 : }
     128                 : 
     129                 : Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
     130                 :                                                    SourceLocation AtLoc,
     131                 :                                                    SourceLocation SelLoc,
     132                 :                                                    SourceLocation LParenLoc,
     133               40:                                                    SourceLocation RParenLoc) {
     134                 :   ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
     135               40:                              SourceRange(LParenLoc, RParenLoc), false);
                       32: branch 0 taken
                        8: branch 1 taken
     136               40:   if (!Method)
     137                 :     Method = LookupFactoryMethodInGlobalPool(Sel,
     138               32:                                           SourceRange(LParenLoc, RParenLoc));
                       25: branch 0 taken
                       15: branch 1 taken
     139               40:   if (!Method)
     140               25:     Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
     141                 : 
     142               40:   QualType Ty = Context.getObjCSelType();
                       40: branch 1 taken
                        0: branch 2 not taken
     143               40:   return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
     144                 : }
     145                 : 
     146                 : Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
     147                 :                                                    SourceLocation AtLoc,
     148                 :                                                    SourceLocation ProtoLoc,
     149                 :                                                    SourceLocation LParenLoc,
     150               22:                                                    SourceLocation RParenLoc) {
     151               22:   ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId);
                        2: branch 0 taken
                       20: branch 1 taken
     152               22:   if (!PDecl) {
     153                2:     Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
     154                2:     return true;
     155                 :   }
     156                 : 
     157               20:   QualType Ty = Context.getObjCProtoType();
                        0: branch 1 not taken
                       20: branch 2 taken
     158               20:   if (Ty.isNull())
     159                0:     return true;
     160               20:   Ty = Context.getObjCObjectPointerType(Ty);
                       20: branch 1 taken
                        0: branch 2 not taken
     161               20:   return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
     162                 : }
     163                 : 
     164                 : bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
     165                 :                                      Selector Sel, ObjCMethodDecl *Method,
     166                 :                                      bool isClassMessage,
     167                 :                                      SourceLocation lbrac, SourceLocation rbrac,
     168             1659:                                      QualType &ReturnType) {
                       88: branch 0 taken
                     1571: branch 1 taken
     169             1659:   if (!Method) {
     170                 :     // Apply default argument promotion as for (C99 6.5.2.2p6).
                       30: branch 0 taken
                       88: branch 1 taken
     171              118:     for (unsigned i = 0; i != NumArgs; i++)
     172               30:       DefaultArgumentPromotion(Args[i]);
     173                 : 
     174                 :     unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found :
                       24: branch 0 taken
                       64: branch 1 taken
     175               88:                                        diag::warn_inst_method_not_found;
     176                 :     Diag(lbrac, DiagID)
     177               88:       << Sel << isClassMessage << SourceRange(lbrac, rbrac);
     178               88:     ReturnType = Context.getObjCIdType();
     179               88:     return false;
     180                 :   }
     181                 : 
     182             1571:   ReturnType = Method->getResultType();
     183                 : 
     184             1571:   unsigned NumNamedArgs = Sel.getNumArgs();
                        0: branch 0 not taken
                     1571: branch 1 taken
     185             1571:   assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
     186                 : 
     187             1571:   bool IsError = false;
                      627: branch 0 taken
                     1571: branch 1 taken
     188             2198:   for (unsigned i = 0; i < NumNamedArgs; i++) {
     189              627:     Expr *argExpr = Args[i];
                        0: branch 0 not taken
                      627: branch 1 taken
     190              627:     assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
     191                 : 
     192              627:     QualType lhsType = Method->param_begin()[i]->getType();
     193              627:     QualType rhsType = argExpr->getType();
     194                 : 
     195                 :     // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
                        0: branch 2 not taken
                      627: branch 3 taken
     196              627:     if (lhsType->isArrayType())
     197                0:       lhsType = Context.getArrayDecayedType(lhsType);
                        0: branch 2 not taken
                      627: branch 3 taken
     198              627:     else if (lhsType->isFunctionType())
     199                0:       lhsType = Context.getPointerType(lhsType);
     200                 : 
     201                 :     AssignConvertType Result =
     202              627:       CheckSingleAssignmentConstraints(lhsType, argExpr);
                      258: branch 0 taken
                      369: branch 1 taken
     203              627:     if (Args[i] != argExpr) // The expression was converted.
     204              258:       Args[i] = argExpr; // Make sure we store the converted expression.
     205                 : 
     206                 :     IsError |=
     207                 :       DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
     208              627:                                argExpr, AA_Sending);
     209                 :   }
     210                 : 
     211                 :   // Promote additional arguments to variadic methods.
                       47: branch 1 taken
                     1524: branch 2 taken
     212             1571:   if (Method->isVariadic()) {
                      163: branch 0 taken
                       47: branch 1 taken
     213              210:     for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
     214              163:       IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod);
     215                 :   } else {
     216                 :     // Check for extra arguments to non-variadic methods.
                        1: branch 0 taken
                     1523: branch 1 taken
     217             1524:     if (NumArgs != NumNamedArgs) {
     218                 :       Diag(Args[NumNamedArgs]->getLocStart(),
     219                 :            diag::err_typecheck_call_too_many_args)
     220                 :         << 2 /*method*/ << Method->getSourceRange()
     221                 :         << SourceRange(Args[NumNamedArgs]->getLocStart(),
     222                1:                        Args[NumArgs-1]->getLocEnd());
     223                 :     }
     224                 :   }
     225                 : 
     226             1571:   return IsError;
     227                 : }
     228                 : 
     229               68: bool Sema::isSelfExpr(Expr *RExpr) {
                       55: branch 1 taken
                       13: branch 2 taken
     230               68:   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr))
                        9: branch 4 taken
                       46: branch 5 taken
     231               55:     if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
     232                9:       return true;
     233               59:   return false;
     234                 : }
     235                 : 
     236                 : // Helper method for ActOnClassMethod/ActOnInstanceMethod.
     237                 : // Will search "local" class/category implementations for a method decl.
     238                 : // If failed, then we search in class's root for an instance method.
     239                 : // Returns 0 if no method is found.
     240                 : ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
     241               87:                                           ObjCInterfaceDecl *ClassDecl) {
     242               87:   ObjCMethodDecl *Method = 0;
     243                 :   // lookup in class and all superclasses
                      166: branch 0 taken
                       77: branch 1 taken
                      156: branch 2 taken
                       10: branch 3 taken
     244              330:   while (ClassDecl && !Method) {
                       66: branch 1 taken
                       90: branch 2 taken
     245              156:     if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
     246               66:       Method = ImpDecl->getClassMethod(Sel);
     247                 : 
     248                 :     // Look through local category implementations associated with the class.
                      140: branch 0 taken
                       16: branch 1 taken
     249              156:     if (!Method)
     250              140:       Method = ClassDecl->getCategoryClassMethod(Sel);
     251                 : 
     252                 :     // Before we give up, check if the selector is an instance method.
     253                 :     // But only in the root. This matches gcc's behaviour and what the
     254                 :     // runtime expects.
                      134: branch 0 taken
                       22: branch 1 taken
                       65: branch 3 taken
                       69: branch 4 taken
                       65: branch 5 taken
                       91: branch 6 taken
     255              156:     if (!Method && !ClassDecl->getSuperClass()) {
     256               65:       Method = ClassDecl->lookupInstanceMethod(Sel);
     257                 :       // Look through local category implementations associated
     258                 :       // with the root class.
                       30: branch 0 taken
                       35: branch 1 taken
     259               65:       if (!Method)
     260               30:         Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
     261                 :     }
     262                 : 
     263              156:     ClassDecl = ClassDecl->getSuperClass();
     264                 :   }
     265               87:   return Method;
     266                 : }
     267                 : 
     268                 : ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
     269              103:                                               ObjCInterfaceDecl *ClassDecl) {
     270              103:   ObjCMethodDecl *Method = 0;
                      117: branch 0 taken
                       96: branch 1 taken
                      110: branch 2 taken
                        7: branch 3 taken
     271              316:   while (ClassDecl && !Method) {
     272                 :     // If we have implementations in scope, check "private" methods.
                       20: branch 1 taken
                       90: branch 2 taken
     273              110:     if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
     274               20:       Method = ImpDecl->getInstanceMethod(Sel);
     275                 : 
     276                 :     // Look through local category implementations associated with the class.
                      101: branch 0 taken
                        9: branch 1 taken
     277              110:     if (!Method)
     278              101:       Method = ClassDecl->getCategoryInstanceMethod(Sel);
     279              110:     ClassDecl = ClassDecl->getSuperClass();
     280                 :   }
     281              103:   return Method;
     282                 : }
     283                 : 
     284                 : Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
     285                 :   IdentifierInfo &receiverName,
     286                 :   IdentifierInfo &propertyName,
     287                 :   SourceLocation &receiverNameLoc,
     288               17:   SourceLocation &propertyNameLoc) {
     289                 : 
     290               17:   IdentifierInfo *receiverNamePtr = &receiverName;
     291               17:   ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
     292                 : 
     293                 :   // Search for a declared property first.
     294                 : 
     295               17:   Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
     296               17:   ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
     297                 : 
     298                 :   // If this reference is in an @implementation, check for 'private' methods.
                        3: branch 0 taken
                       14: branch 1 taken
     299               17:   if (!Getter)
                        0: branch 1 not taken
                        3: branch 2 taken
     300                3:     if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
                        0: branch 1 not taken
                        0: branch 2 not taken
     301                0:       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
                        0: branch 1 not taken
                        0: branch 2 not taken
     302                0:         if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
     303                0:           Getter = ImpDecl->getClassMethod(Sel);
     304                 : 
                       14: branch 0 taken
                        3: branch 1 taken
     305               17:   if (Getter) {
     306                 :     // FIXME: refactor/share with ActOnMemberReference().
     307                 :     // Check if we can reference this property.
                        0: branch 1 not taken
                       14: branch 2 taken
     308               14:     if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
     309                0:       return ExprError();
     310                 :   }
     311                 : 
     312                 :   // Look for the matching setter, in case it is needed.
     313                 :   Selector SetterSel =
     314                 :     SelectorTable::constructSetterName(PP.getIdentifierTable(),
     315               17:                                        PP.getSelectorTable(), &propertyName);
     316                 : 
     317               17:   ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
                        3: branch 0 taken
                       14: branch 1 taken
     318               17:   if (!Setter) {
     319                 :     // If this reference is in an @implementation, also check for 'private'
     320                 :     // methods.
                        0: branch 1 not taken
                        3: branch 2 taken
     321                3:     if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
                        0: branch 1 not taken
                        0: branch 2 not taken
     322                0:       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
                        0: branch 1 not taken
                        0: branch 2 not taken
     323                0:         if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
     324                0:           Setter = ImpDecl->getClassMethod(SetterSel);
     325                 :   }
     326                 :   // Look through local category implementations associated with the class.
                        3: branch 0 taken
                       14: branch 1 taken
     327               17:   if (!Setter)
     328                3:     Setter = IFace->getCategoryClassMethod(SetterSel);
     329                 : 
                       14: branch 0 taken
                        3: branch 1 taken
                        0: branch 3 not taken
                       14: branch 4 taken
                        0: branch 5 not taken
                       17: branch 6 taken
     330               17:   if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
     331                0:     return ExprError();
     332                 : 
                        3: branch 0 taken
                       14: branch 1 taken
                        2: branch 2 taken
                        1: branch 3 taken
     333               17:   if (Getter || Setter) {
     334               16:     QualType PType;
     335                 : 
                       14: branch 0 taken
                        2: branch 1 taken
     336               16:     if (Getter)
     337               14:       PType = Getter->getResultType();
     338                 :     else {
                        2: branch 1 taken
                        2: branch 2 taken
     339                6:       for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
     340                2:            E = Setter->param_end(); PI != E; ++PI)
     341                2:         PType = (*PI)->getType();
     342                 :     }
     343                 :     return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
     344                 :                                   Getter, PType, Setter,
                       16: branch 1 taken
                        0: branch 2 not taken
     345               16:                                   propertyNameLoc, IFace, receiverNameLoc));
     346                 :   }
     347                 :   return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
     348                1:                      << &propertyName << Context.getObjCInterfaceType(IFace));
     349                 : }
     350                 : 
     351                 : 
     352                 : // ActOnClassMessage - used for both unary and keyword messages.
     353                 : // ArgExprs is optional - if it is present, the number of expressions
     354                 : // is obtained from Sel.getNumArgs().
     355                 : Sema::ExprResult Sema::ActOnClassMessage(
     356                 :   Scope *S,
     357                 :   IdentifierInfo *receiverName, Selector Sel,
     358                 :   SourceLocation lbrac, SourceLocation receiverLoc,
     359                 :   SourceLocation selectorLoc, SourceLocation rbrac,
     360              550:   ExprTy **Args, unsigned NumArgs) {
                        0: branch 0 not taken
                      550: branch 1 taken
     361              550:   assert(receiverName && "missing receiver class name");
     362                 : 
     363              550:   Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
     364              550:   ObjCInterfaceDecl* ClassDecl = 0;
     365              550:   bool isSuper = false;
     366                 : 
                      105: branch 1 taken
                      445: branch 2 taken
     367              550:   if (receiverName->isStr("super")) {
                       96: branch 1 taken
                        9: branch 2 taken
     368              105:     if (getCurMethodDecl()) {
     369               96:       isSuper = true;
     370               96:       ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
                        1: branch 0 taken
                       95: branch 1 taken
     371               96:       if (!OID)
     372                 :         return Diag(lbrac, diag::error_no_super_class_message)
     373                1:                       << getCurMethodDecl()->getDeclName();
     374               95:       ClassDecl = OID->getSuperClass();
                        1: branch 0 taken
                       94: branch 1 taken
     375               95:       if (!ClassDecl)
     376                1:         return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
                       66: branch 2 taken
                       28: branch 3 taken
     377               94:       if (getCurMethodDecl()->isInstanceMethod()) {
     378               66:         QualType superTy = Context.getObjCInterfaceType(ClassDecl);
     379               66:         superTy = Context.getObjCObjectPointerType(superTy);
     380                 :         ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
                       66: branch 2 taken
                        0: branch 3 not taken
     381               66:                                                               superTy);
     382                 :         // We are really in an instance method, redirect.
     383                 :         return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
     384               66:                                     selectorLoc, rbrac, Args, NumArgs);
     385                 :       }
     386                 :       // We are sending a message to 'super' within a class method. Do nothing,
     387                 :       // the receiver will pass through as 'super' (how convenient:-).
     388                 :     } else {
     389                 :       // 'super' has been used outside a method context. If a variable named
     390                 :       // 'super' has been declared, redirect. If not, produce a diagnostic.
     391                 :       NamedDecl *SuperDecl
     392                9:         = LookupSingleName(S, receiverName, LookupOrdinaryName);
     393                9:       ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
                        7: branch 0 taken
                        2: branch 1 taken
     394                9:       if (VD) {
     395                 :         ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
                        7: branch 2 taken
                        0: branch 3 not taken
     396                7:                                                             receiverLoc);
     397                 :         // We are really in an instance method, redirect.
     398                 :         return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
     399                7:                                     selectorLoc, rbrac, Args, NumArgs);
     400                 :       }
                        1: branch 1 taken
                        1: branch 2 taken
     401                2:       else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
     402                 :         const ObjCInterfaceType *OCIT;
     403                1:         OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
                        0: branch 0 not taken
                        1: branch 1 taken
     404                1:         if (!OCIT) {
     405                0:           Diag(receiverLoc, diag::err_invalid_receiver_to_message);
     406                0:           return true;
     407                 :         }
     408                1:         ClassDecl = OCIT->getDecl();
     409                 :       }
     410                 :       else      
     411                1:         return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
     412                 :     }
     413                 :   } else
     414              445:     ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
     415                 : 
     416                 :   // The following code allows for the following GCC-ism:
     417                 :   //
     418                 :   //  typedef XCElementDisplayRect XCElementGraphicsRect;
     419                 :   //
     420                 :   //  @implementation XCRASlice
     421                 :   //  - whatever { // Note that XCElementGraphicsRect is a typedef name.
     422                 :   //    _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
     423                 :   //  }
     424                 :   //
     425                 :   // If necessary, the following lookup could move to getObjCInterfaceDecl().
                        2: branch 0 taken
                      472: branch 1 taken
     426              474:   if (!ClassDecl) {
     427                 :     NamedDecl *IDecl
     428                2:       = LookupSingleName(TUScope, receiverName, LookupOrdinaryName);
                        2: branch 1 taken
                        0: branch 2 not taken
     429                2:     if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
     430                 :       const ObjCInterfaceType *OCIT;
     431                2:       OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
                        1: branch 0 taken
                        1: branch 1 taken
     432                2:       if (!OCIT) {
     433                1:         Diag(receiverLoc, diag::err_invalid_receiver_to_message);
     434                1:         return true;
     435                 :       }
     436                1:       ClassDecl = OCIT->getDecl();
     437                 :     }
     438                 :   }
                        0: branch 0 not taken
                      473: branch 1 taken
     439              473:   assert(ClassDecl && "missing interface declaration");
     440              473:   ObjCMethodDecl *Method = 0;
     441              473:   QualType returnType;
                        2: branch 1 taken
                      471: branch 2 taken
     442              473:   if (ClassDecl->isForwardDecl()) {
     443                 :     // A forward class used in messaging is tread as a 'Class'
     444                2:     Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
     445                2:     Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
                        1: branch 0 taken
                        1: branch 1 taken
     446                2:     if (Method)
     447                 :       Diag(Method->getLocation(), diag::note_method_sent_forward_class)
     448                1:         << Method->getDeclName();
     449                 :   }
                      472: branch 0 taken
                        1: branch 1 taken
     450              473:   if (!Method)
     451              472:     Method = ClassDecl->lookupClassMethod(Sel);
     452                 : 
     453                 :   // If we have an implementation in scope, check "private" methods.
                       75: branch 0 taken
                      398: branch 1 taken
     454              473:   if (!Method)
     455               75:     Method = LookupPrivateClassMethod(Sel, ClassDecl);
     456                 : 
                      449: branch 0 taken
                       24: branch 1 taken
                        0: branch 3 not taken
                      449: branch 4 taken
                        0: branch 5 not taken
                      473: branch 6 taken
     457              473:   if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
     458                0:     return true;
     459                 : 
                        0: branch 1 not taken
                      473: branch 2 taken
     460              473:   if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
     461                 :                                 lbrac, rbrac, returnType))
     462                0:     return true;
     463                 : 
     464              473:   returnType = returnType.getNonReferenceType();
     465                 : 
     466                 :   // If we have the ObjCInterfaceDecl* for the class that is receiving the
     467                 :   // message, use that to construct the ObjCMessageExpr.  Otherwise pass on the
     468                 :   // IdentifierInfo* for the class.
     469                 :   // FIXME: need to do a better job handling 'super' usage within a class.  For
     470                 :   // now, we simply pass the "super" identifier through (which isn't consistent
     471                 :   // with instance methods.
                       28: branch 0 taken
                      445: branch 1 taken
     472              473:   if (isSuper)
     473                 :     return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method,
                       28: branch 1 taken
                        0: branch 2 not taken
     474               28:                                          lbrac, rbrac, ArgExprs, NumArgs);
     475                 :   else
     476                 :     return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
                      445: branch 1 taken
                        0: branch 2 not taken
     477              445:                                          lbrac, rbrac, ArgExprs, NumArgs);
     478                 : }
     479                 : 
     480                 : // ActOnInstanceMessage - used for both unary and keyword messages.
     481                 : // ArgExprs is optional - if it is present, the number of expressions
     482                 : // is obtained from Sel.getNumArgs().
     483                 : Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
     484                 :                                             SourceLocation lbrac,
     485                 :                                             SourceLocation receiverLoc,
     486                 :                                             SourceLocation rbrac,
     487             1187:                                             ExprTy **Args, unsigned NumArgs) {
                        0: branch 0 not taken
                     1187: branch 1 taken
     488             1187:   assert(receiver && "missing receiver expression");
     489                 : 
     490             1187:   Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
     491             1187:   Expr *RExpr = static_cast<Expr *>(receiver);
     492                 : 
     493                 :   // If necessary, apply function/array conversion to the receiver.
     494                 :   // C99 6.7.5.3p[7,8].
     495             1187:   DefaultFunctionArrayLvalueConversion(RExpr);
     496                 : 
     497             1187:   QualType returnType;
     498                 :   QualType ReceiverCType =
     499             1187:     Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
     500                 : 
     501                 :   // Handle messages to 'super'.
                       66: branch 1 taken
                     1121: branch 2 taken
     502             1187:   if (isa<ObjCSuperExpr>(RExpr)) {
     503               66:     ObjCMethodDecl *Method = 0;
                       66: branch 1 taken
                        0: branch 2 not taken
     504               66:     if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
     505                 :       // If we have an interface in scope, check 'super' methods.
                       66: branch 1 taken
                        0: branch 2 not taken
     506               66:       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
                       66: branch 1 taken
                        0: branch 2 not taken
     507               66:         if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) {
     508               66:           Method = SuperDecl->lookupInstanceMethod(Sel);
     509                 : 
                       12: branch 0 taken
                       54: branch 1 taken
     510               66:           if (!Method)
     511                 :             // If we have implementations in scope, check "private" methods.
     512               12:             Method = LookupPrivateInstanceMethod(Sel, SuperDecl);
     513                 :         }
     514                 :     }
     515                 : 
                       57: branch 0 taken
                        9: branch 1 taken
                        0: branch 3 not taken
                       57: branch 4 taken
                        0: branch 5 not taken
                       66: branch 6 taken
     516               66:     if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
     517                0:       return true;
     518                 : 
                        0: branch 1 not taken
                       66: branch 2 taken
     519               66:     if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
     520                 :                                   lbrac, rbrac, returnType))
     521                0:       return true;
     522                 : 
     523               66:     returnType = returnType.getNonReferenceType();
     524                 :     return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
                       66: branch 1 taken
                        0: branch 2 not taken
     525               66:                                          rbrac, ArgExprs, NumArgs);
     526                 :   }
     527                 : 
     528                 :   // Handle messages to id.
                      687: branch 2 taken
                      434: branch 3 taken
                      681: branch 6 taken
                        6: branch 7 taken
                        4: branch 10 taken
                      677: branch 11 taken
                      444: branch 12 taken
                      677: branch 13 taken
     529             1121:   if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
     530                 :       Context.isObjCNSObjectType(RExpr->getType())) {
     531                 :     ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
     532              444:                                Sel, SourceRange(lbrac,rbrac));
                       30: branch 0 taken
                      414: branch 1 taken
     533              444:     if (!Method)
     534               30:       Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
                        2: branch 1 taken
                      442: branch 2 taken
     535              444:     if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
     536                 :                                   lbrac, rbrac, returnType))
     537                2:       return true;
     538              442:     returnType = returnType.getNonReferenceType();
     539                 :     return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
                      442: branch 1 taken
                        0: branch 2 not taken
     540              442:                                          rbrac, ArgExprs, NumArgs);
     541                 :   }
     542                 : 
     543                 :   // Handle messages to Class.
                      653: branch 2 taken
                       24: branch 3 taken
                        2: branch 6 taken
                      651: branch 7 taken
                       26: branch 8 taken
                      651: branch 9 taken
     544              677:   if (ReceiverCType->isObjCClassType() ||
     545                 :       ReceiverCType->isObjCQualifiedClassType()) {
     546               26:     ObjCMethodDecl *Method = 0;
     547                 : 
                       18: branch 1 taken
                        8: branch 2 taken
     548               26:     if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
                       18: branch 1 taken
                        0: branch 2 not taken
     549               18:       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
     550                 :         // First check the public methods in the class interface.
     551               18:         Method = ClassDecl->lookupClassMethod(Sel);
     552                 : 
                       12: branch 0 taken
                        6: branch 1 taken
     553               18:         if (!Method)
     554               12:           Method = LookupPrivateClassMethod(Sel, ClassDecl);
     555                 : 
     556                 :         // FIXME: if we still haven't found a method, we need to look in
     557                 :         // protocols (if we have qualifiers).
     558                 :       }
                       13: branch 0 taken
                        5: branch 1 taken
                        0: branch 3 not taken
                       13: branch 4 taken
                        0: branch 5 not taken
                       18: branch 6 taken
     559               18:       if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
     560                0:         return true;
     561                 :     }
                       13: branch 0 taken
                       13: branch 1 taken
     562               26:     if (!Method) {
     563                 :       // If not messaging 'self', look for any factory method named 'Sel'.
                       10: branch 1 taken
                        3: branch 2 taken
     564               13:       if (!isSelfExpr(RExpr)) {
     565               10:         Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
                        3: branch 0 taken
                        7: branch 1 taken
     566               10:         if (!Method) {
     567                 :           // If no class (factory) method was found, check if an _instance_
     568                 :           // method of the same name exists in the root class only.
     569                 :           Method = LookupInstanceMethodInGlobalPool(
     570                3:                                    Sel, SourceRange(lbrac,rbrac));
                        3: branch 0 taken
                        0: branch 1 not taken
     571                3:           if (Method)
                        2: branch 0 taken
                        1: branch 1 taken
     572                3:               if (const ObjCInterfaceDecl *ID =
     573                3:                 dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
                        1: branch 1 taken
                        1: branch 2 taken
     574                2:               if (ID->getSuperClass())
     575                 :                 Diag(lbrac, diag::warn_root_inst_method_not_found)
     576                1:                   << Sel << SourceRange(lbrac, rbrac);
     577                 :             }
     578                 :         }
     579                 :       }
     580                 :     }
                        0: branch 1 not taken
                       26: branch 2 taken
     581               26:     if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
     582                 :                                   lbrac, rbrac, returnType))
     583                0:       return true;
     584               26:     returnType = returnType.getNonReferenceType();
     585                 :     return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
                       26: branch 1 taken
                        0: branch 2 not taken
     586               26:                                          rbrac, ArgExprs, NumArgs);
     587                 :   }
     588                 : 
     589              651:   ObjCMethodDecl *Method = 0;
     590              651:   ObjCInterfaceDecl* ClassDecl = 0;
     591                 : 
     592                 :   // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
     593                 :   // long as one of the protocols implements the selector (if not, warn).
                       23: branch 0 taken
                      628: branch 1 taken
     594              651:   if (const ObjCObjectPointerType *QIdTy =
     595              651:         ReceiverCType->getAsObjCQualifiedIdType()) {
     596                 :     // Search protocols for instance methods.
                       23: branch 1 taken
                        1: branch 2 taken
     597               47:     for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
     598               23:          E = QIdTy->qual_end(); I != E; ++I) {
     599               23:       ObjCProtocolDecl *PDecl = *I;
                       23: branch 0 taken
                        0: branch 1 not taken
                       20: branch 3 taken
                        3: branch 4 taken
                       20: branch 5 taken
                        3: branch 6 taken
     600               23:       if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
     601               20:         break;
     602                 :       // Since we aren't supporting "Class<foo>", look for a class method.
                        3: branch 0 taken
                        0: branch 1 not taken
                        2: branch 3 taken
                        1: branch 4 taken
                        2: branch 5 taken
                        1: branch 6 taken
     603                3:       if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
     604                2:         break;
     605                 :     }
                      620: branch 0 taken
                        8: branch 1 taken
     606              628:   } else if (const ObjCObjectPointerType *OCIType =
     607              628:                 ReceiverCType->getAsObjCInterfacePointerType()) {
     608                 :     // We allow sending a message to a pointer to an interface (an object).
     609                 : 
     610              620:     ClassDecl = OCIType->getInterfaceDecl();
     611                 :     // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
     612                 :     // faster than the following method (which can do *many* linear searches).
     613                 :     // The idea is to add class info to InstanceMethodPool.
     614              620:     Method = ClassDecl->lookupInstanceMethod(Sel);
     615                 : 
                       66: branch 0 taken
                      554: branch 1 taken
     616              620:     if (!Method) {
     617                 :       // Search protocol qualifiers.
                        6: branch 1 taken
                       61: branch 2 taken
     618              133:       for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
     619               66:            E = OCIType->qual_end(); QI != E; ++QI) {
                        5: branch 1 taken
                        1: branch 2 taken
     620                6:         if ((Method = (*QI)->lookupInstanceMethod(Sel)))
     621                5:           break;
     622                 :       }
     623                 :     }
                       61: branch 0 taken
                      559: branch 1 taken
     624              620:     if (!Method) {
     625                 :       // If we have implementations in scope, check "private" methods.
     626               61:       Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
     627                 : 
                       50: branch 0 taken
                       11: branch 1 taken
                       48: branch 3 taken
                        2: branch 4 taken
                       48: branch 5 taken
                       13: branch 6 taken
     628               61:       if (!Method && !isSelfExpr(RExpr)) {
     629                 :         // If we still haven't found a method, look in the global pool. This
     630                 :         // behavior isn't very desirable, however we need it for GCC
     631                 :         // compatibility. FIXME: should we deviate??
                       47: branch 1 taken
                        1: branch 2 taken
     632               48:         if (OCIType->qual_empty()) {
     633                 :           Method = LookupInstanceMethodInGlobalPool(
     634               47:                                Sel, SourceRange(lbrac,rbrac));
                       32: branch 0 taken
                       15: branch 1 taken
                        2: branch 4 taken
                       30: branch 5 taken
                        2: branch 6 taken
                       45: branch 7 taken
     635               47:           if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
     636                 :             Diag(lbrac, diag::warn_maynot_respond)
     637                2:               << OCIType->getInterfaceDecl()->getIdentifier()->getName() << Sel;
     638                 :         }
     639                 :       }
     640                 :     }
                      602: branch 0 taken
                       18: branch 1 taken
                        0: branch 3 not taken
                      602: branch 4 taken
                        0: branch 5 not taken
                      620: branch 6 taken
     641              620:     if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
     642                0:       return true;
                        8: branch 2 taken
                        0: branch 3 not taken
                        4: branch 6 taken
                        4: branch 7 taken
                        3: branch 10 taken
                        1: branch 11 taken
                        3: branch 14 taken
                        0: branch 15 not taken
                        7: branch 16 taken
                        1: branch 17 taken
     643                8:   } else if (!Context.getObjCIdType().isNull() &&
     644                 :              (ReceiverCType->isPointerType() ||
     645                 :               (ReceiverCType->isIntegerType() &&
     646                 :                ReceiverCType->isScalarType()))) {
     647                 :     // Implicitly convert integers and pointers to 'id' but emit a warning.
     648                 :     Diag(lbrac, diag::warn_bad_receiver_type)
     649                7:       << RExpr->getType() << RExpr->getSourceRange();
                        4: branch 2 taken
                        3: branch 3 taken
     650                7:     if (ReceiverCType->isPointerType())
     651                4:       ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast);
     652                 :     else
     653                 :       ImpCastExprToType(RExpr, Context.getObjCIdType(),
     654                3:                         CastExpr::CK_IntegralToPointer);
     655                 :   } else {
     656                 :     // Reject other random receiver types (e.g. structs).
     657                 :     Diag(lbrac, diag::err_bad_receiver_type)
     658                1:       << RExpr->getType() << RExpr->getSourceRange();
     659                1:     return true;
     660                 :   }
     661                 : 
                      624: branch 0 taken
                       26: branch 1 taken
     662              650:   if (Method)
     663              624:     DiagnoseSentinelCalls(Method, receiverLoc, ArgExprs, NumArgs);
                        1: branch 1 taken
                      649: branch 2 taken
     664              650:   if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
     665                 :                                 lbrac, rbrac, returnType))
     666                1:     return true;
     667              649:   returnType = returnType.getNonReferenceType();
     668                 :   return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
                      649: branch 1 taken
                        0: branch 2 not taken
     669              649:                                        rbrac, ArgExprs, NumArgs);
     670                 : }
     671                 : 

Generated: 2010-02-10 01:31 by zcov