zcov: / lib/Parse/ParseObjc.cpp


Files: 1 Branches Taken: 81.7% 414 / 507
Generated: 2010-02-10 01:31 Branches Executed: 98.8% 501 / 507
Line Coverage: 90.6% 788 / 870


Programs: 2 Runs 3018


       1                 : //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
       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 the Objective-C portions of the Parser interface.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Parse/Parser.h"
      15                 : #include "clang/Parse/DeclSpec.h"
      16                 : #include "clang/Parse/Scope.h"
      17                 : #include "clang/Parse/ParseDiagnostic.h"
      18                 : #include "llvm/ADT/SmallVector.h"
      19                 : using namespace clang;
      20                 : 
      21                 : 
      22                 : /// ParseObjCAtDirectives - Handle parts of the external-declaration production:
      23                 : ///       external-declaration: [C99 6.9]
      24                 : /// [OBJC]  objc-class-definition
      25                 : /// [OBJC]  objc-class-declaration
      26                 : /// [OBJC]  objc-alias-declaration
      27                 : /// [OBJC]  objc-protocol-definition
      28                 : /// [OBJC]  objc-method-definition
      29                 : /// [OBJC]  '@' 'end'
      30             4381: Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
      31             4381:   SourceLocation AtLoc = ConsumeToken(); // the "@"
      32                 : 
                        2: branch 1 taken
                     4379: branch 2 taken
      33             4381:   if (Tok.is(tok::code_completion)) {
      34                2:     Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
      35                2:     ConsumeToken();
      36                 :   }
      37                 : 
                      391: branch 1 taken
                     1738: branch 2 taken
                      730: branch 3 taken
                      652: branch 4 taken
                      633: branch 5 taken
                       10: branch 6 taken
                      167: branch 7 taken
                       58: branch 8 taken
                        2: branch 9 taken
      38             4381:   switch (Tok.getObjCKeywordID()) {
      39                 :   case tok::objc_class:
      40              391:     return ParseObjCAtClassDeclaration(AtLoc);
      41                 :   case tok::objc_interface:
      42             1738:     return ParseObjCAtInterfaceDeclaration(AtLoc);
      43                 :   case tok::objc_protocol:
      44              730:     return ParseObjCAtProtocolDeclaration(AtLoc);
      45                 :   case tok::objc_implementation:
      46              652:     return ParseObjCAtImplementationDeclaration(AtLoc);
      47                 :   case tok::objc_end:
      48              633:     return ParseObjCAtEndDeclaration(AtLoc);
      49                 :   case tok::objc_compatibility_alias:
      50               10:     return ParseObjCAtAliasDeclaration(AtLoc);
      51                 :   case tok::objc_synthesize:
      52              167:     return ParseObjCPropertySynthesize(AtLoc);
      53                 :   case tok::objc_dynamic:
      54               58:     return ParseObjCPropertyDynamic(AtLoc);
      55                 :   default:
      56                2:     Diag(AtLoc, diag::err_unexpected_at);
      57                2:     SkipUntil(tok::semi);
      58                2:     return DeclPtrTy();
      59                 :   }
      60                 : }
      61                 : 
      62                 : ///
      63                 : /// objc-class-declaration:
      64                 : ///    '@' 'class' identifier-list ';'
      65                 : ///
      66              391: Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
      67              391:   ConsumeToken(); // the identifier "class"
      68              391:   llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
      69              391:   llvm::SmallVector<SourceLocation, 8> ClassLocs;
      70                 : 
      71                 : 
      72              867:   while (1) {
                        0: branch 1 not taken
                     1258: branch 2 taken
      73             1258:     if (Tok.isNot(tok::identifier)) {
      74                0:       Diag(Tok, diag::err_expected_ident);
      75                0:       SkipUntil(tok::semi);
      76                0:       return DeclPtrTy();
      77                 :     }
      78             1258:     ClassNames.push_back(Tok.getIdentifierInfo());
      79             1258:     ClassLocs.push_back(Tok.getLocation());
      80             1258:     ConsumeToken();
      81                 : 
                      867: branch 1 taken
                      391: branch 2 taken
      82             1258:     if (Tok.isNot(tok::comma))
      83              391:       break;
      84                 : 
      85              867:     ConsumeToken();
      86                 :   }
      87                 : 
      88                 :   // Consume the ';'.
                        0: branch 1 not taken
                      391: branch 2 taken
      89              391:   if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
      90                0:     return DeclPtrTy();
      91                 : 
      92                 :   return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
      93                 :                                               ClassLocs.data(),
      94              391:                                               ClassNames.size());
      95                 : }
      96                 : 
      97                 : ///
      98                 : ///   objc-interface:
      99                 : ///     objc-class-interface-attributes[opt] objc-class-interface
     100                 : ///     objc-category-interface
     101                 : ///
     102                 : ///   objc-class-interface:
     103                 : ///     '@' 'interface' identifier objc-superclass[opt]
     104                 : ///       objc-protocol-refs[opt]
     105                 : ///       objc-class-instance-variables[opt]
     106                 : ///       objc-interface-decl-list
     107                 : ///     @end
     108                 : ///
     109                 : ///   objc-category-interface:
     110                 : ///     '@' 'interface' identifier '(' identifier[opt] ')'
     111                 : ///       objc-protocol-refs[opt]
     112                 : ///       objc-interface-decl-list
     113                 : ///     @end
     114                 : ///
     115                 : ///   objc-superclass:
     116                 : ///     ':' identifier
     117                 : ///
     118                 : ///   objc-class-interface-attributes:
     119                 : ///     __attribute__((visibility("default")))
     120                 : ///     __attribute__((visibility("hidden")))
     121                 : ///     __attribute__((deprecated))
     122                 : ///     __attribute__((unavailable))
     123                 : ///     __attribute__((objc_exception)) - used by NSException on 64-bit
     124                 : ///
     125                 : Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
     126             1753:   SourceLocation atLoc, AttributeList *attrList) {
     127                 :   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
                     1753: branch 1 taken
                        0: branch 2 not taken
     128             1753:          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
     129             1753:   ConsumeToken(); // the "interface" identifier
     130                 : 
     131                 :   // Code completion after '@interface'.
                        2: branch 1 taken
                     1751: branch 2 taken
     132             1753:   if (Tok.is(tok::code_completion)) {
     133                2:     Actions.CodeCompleteObjCInterfaceDecl(CurScope);
     134                2:     ConsumeToken();
     135                 :   }
     136                 : 
                        2: branch 1 taken
                     1751: branch 2 taken
     137             1753:   if (Tok.isNot(tok::identifier)) {
     138                2:     Diag(Tok, diag::err_expected_ident); // missing class or category name.
     139                2:     return DeclPtrTy();
     140                 :   }
     141                 : 
     142                 :   // We have a class or category name - consume it.
     143             1751:   IdentifierInfo *nameId = Tok.getIdentifierInfo();
     144             1751:   SourceLocation nameLoc = ConsumeToken();
     145                 : 
                      189: branch 1 taken
                     1562: branch 2 taken
     146             1751:   if (Tok.is(tok::l_paren)) { // we have a category.
     147              189:     SourceLocation lparenLoc = ConsumeParen();
     148              189:     SourceLocation categoryLoc, rparenLoc;
     149              189:     IdentifierInfo *categoryId = 0;
     150                 : 
                        2: branch 1 taken
                      187: branch 2 taken
     151              189:     if (Tok.is(tok::code_completion)) {
     152                2:       Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId);
     153                2:       ConsumeToken();
     154                 :     }
     155                 :     
     156                 :     // For ObjC2, the category name is optional (not an error).
                      158: branch 1 taken
                       31: branch 2 taken
     157              189:     if (Tok.is(tok::identifier)) {
     158              158:       categoryId = Tok.getIdentifierInfo();
     159              158:       categoryLoc = ConsumeToken();
                        0: branch 1 not taken
                       31: branch 2 taken
     160               31:     } else if (!getLang().ObjC2) {
     161                0:       Diag(Tok, diag::err_expected_ident); // missing category name.
     162                0:       return DeclPtrTy();
     163                 :     }
                        2: branch 1 taken
                      187: branch 2 taken
     164              189:     if (Tok.isNot(tok::r_paren)) {
     165                2:       Diag(Tok, diag::err_expected_rparen);
     166                2:       SkipUntil(tok::r_paren, false); // don't stop at ';'
     167                2:       return DeclPtrTy();
     168                 :     }
     169              187:     rparenLoc = ConsumeParen();
     170                 : 
     171                 :     // Next, we need to check for any protocol references.
     172              187:     SourceLocation LAngleLoc, EndProtoLoc;
     173              187:     llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
     174              187:     llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
                       18: branch 1 taken
                      169: branch 2 taken
                        0: branch 4 not taken
                       18: branch 5 taken
                        0: branch 6 not taken
                      187: branch 7 taken
     175              187:     if (Tok.is(tok::less) &&
     176                 :         ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
     177                 :                                     LAngleLoc, EndProtoLoc))
     178                0:       return DeclPtrTy();
     179                 : 
                        0: branch 0 not taken
                      187: branch 1 taken
     180              187:     if (attrList) // categories don't support attributes.
     181                0:       Diag(Tok, diag::err_objc_no_attributes_on_category);
     182                 : 
     183                 :     DeclPtrTy CategoryType =
     184                 :       Actions.ActOnStartCategoryInterface(atLoc,
     185                 :                                           nameId, nameLoc,
     186                 :                                           categoryId, categoryLoc,
     187                 :                                           ProtocolRefs.data(),
     188                 :                                           ProtocolRefs.size(),
     189                 :                                           ProtocolLocs.data(),
     190              187:                                           EndProtoLoc);
     191                 : 
     192              187:     ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
     193              187:     return CategoryType;
     194                 :   }
     195                 :   // Parse a class interface.
     196             1562:   IdentifierInfo *superClassId = 0;
     197             1562:   SourceLocation superClassLoc;
     198                 : 
                      733: branch 1 taken
                      829: branch 2 taken
     199             1562:   if (Tok.is(tok::colon)) { // a super class is specified.
     200              733:     ConsumeToken();
     201                 : 
     202                 :     // Code completion of superclass names.
                        1: branch 1 taken
                      732: branch 2 taken
     203              733:     if (Tok.is(tok::code_completion)) {
     204                1:       Actions.CodeCompleteObjCSuperclass(CurScope, nameId);
     205                1:       ConsumeToken();
     206                 :     }
     207                 : 
                        1: branch 1 taken
                      732: branch 2 taken
     208              733:     if (Tok.isNot(tok::identifier)) {
     209                1:       Diag(Tok, diag::err_expected_ident); // missing super class name.
     210                1:       return DeclPtrTy();
     211                 :     }
     212              732:     superClassId = Tok.getIdentifierInfo();
     213              732:     superClassLoc = ConsumeToken();
     214                 :   }
     215                 :   // Next, we need to check for any protocol references.
     216             1561:   llvm::SmallVector<Action::DeclPtrTy, 8> ProtocolRefs;
     217             1561:   llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
     218             1561:   SourceLocation LAngleLoc, EndProtoLoc;
                      422: branch 1 taken
                     1139: branch 2 taken
                        0: branch 4 not taken
                      422: branch 5 taken
                        0: branch 6 not taken
                     1561: branch 7 taken
     219             1561:   if (Tok.is(tok::less) &&
     220                 :       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
     221                 :                                   LAngleLoc, EndProtoLoc))
     222                0:     return DeclPtrTy();
     223                 : 
     224                 :   DeclPtrTy ClsType =
     225                 :     Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
     226                 :                                      superClassId, superClassLoc,
     227                 :                                      ProtocolRefs.data(), ProtocolRefs.size(),
     228                 :                                      ProtocolLocs.data(),
     229             1561:                                      EndProtoLoc, attrList);
     230                 : 
                      752: branch 1 taken
                      809: branch 2 taken
     231             1561:   if (Tok.is(tok::l_brace))
     232              752:     ParseObjCClassInstanceVariables(ClsType, atLoc);
     233                 : 
     234             1561:   ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
     235             1561:   return ClsType;
     236                 : }
     237                 : 
     238                 : /// The Objective-C property callback.  This should be defined where
     239                 : /// it's used, but instead it's been lifted to here to support VS2005.
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                      504: branch 6 taken
     240              504: struct Parser::ObjCPropertyCallback : FieldCallback {
     241                 :   Parser &P;
     242                 :   DeclPtrTy IDecl;
     243                 :   llvm::SmallVectorImpl<DeclPtrTy> &Props;
     244                 :   ObjCDeclSpec &OCDS;
     245                 :   SourceLocation AtLoc;
     246                 :   tok::ObjCKeywordKind MethodImplKind;
     247                 :         
     248                 :   ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
     249                 :                        llvm::SmallVectorImpl<DeclPtrTy> &Props,
     250                 :                        ObjCDeclSpec &OCDS, SourceLocation AtLoc,
     251              504:                        tok::ObjCKeywordKind MethodImplKind) :
     252                 :     P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
     253              504:     MethodImplKind(MethodImplKind) {
     254              504:   }
     255                 : 
     256              502:   DeclPtrTy invoke(FieldDeclarator &FD) {
                        7: branch 1 taken
                      495: branch 2 taken
     257              502:     if (FD.D.getIdentifier() == 0) {
     258                 :       P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
     259                7:         << FD.D.getSourceRange();
     260                7:       return DeclPtrTy();
     261                 :     }
                        1: branch 0 taken
                      494: branch 1 taken
     262              495:     if (FD.BitfieldSize) {
     263                 :       P.Diag(AtLoc, diag::err_objc_property_bitfield)
     264                1:         << FD.D.getSourceRange();
     265                1:       return DeclPtrTy();
     266                 :     }
     267                 : 
     268                 :     // Install the property declarator into interfaceDecl.
     269                 :     IdentifierInfo *SelName =
                       18: branch 1 taken
                      476: branch 2 taken
     270              494:       OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
     271                 : 
     272                 :     Selector GetterSel =
     273              494:       P.PP.getSelectorTable().getNullarySelector(SelName);
     274              494:     IdentifierInfo *SetterName = OCDS.getSetterName();
     275              494:     Selector SetterSel;
                       21: branch 0 taken
                      473: branch 1 taken
     276              494:     if (SetterName)
     277               21:       SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
     278                 :     else
     279                 :       SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
     280                 :                                                      P.PP.getSelectorTable(),
     281              473:                                                      FD.D.getIdentifier());
     282              494:     bool isOverridingProperty = false;
     283                 :     DeclPtrTy Property =
     284                 :       P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
     285                 :                               GetterSel, SetterSel, IDecl,
     286                 :                               &isOverridingProperty,
     287              494:                               MethodImplKind);
                      458: branch 0 taken
                       36: branch 1 taken
     288              494:     if (!isOverridingProperty)
     289              458:       Props.push_back(Property);
     290                 : 
     291              494:     return Property;
     292                 :   }
     293                 : };
     294                 : 
     295                 : ///   objc-interface-decl-list:
     296                 : ///     empty
     297                 : ///     objc-interface-decl-list objc-property-decl [OBJC2]
     298                 : ///     objc-interface-decl-list objc-method-requirement [OBJC2]
     299                 : ///     objc-interface-decl-list objc-method-proto ';'
     300                 : ///     objc-interface-decl-list declaration
     301                 : ///     objc-interface-decl-list ';'
     302                 : ///
     303                 : ///   objc-method-requirement: [OBJC2]
     304                 : ///     @required
     305                 : ///     @optional
     306                 : ///
     307                 : void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
     308             2409:                                         tok::ObjCKeywordKind contextKey) {
     309             2409:   llvm::SmallVector<DeclPtrTy, 32> allMethods;
     310             2409:   llvm::SmallVector<DeclPtrTy, 16> allProperties;
     311             2409:   llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
     312             2409:   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
     313                 : 
     314             2409:   SourceRange AtEnd;
     315                 : 
     316             2766:   while (1) {
     317                 :     // If this is a method prototype, parse it.
                     3376: branch 1 taken
                     1799: branch 2 taken
                      405: branch 4 taken
                     2971: branch 5 taken
                     2204: branch 6 taken
                     2971: branch 7 taken
     318             5175:     if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
     319                 :       DeclPtrTy methodPrototype =
     320             2204:         ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
     321             2204:       allMethods.push_back(methodPrototype);
     322                 :       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
     323                 :       // method definitions.
     324                 :       ExpectAndConsume(tok::semi, diag::err_expected_semi_after_method_proto,
     325             2204:                        "", tok::semi);
     326             2204:       continue;
     327                 :     }
     328                 : 
     329                 :     // Ignore excess semicolons.
                        5: branch 1 taken
                     2966: branch 2 taken
     330             2971:     if (Tok.is(tok::semi)) {
     331                5:       ConsumeToken();
     332                5:       continue;
     333                 :     }
     334                 : 
     335                 :     // If we got to the end of the file, exit the loop.
                     2957: branch 1 taken
                        9: branch 2 taken
     336             2966:     if (Tok.is(tok::eof))
     337                9:       break;
     338                 : 
     339                 :     // Code completion within an Objective-C interface.
                        1: branch 1 taken
                     2956: branch 2 taken
     340             2957:     if (Tok.is(tok::code_completion)) {
     341                 :       Actions.CodeCompleteOrdinaryName(CurScope, 
     342                 :                                   ObjCImpDecl? Action::CCC_ObjCImplementation
                        0: branch 1 not taken
                        1: branch 2 taken
     343                1:                                              : Action::CCC_ObjCInterface);
     344                1:       ConsumeToken();
     345                 :     }
     346                 :     
     347                 :     // If we don't have an @ directive, parse it as a function definition.
                       14: branch 1 taken
                     2943: branch 2 taken
     348             2957:     if (Tok.isNot(tok::at)) {
     349                 :       // The code below does not consume '}'s because it is afraid of eating the
     350                 :       // end of a namespace.  Because of the way this code is structured, an
     351                 :       // erroneous r_brace would cause an infinite loop if not handled here.
                        1: branch 1 taken
                       13: branch 2 taken
     352               14:       if (Tok.is(tok::r_brace))
     353                1:         break;
     354                 : 
     355                 :       // FIXME: as the name implies, this rule allows function definitions.
     356                 :       // We could pass a flag or check for functions during semantic analysis.
     357               13:       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(0));
     358               13:       continue;
     359                 :     }
     360                 : 
     361                 :     // Otherwise, we have an @ directive, eat the @.
     362             2943:     SourceLocation AtLoc = ConsumeToken(); // the "@"
                        1: branch 1 taken
                     2942: branch 2 taken
     363             2943:     if (Tok.is(tok::code_completion)) {
     364                1:       Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
     365                1:       ConsumeToken();
     366                1:       break;
     367                 :     }
     368                 : 
     369             2942:     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
     370                 : 
                     2398: branch 0 taken
                      544: branch 1 taken
     371             2942:     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
     372             2398:       AtEnd.setBegin(AtLoc);
     373             2398:       AtEnd.setEnd(Tok.getLocation());
     374             2398:       break;
     375                 :     }
     376                 : 
     377                 :     // Eat the identifier.
     378              544:     ConsumeToken();
     379                 : 
                        0: branch 0 not taken
                       40: branch 1 taken
                      504: branch 2 taken
     380              544:     switch (DirectiveKind) {
     381                 :     default:
     382                 :       // FIXME: If someone forgets an @end on a protocol, this loop will
     383                 :       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
     384                 :       // would probably be better to bail out if we saw an @class or @interface
     385                 :       // or something like that.
     386                0:       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
     387                 :       // Skip until we see an '@' or '}' or ';'.
     388                0:       SkipUntil(tok::r_brace, tok::at);
     389                0:       break;
     390                 : 
     391                 :     case tok::objc_required:
     392                 :     case tok::objc_optional:
     393                 :       // This is only valid on protocols.
     394                 :       // FIXME: Should this check for ObjC2 being enabled?
                        2: branch 0 taken
                       38: branch 1 taken
     395               40:       if (contextKey != tok::objc_protocol)
     396                2:         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
     397                 :       else
     398               38:         MethodImplKind = DirectiveKind;
     399               40:       break;
     400                 : 
     401                 :     case tok::objc_property:
                        0: branch 1 not taken
                      504: branch 2 taken
     402              504:       if (!getLang().ObjC2)
     403                0:         Diag(AtLoc, diag::err_objc_propertoes_require_objc2);
     404                 : 
     405              504:       ObjCDeclSpec OCDS;
     406                 :       // Parse property attribute list, if any.
                      352: branch 1 taken
                      152: branch 2 taken
     407              504:       if (Tok.is(tok::l_paren))
     408                 :         ParseObjCPropertyAttribute(OCDS, interfaceDecl,
     409              352:                                    allMethods.data(), allMethods.size());
     410                 : 
     411                 :       ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties,
     412              504:                                     OCDS, AtLoc, MethodImplKind);
     413                 : 
     414                 :       // Parse all the comma separated declarators.
     415              504:       DeclSpec DS;
     416              504:       ParseStructDeclaration(DS, Callback);
     417                 : 
     418                 :       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
     419              504:                        tok::at);
     420              504:       break;
     421                 :     }
     422                 :   }
     423                 : 
     424                 :   // We break out of the big loop in two cases: when we see @end or when we see
     425                 :   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
                        0: branch 1 not taken
                     2409: branch 2 taken
     426             2409:   if (Tok.is(tok::code_completion)) {
     427                0:     Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
     428                0:     ConsumeToken();
                     2398: branch 1 taken
                       11: branch 2 taken
     429             2409:   } else if (Tok.isObjCAtKeyword(tok::objc_end))
     430             2398:     ConsumeToken(); // the "end" identifier
     431                 :   else
     432               11:     Diag(Tok, diag::err_objc_missing_end);
     433                 : 
     434                 :   // Insert collected methods declarations into the @interface object.
     435                 :   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
     436                 :   Actions.ActOnAtEnd(AtEnd, interfaceDecl,
     437                 :                      allMethods.data(), allMethods.size(),
     438                 :                      allProperties.data(), allProperties.size(),
     439             2409:                      allTUVariables.data(), allTUVariables.size());
     440             2409: }
     441                 : 
     442                 : ///   Parse property attribute declarations.
     443                 : ///
     444                 : ///   property-attr-decl: '(' property-attrlist ')'
     445                 : ///   property-attrlist:
     446                 : ///     property-attribute
     447                 : ///     property-attrlist ',' property-attribute
     448                 : ///   property-attribute:
     449                 : ///     getter '=' identifier
     450                 : ///     setter '=' identifier ':'
     451                 : ///     readonly
     452                 : ///     readwrite
     453                 : ///     assign
     454                 : ///     retain
     455                 : ///     copy
     456                 : ///     nonatomic
     457                 : ///
     458                 : void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
     459                 :                                         DeclPtrTy *Methods, 
     460              352:                                         unsigned NumMethods) {
                        0: branch 1 not taken
                      352: branch 2 taken
     461              352:   assert(Tok.getKind() == tok::l_paren);
     462              352:   SourceLocation LHSLoc = ConsumeParen(); // consume '('
     463                 : 
     464              149:   while (1) {
                        2: branch 1 taken
                      499: branch 2 taken
     465              501:     if (Tok.is(tok::code_completion)) {
     466                2:       Actions.CodeCompleteObjCPropertyFlags(CurScope, DS);
     467                2:       ConsumeToken();
     468                 :     }
     469              501:     const IdentifierInfo *II = Tok.getIdentifierInfo();
     470                 : 
     471                 :     // If this is not an identifier at all, bail out early.
                        3: branch 0 taken
                      498: branch 1 taken
     472              501:     if (II == 0) {
     473                3:       MatchRHSPunctuation(tok::r_paren, LHSLoc);
     474                3:       return;
     475                 :     }
     476                 : 
     477              498:     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
     478                 : 
                      110: branch 1 taken
                      388: branch 2 taken
     479              498:     if (II->isStr("readonly"))
     480              110:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
                       85: branch 1 taken
                      303: branch 2 taken
     481              388:     else if (II->isStr("assign"))
     482               85:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
                       68: branch 1 taken
                      235: branch 2 taken
     483              303:     else if (II->isStr("readwrite"))
     484               68:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
                       57: branch 1 taken
                      178: branch 2 taken
     485              235:     else if (II->isStr("retain"))
     486               57:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
                       52: branch 1 taken
                      126: branch 2 taken
     487              178:     else if (II->isStr("copy"))
     488               52:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
                       80: branch 1 taken
                       46: branch 2 taken
     489              126:     else if (II->isStr("nonatomic"))
     490               80:       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
                       24: branch 1 taken
                       22: branch 2 taken
                       23: branch 4 taken
                        1: branch 5 taken
                       45: branch 6 taken
                        1: branch 7 taken
     491               46:     else if (II->isStr("getter") || II->isStr("setter")) {
     492                 :       // getter/setter require extra treatment.
                        0: branch 1 not taken
                       45: branch 2 taken
     493               45:       if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "",
     494                 :                            tok::r_paren))
     495                0:         return;
     496                 : 
                        4: branch 1 taken
                       41: branch 2 taken
     497               45:       if (Tok.is(tok::code_completion)) {
                        2: branch 1 taken
                        2: branch 2 taken
     498                4:         if (II->getNameStart()[0] == 's')
     499                 :           Actions.CodeCompleteObjCPropertySetter(CurScope, ClassDecl,
     500                2:                                                  Methods, NumMethods);
     501                 :         else
     502                 :           Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl,
     503                2:                                                  Methods, NumMethods);
     504                4:         ConsumeToken();
     505                 :       }
     506                 : 
                        4: branch 1 taken
                       41: branch 2 taken
     507               45:       if (Tok.isNot(tok::identifier)) {
     508                4:         Diag(Tok, diag::err_expected_ident);
     509                4:         SkipUntil(tok::r_paren);
     510                4:         return;
     511                 :       }
     512                 : 
                       21: branch 1 taken
                       20: branch 2 taken
     513               41:       if (II->getNameStart()[0] == 's') {
     514               21:         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
     515               21:         DS.setSetterName(Tok.getIdentifierInfo());
     516               21:         ConsumeToken();  // consume method name
     517                 : 
                        0: branch 1 not taken
                       21: branch 2 taken
     518               21:         if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "",
     519                 :                              tok::r_paren))
     520                0:           return;
     521                 :       } else {
     522               20:         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
     523               20:         DS.setGetterName(Tok.getIdentifierInfo());
     524               20:         ConsumeToken();  // consume method name
     525                 :       }
     526                 :     } else {
     527                1:       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
     528                1:       SkipUntil(tok::r_paren);
     529                1:       return;
     530                 :     }
     531                 : 
                      149: branch 1 taken
                      344: branch 2 taken
     532              493:     if (Tok.isNot(tok::comma))
     533              344:       break;
     534                 : 
     535              149:     ConsumeToken();
     536                 :   }
     537                 : 
     538              344:   MatchRHSPunctuation(tok::r_paren, LHSLoc);
     539                 : }
     540                 : 
     541                 : ///   objc-method-proto:
     542                 : ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
     543                 : ///     objc-class-method objc-method-decl objc-method-attributes[opt]
     544                 : ///
     545                 : ///   objc-instance-method: '-'
     546                 : ///   objc-class-method: '+'
     547                 : ///
     548                 : ///   objc-method-attributes:         [OBJC2]
     549                 : ///     __attribute__((deprecated))
     550                 : ///
     551                 : Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
     552             3128:                                           tok::ObjCKeywordKind MethodImplKind) {
                      585: branch 1 taken
                     2543: branch 2 taken
                      585: branch 4 taken
                        0: branch 5 not taken
     553             3128:   assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
     554                 : 
     555             3128:   tok::TokenKind methodType = Tok.getKind();
     556             3128:   SourceLocation mLoc = ConsumeToken();
     557                 : 
     558             3128:   DeclPtrTy MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
     559                 :   // Since this rule is used for both method declarations and definitions,
     560                 :   // the caller is (optionally) responsible for consuming the ';'.
     561                 :   return MDecl;
     562                 : }
     563                 : 
     564                 : ///   objc-selector:
     565                 : ///     identifier
     566                 : ///     one of
     567                 : ///       enum struct union if else while do for switch case default
     568                 : ///       break continue return goto asm sizeof typeof __alignof
     569                 : ///       unsigned long const short volatile signed restrict _Complex
     570                 : ///       in out inout bycopy byref oneway int char float double void _Bool
     571                 : ///
     572             7417: IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
                     1819: branch 1 taken
                     5598: branch 2 taken
     573             7417:   switch (Tok.getKind()) {
     574                 :   default:
     575             1819:     return 0;
     576                 :   case tok::identifier:
     577                 :   case tok::kw_asm:
     578                 :   case tok::kw_auto:
     579                 :   case tok::kw_bool:
     580                 :   case tok::kw_break:
     581                 :   case tok::kw_case:
     582                 :   case tok::kw_catch:
     583                 :   case tok::kw_char:
     584                 :   case tok::kw_class:
     585                 :   case tok::kw_const:
     586                 :   case tok::kw_const_cast:
     587                 :   case tok::kw_continue:
     588                 :   case tok::kw_default:
     589                 :   case tok::kw_delete:
     590                 :   case tok::kw_do:
     591                 :   case tok::kw_double:
     592                 :   case tok::kw_dynamic_cast:
     593                 :   case tok::kw_else:
     594                 :   case tok::kw_enum:
     595                 :   case tok::kw_explicit:
     596                 :   case tok::kw_export:
     597                 :   case tok::kw_extern:
     598                 :   case tok::kw_false:
     599                 :   case tok::kw_float:
     600                 :   case tok::kw_for:
     601                 :   case tok::kw_friend:
     602                 :   case tok::kw_goto:
     603                 :   case tok::kw_if:
     604                 :   case tok::kw_inline:
     605                 :   case tok::kw_int:
     606                 :   case tok::kw_long:
     607                 :   case tok::kw_mutable:
     608                 :   case tok::kw_namespace:
     609                 :   case tok::kw_new:
     610                 :   case tok::kw_operator:
     611                 :   case tok::kw_private:
     612                 :   case tok::kw_protected:
     613                 :   case tok::kw_public:
     614                 :   case tok::kw_register:
     615                 :   case tok::kw_reinterpret_cast:
     616                 :   case tok::kw_restrict:
     617                 :   case tok::kw_return:
     618                 :   case tok::kw_short:
     619                 :   case tok::kw_signed:
     620                 :   case tok::kw_sizeof:
     621                 :   case tok::kw_static:
     622                 :   case tok::kw_static_cast:
     623                 :   case tok::kw_struct:
     624                 :   case tok::kw_switch:
     625                 :   case tok::kw_template:
     626                 :   case tok::kw_this:
     627                 :   case tok::kw_throw:
     628                 :   case tok::kw_true:
     629                 :   case tok::kw_try:
     630                 :   case tok::kw_typedef:
     631                 :   case tok::kw_typeid:
     632                 :   case tok::kw_typename:
     633                 :   case tok::kw_typeof:
     634                 :   case tok::kw_union:
     635                 :   case tok::kw_unsigned:
     636                 :   case tok::kw_using:
     637                 :   case tok::kw_virtual:
     638                 :   case tok::kw_void:
     639                 :   case tok::kw_volatile:
     640                 :   case tok::kw_wchar_t:
     641                 :   case tok::kw_while:
     642                 :   case tok::kw__Bool:
     643                 :   case tok::kw__Complex:
     644                 :   case tok::kw___alignof:
     645             5598:     IdentifierInfo *II = Tok.getIdentifierInfo();
     646             5598:     SelectorLoc = ConsumeToken();
     647             5598:     return II;
     648                 :   }
     649                 : }
     650                 : 
     651                 : ///  objc-for-collection-in: 'in'
     652                 : ///
     653               56: bool Parser::isTokIdentifier_in() const {
     654                 :   // FIXME: May have to do additional look-ahead to only allow for
     655                 :   // valid tokens following an 'in'; such as an identifier, unary operators,
     656                 :   // '[' etc.
     657                 :   return (getLang().ObjC2 && Tok.is(tok::identifier) &&
                       56: branch 1 taken
                        0: branch 2 not taken
                       56: branch 4 taken
                        0: branch 5 not taken
                       56: branch 7 taken
                        0: branch 8 not taken
     658               56:           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
     659                 : }
     660                 : 
     661                 : /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
     662                 : /// qualifier list and builds their bitmask representation in the input
     663                 : /// argument.
     664                 : ///
     665                 : ///   objc-type-qualifiers:
     666                 : ///     objc-type-qualifier
     667                 : ///     objc-type-qualifiers objc-type-qualifier
     668                 : ///
     669             4779: void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
     670               47:   while (1) {
                     2551: branch 1 taken
                     2228: branch 2 taken
     671             4779:     if (Tok.isNot(tok::identifier))
     672             2228:       return;
     673                 : 
     674             2551:     const IdentifierInfo *II = Tok.getIdentifierInfo();
                    15207: branch 0 taken
                     2504: branch 1 taken
     675            17711:     for (unsigned i = 0; i != objc_NumQuals; ++i) {
                       47: branch 0 taken
                    15160: branch 1 taken
     676            15207:       if (II != ObjCTypeQuals[i])
     677            15160:         continue;
     678                 : 
     679                 :       ObjCDeclSpec::ObjCDeclQualifier Qual;
                        0: branch 0 not taken
                        2: branch 1 taken
                        4: branch 2 taken
                        2: branch 3 taken
                       30: branch 4 taken
                        7: branch 5 taken
                        2: branch 6 taken
     680               47:       switch (i) {
     681                0:       default: assert(0 && "Unknown decl qualifier");
     682                2:       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
     683                4:       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
     684                2:       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
     685               30:       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
     686                7:       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
     687                2:       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
     688                 :       }
     689               47:       DS.setObjCDeclQualifier(Qual);
     690               47:       ConsumeToken();
     691               47:       II = 0;
     692               47:       break;
     693                 :     }
     694                 : 
     695                 :     // If this wasn't a recognized qualifier, bail out.
                       47: branch 0 taken
                     2504: branch 1 taken
     696             2551:     if (II) return;
     697                 :   }
     698                 : }
     699                 : 
     700                 : ///   objc-type-name:
     701                 : ///     '(' objc-type-qualifiers[opt] type-name ')'
     702                 : ///     '(' objc-type-qualifiers[opt] ')'
     703                 : ///
     704             4732: Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
                     4732: branch 1 taken
                        0: branch 2 not taken
     705             4732:   assert(Tok.is(tok::l_paren) && "expected (");
     706                 : 
     707             4732:   SourceLocation LParenLoc = ConsumeParen();
     708             4732:   SourceLocation TypeStartLoc = Tok.getLocation();
     709                 : 
     710                 :   // Parse type qualifiers, in, inout, etc.
     711             4732:   ParseObjCTypeQualifierList(DS);
     712                 : 
     713             4732:   TypeTy *Ty = 0;
                     4724: branch 1 taken
                        8: branch 2 taken
     714             4732:   if (isTypeSpecifierQualifier()) {
     715             4724:     TypeResult TypeSpec = ParseTypeName();
                     4724: branch 1 taken
                        0: branch 2 not taken
     716             4724:     if (!TypeSpec.isInvalid())
     717             4724:       Ty = TypeSpec.get();
     718                 :   }
     719                 : 
                     4725: branch 1 taken
                        7: branch 2 taken
     720             4732:   if (Tok.is(tok::r_paren))
     721             4725:     ConsumeParen();
                        6: branch 2 taken
                        1: branch 3 taken
     722                7:   else if (Tok.getLocation() == TypeStartLoc) {
     723                 :     // If we didn't eat any tokens, then this isn't a type.
     724                6:     Diag(Tok, diag::err_expected_type);
     725                6:     SkipUntil(tok::r_paren);
     726                 :   } else {
     727                 :     // Otherwise, we found *something*, but didn't get a ')' in the right
     728                 :     // place.  Emit an error then return what we have as the type.
     729                1:     MatchRHSPunctuation(tok::r_paren, LParenLoc);
     730                 :   }
     731             4732:   return Ty;
     732                 : }
     733                 : 
     734                 : ///   objc-method-decl:
     735                 : ///     objc-selector
     736                 : ///     objc-keyword-selector objc-parmlist[opt]
     737                 : ///     objc-type-name objc-selector
     738                 : ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
     739                 : ///
     740                 : ///   objc-keyword-selector:
     741                 : ///     objc-keyword-decl
     742                 : ///     objc-keyword-selector objc-keyword-decl
     743                 : ///
     744                 : ///   objc-keyword-decl:
     745                 : ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
     746                 : ///     objc-selector ':' objc-keyword-attributes[opt] identifier
     747                 : ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
     748                 : ///     ':' objc-keyword-attributes[opt] identifier
     749                 : ///
     750                 : ///   objc-parmlist:
     751                 : ///     objc-parms objc-ellipsis[opt]
     752                 : ///
     753                 : ///   objc-parms:
     754                 : ///     objc-parms , parameter-declaration
     755                 : ///
     756                 : ///   objc-ellipsis:
     757                 : ///     , ...
     758                 : ///
     759                 : ///   objc-keyword-attributes:         [OBJC2]
     760                 : ///     __attribute__((unused))
     761                 : ///
     762                 : Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
     763                 :                                               tok::TokenKind mType,
     764                 :                                               DeclPtrTy IDecl,
     765             3128:                                           tok::ObjCKeywordKind MethodImplKind) {
     766             3128:   ParsingDeclRAIIObject PD(*this);
     767                 : 
     768                 :   // Parse the return type if present.
     769             3128:   TypeTy *ReturnType = 0;
     770             3128:   ObjCDeclSpec DSRet;
                     2921: branch 1 taken
                      207: branch 2 taken
     771             3128:   if (Tok.is(tok::l_paren))
     772             2921:     ReturnType = ParseObjCTypeName(DSRet);
     773                 : 
     774             3128:   SourceLocation selLoc;
     775             3128:   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
     776                 : 
     777                 :   // An unnamed colon is valid.
                        4: branch 0 taken
                     3124: branch 1 taken
                        1: branch 3 taken
                        3: branch 4 taken
                        1: branch 5 taken
                     3127: branch 6 taken
     778             3128:   if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
     779                 :     Diag(Tok, diag::err_expected_selector_for_method)
     780                1:       << SourceRange(mLoc, Tok.getLocation());
     781                 :     // Skip until we get a ; or {}.
     782                1:     SkipUntil(tok::r_brace);
     783                1:     return DeclPtrTy();
     784                 :   }
     785                 : 
     786             3127:   llvm::SmallVector<Declarator, 8> CargNames;
                     1803: branch 1 taken
                     1324: branch 2 taken
     787             3127:   if (Tok.isNot(tok::colon)) {
     788                 :     // If attributes exist after the method, parse them.
     789             1803:     AttributeList *MethodAttrs = 0;
                     1803: branch 1 taken
                        0: branch 2 not taken
                       34: branch 4 taken
                     1769: branch 5 taken
                       34: branch 6 taken
                     1769: branch 7 taken
     790             1803:     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
     791               34:       MethodAttrs = ParseGNUAttributes();
     792                 : 
     793             1803:     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
     794                 :     DeclPtrTy Result
     795                 :          = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
     796                 :                                           mType, IDecl, DSRet, ReturnType, Sel,
     797                 :                                           0, CargNames, MethodAttrs,
     798             1803:                                           MethodImplKind);
     799             1803:     PD.complete(Result);
     800             1803:     return Result;
     801                 :   }
     802                 : 
     803             1324:   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
     804             1324:   llvm::SmallVector<Action::ObjCArgInfo, 12> ArgInfos;
     805                 : 
     806              508:   while (1) {
     807             1832:     Action::ObjCArgInfo ArgInfo;
     808                 : 
     809                 :     // Each iteration parses a single keyword argument.
                        0: branch 1 not taken
                     1832: branch 2 taken
     810             1832:     if (Tok.isNot(tok::colon)) {
     811                0:       Diag(Tok, diag::err_expected_colon);
     812                0:       break;
     813                 :     }
     814             1832:     ConsumeToken(); // Eat the ':'.
     815                 : 
     816             1832:     ArgInfo.Type = 0;
                     1811: branch 1 taken
                       21: branch 2 taken
     817             1832:     if (Tok.is(tok::l_paren)) // Parse the argument type if present.
     818             1811:       ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec);
     819                 : 
     820                 :     // If attributes exist before the argument name, parse them.
     821             1832:     ArgInfo.ArgAttrs = 0;
                     1832: branch 1 taken
                        0: branch 2 not taken
                        5: branch 4 taken
                     1827: branch 5 taken
                        5: branch 6 taken
                     1827: branch 7 taken
     822             1832:     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
     823                5:       ArgInfo.ArgAttrs = ParseGNUAttributes();
     824                 : 
                        1: branch 1 taken
                     1831: branch 2 taken
     825             1832:     if (Tok.isNot(tok::identifier)) {
     826                1:       Diag(Tok, diag::err_expected_ident); // missing argument name.
     827                1:       break;
     828                 :     }
     829                 : 
     830             1831:     ArgInfo.Name = Tok.getIdentifierInfo();
     831             1831:     ArgInfo.NameLoc = Tok.getLocation();
     832             1831:     ConsumeToken(); // Eat the identifier.
     833                 : 
     834             1831:     ArgInfos.push_back(ArgInfo);
     835             1831:     KeyIdents.push_back(SelIdent);
     836                 : 
     837                 :     // Check for another keyword selector.
     838             1831:     SourceLocation Loc;
     839             1831:     SelIdent = ParseObjCSelectorPiece(Loc);
                     1368: branch 0 taken
                      463: branch 1 taken
                     1323: branch 3 taken
                       45: branch 4 taken
                     1323: branch 5 taken
                      508: branch 6 taken
     840             1831:     if (!SelIdent && Tok.isNot(tok::colon))
     841             1323:       break;
     842                 :     // We have a selector or a colon, continue parsing.
     843                 :   }
     844                 : 
     845             1324:   bool isVariadic = false;
     846                 : 
     847                 :   // Parse the (optional) parameter list.
                       98: branch 3 taken
                     1228: branch 4 taken
     848             1326:   while (Tok.is(tok::comma)) {
     849               98:     ConsumeToken();
                       96: branch 1 taken
                        2: branch 2 taken
     850               98:     if (Tok.is(tok::ellipsis)) {
     851               96:       isVariadic = true;
     852               96:       ConsumeToken();
     853               96:       break;
     854                 :     }
     855                2:     DeclSpec DS;
     856                2:     ParseDeclarationSpecifiers(DS);
     857                 :     // Parse the declarator.
     858                2:     Declarator ParmDecl(DS, Declarator::PrototypeContext);
     859                2:     ParseDeclarator(ParmDecl);
     860                2:     CargNames.push_back(ParmDecl);
     861                 :   }
     862                 : 
     863                 :   // FIXME: Add support for optional parmameter list...
     864                 :   // If attributes exist after the method, parse them.
     865             1324:   AttributeList *MethodAttrs = 0;
                     1324: branch 1 taken
                        0: branch 2 not taken
                       21: branch 4 taken
                     1303: branch 5 taken
                       21: branch 6 taken
                     1303: branch 7 taken
     866             1324:   if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
     867               21:     MethodAttrs = ParseGNUAttributes();
     868                 : 
                        1: branch 1 taken
                     1323: branch 2 taken
     869             1324:   if (KeyIdents.size() == 0)
     870                1:     return DeclPtrTy();
     871                 :   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
     872             1323:                                                    &KeyIdents[0]);
     873                 :   DeclPtrTy Result
     874                 :        = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
     875                 :                                         mType, IDecl, DSRet, ReturnType, Sel,
     876                 :                                         &ArgInfos[0], CargNames, MethodAttrs,
     877             1323:                                         MethodImplKind, isVariadic);
     878             1323:   PD.complete(Result);
     879             1323:   return Result;
     880                 : }
     881                 : 
     882                 : ///   objc-protocol-refs:
     883                 : ///     '<' identifier-list '>'
     884                 : ///
     885                 : bool Parser::
     886                 : ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
     887                 :                             llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs,
     888                 :                             bool WarnOnDeclarations,
     889              862:                             SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
                      862: branch 1 taken
                        0: branch 2 not taken
     890              862:   assert(Tok.is(tok::less) && "expected <");
     891                 : 
     892              862:   LAngleLoc = ConsumeToken(); // the "<"
     893                 : 
     894              862:   llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
     895                 : 
     896              369:   while (1) {
                        2: branch 1 taken
                     1229: branch 2 taken
     897             1231:     if (Tok.is(tok::code_completion)) {
     898                 :       Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), 
     899                2:                                                  ProtocolIdents.size());
     900                2:       ConsumeToken();
     901                 :     }
     902                 : 
                        2: branch 1 taken
                     1229: branch 2 taken
     903             1231:     if (Tok.isNot(tok::identifier)) {
     904                2:       Diag(Tok, diag::err_expected_ident);
     905                2:       SkipUntil(tok::greater);
     906                2:       return true;
     907                 :     }
     908                 :     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
     909             1229:                                        Tok.getLocation()));
     910             1229:     ProtocolLocs.push_back(Tok.getLocation());
     911             1229:     ConsumeToken();
     912                 : 
                      369: branch 1 taken
                      860: branch 2 taken
     913             1229:     if (Tok.isNot(tok::comma))
     914              860:       break;
     915              369:     ConsumeToken();
     916                 :   }
     917                 : 
     918                 :   // Consume the '>'.
                        0: branch 1 not taken
                      860: branch 2 taken
     919              860:   if (Tok.isNot(tok::greater)) {
     920                0:     Diag(Tok, diag::err_expected_greater);
     921                0:     return true;
     922                 :   }
     923                 : 
     924              860:   EndLoc = ConsumeAnyToken();
     925                 : 
     926                 :   // Convert the list of protocols identifiers into a list of protocol decls.
     927                 :   Actions.FindProtocolDeclaration(WarnOnDeclarations,
     928                 :                                   &ProtocolIdents[0], ProtocolIdents.size(),
     929              860:                                   Protocols);
     930              860:   return false;
     931                 : }
     932                 : 
     933                 : ///   objc-class-instance-variables:
     934                 : ///     '{' objc-instance-variable-decl-list[opt] '}'
     935                 : ///
     936                 : ///   objc-instance-variable-decl-list:
     937                 : ///     objc-visibility-spec
     938                 : ///     objc-instance-variable-decl ';'
     939                 : ///     ';'
     940                 : ///     objc-instance-variable-decl-list objc-visibility-spec
     941                 : ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
     942                 : ///     objc-instance-variable-decl-list ';'
     943                 : ///
     944                 : ///   objc-visibility-spec:
     945                 : ///     @private
     946                 : ///     @protected
     947                 : ///     @public
     948                 : ///     @package [OBJC2]
     949                 : ///
     950                 : ///   objc-instance-variable-decl:
     951                 : ///     struct-declaration
     952                 : ///
     953                 : void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
     954              766:                                              SourceLocation atLoc) {
                      766: branch 1 taken
                        0: branch 2 not taken
     955              766:   assert(Tok.is(tok::l_brace) && "expected {");
     956              766:   llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
     957                 : 
     958              766:   ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
     959                 : 
     960              766:   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
     961                 : 
     962              766:   tok::ObjCKeywordKind visibility = tok::objc_protected;
     963                 :   // While we still have something to read, read the instance variables.
                      759: branch 1 taken
                      764: branch 2 taken
                      757: branch 4 taken
                        2: branch 5 taken
                      757: branch 6 taken
                      766: branch 7 taken
     964             2289:   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     965                 :     // Each iteration of this loop reads one objc-instance-variable-decl.
     966                 : 
     967                 :     // Check for extraneous top-level semicolon.
                        0: branch 1 not taken
                      757: branch 2 taken
     968              757:     if (Tok.is(tok::semi)) {
     969                 :       Diag(Tok, diag::ext_extra_struct_semi)
     970                0:         << CodeModificationHint::CreateRemoval(Tok.getLocation());
     971                0:       ConsumeToken();
     972                0:       continue;
     973                 :     }
     974                 : 
     975                 :     // Set the default visibility to private.
                       79: branch 1 taken
                      678: branch 2 taken
     976              757:     if (Tok.is(tok::at)) { // parse objc-visibility-spec
     977               79:       ConsumeToken(); // eat the @ sign
     978                 :       
                        1: branch 1 taken
                       78: branch 2 taken
     979               79:       if (Tok.is(tok::code_completion)) {
     980                1:         Actions.CodeCompleteObjCAtVisibility(CurScope);
     981                1:         ConsumeToken();
     982                 :       }
     983                 :       
                       78: branch 1 taken
                        1: branch 2 taken
     984               79:       switch (Tok.getObjCKeywordID()) {
     985                 :       case tok::objc_private:
     986                 :       case tok::objc_public:
     987                 :       case tok::objc_protected:
     988                 :       case tok::objc_package:
     989               78:         visibility = Tok.getObjCKeywordID();
     990               78:         ConsumeToken();
     991               78:         continue;
     992                 :       default:
     993                1:         Diag(Tok, diag::err_objc_illegal_visibility_spec);
     994                1:         continue;
     995                 :       }
     996                 :     }
     997                 : 
                        1: branch 1 taken
                      677: branch 2 taken
     998              678:     if (Tok.is(tok::code_completion)) {
     999                 :       Actions.CodeCompleteOrdinaryName(CurScope, 
    1000                1:                                        Action::CCC_ObjCInstanceVariableList);
    1001                1:       ConsumeToken();
    1002                 :     }
    1003                 :     
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                      678: branch 6 taken
                        0: branch 9 not taken
                        0: branch 10 not taken
    1004              678:     struct ObjCIvarCallback : FieldCallback {
    1005                 :       Parser &P;
    1006                 :       DeclPtrTy IDecl;
    1007                 :       tok::ObjCKeywordKind visibility;
    1008                 :       llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls;
    1009                 : 
    1010                 :       ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
    1011              678:                        llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) :
    1012              678:         P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
    1013              678:       }
    1014                 : 
    1015              690:       DeclPtrTy invoke(FieldDeclarator &FD) {
    1016                 :         // Install the declarator into the interface decl.
    1017                 :         DeclPtrTy Field
    1018                 :           = P.Actions.ActOnIvar(P.CurScope,
    1019                 :                                 FD.D.getDeclSpec().getSourceRange().getBegin(),
    1020              690:                                 IDecl, FD.D, FD.BitfieldSize, visibility);
    1021              690:         AllIvarDecls.push_back(Field);
    1022                 :         return Field;
    1023                 :       }
    1024              678:     } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
    1025                 : 
    1026                 :     // Parse all the comma separated declarators.
    1027              678:     DeclSpec DS;
    1028              678:     ParseStructDeclaration(DS, Callback);
    1029                 : 
                      676: branch 1 taken
                        2: branch 2 taken
    1030              678:     if (Tok.is(tok::semi)) {
    1031              676:       ConsumeToken();
    1032                 :     } else {
    1033                2:       Diag(Tok, diag::err_expected_semi_decl_list);
    1034                 :       // Skip to end of block or statement
    1035                2:       SkipUntil(tok::r_brace, true, true);
    1036                 :     }
    1037              678:   }
    1038              766:   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
    1039                 :   // Call ActOnFields() even if we don't have any decls. This is useful
    1040                 :   // for code rewriting tools that need to be aware of the empty list.
    1041                 :   Actions.ActOnFields(CurScope, atLoc, interfaceDecl,
    1042                 :                       AllIvarDecls.data(), AllIvarDecls.size(),
    1043              766:                       LBraceLoc, RBraceLoc, 0);
    1044              766:   return;
    1045                 : }
    1046                 : 
    1047                 : ///   objc-protocol-declaration:
    1048                 : ///     objc-protocol-definition
    1049                 : ///     objc-protocol-forward-reference
    1050                 : ///
    1051                 : ///   objc-protocol-definition:
    1052                 : ///     @protocol identifier
    1053                 : ///       objc-protocol-refs[opt]
    1054                 : ///       objc-interface-decl-list
    1055                 : ///     @end
    1056                 : ///
    1057                 : ///   objc-protocol-forward-reference:
    1058                 : ///     @protocol identifier-list ';'
    1059                 : ///
    1060                 : ///   "@protocol identifier ;" should be resolved as "@protocol
    1061                 : ///   identifier-list ;": objc-interface-decl-list may not start with a
    1062                 : ///   semicolon in the first alternative if objc-protocol-refs are omitted.
    1063                 : Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
    1064              735:                                                       AttributeList *attrList) {
    1065                 :   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
                      735: branch 1 taken
                        0: branch 2 not taken
    1066              735:          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
    1067              735:   ConsumeToken(); // the "protocol" identifier
    1068                 : 
                        1: branch 1 taken
                      734: branch 2 taken
    1069              735:   if (Tok.is(tok::code_completion)) {
    1070                1:     Actions.CodeCompleteObjCProtocolDecl(CurScope);
    1071                1:     ConsumeToken();
    1072                 :   }
    1073                 : 
                        1: branch 1 taken
                      734: branch 2 taken
    1074              735:   if (Tok.isNot(tok::identifier)) {
    1075                1:     Diag(Tok, diag::err_expected_ident); // missing protocol name.
    1076                1:     return DeclPtrTy();
    1077                 :   }
    1078                 :   // Save the protocol name, then consume it.
    1079              734:   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
    1080              734:   SourceLocation nameLoc = ConsumeToken();
    1081                 : 
                       66: branch 1 taken
                      668: branch 2 taken
    1082              734:   if (Tok.is(tok::semi)) { // forward declaration of one protocol.
    1083               66:     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
    1084               66:     ConsumeToken();
    1085                 :     return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
    1086               66:                                                    attrList);
    1087                 :   }
    1088                 : 
                        7: branch 1 taken
                      661: branch 2 taken
    1089              668:   if (Tok.is(tok::comma)) { // list of forward declarations.
    1090                7:     llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
    1091                7:     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
    1092                 : 
    1093                 :     // Parse the list of forward declarations.
    1094                5:     while (1) {
    1095               12:       ConsumeToken(); // the ','
                        0: branch 1 not taken
                       12: branch 2 taken
    1096               12:       if (Tok.isNot(tok::identifier)) {
    1097                0:         Diag(Tok, diag::err_expected_ident);
    1098                0:         SkipUntil(tok::semi);
    1099                0:         return DeclPtrTy();
    1100                 :       }
    1101                 :       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
    1102               12:                                                Tok.getLocation()));
    1103               12:       ConsumeToken(); // the identifier
    1104                 : 
                        5: branch 1 taken
                        7: branch 2 taken
    1105               12:       if (Tok.isNot(tok::comma))
    1106                7:         break;
    1107                 :     }
    1108                 :     // Consume the ';'.
                        0: branch 1 not taken
                        7: branch 2 taken
    1109                7:     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
    1110                0:       return DeclPtrTy();
    1111                 : 
    1112                 :     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
    1113                 :                                                    &ProtocolRefs[0],
    1114                 :                                                    ProtocolRefs.size(),
    1115                7:                                                    attrList);
    1116                 :   }
    1117                 : 
    1118                 :   // Last, and definitely not least, parse a protocol declaration.
    1119              661:   SourceLocation LAngleLoc, EndProtoLoc;
    1120                 : 
    1121              661:   llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
    1122              661:   llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
                       85: branch 1 taken
                      576: branch 2 taken
                        0: branch 4 not taken
                       85: branch 5 taken
                        0: branch 6 not taken
                      661: branch 7 taken
    1123              661:   if (Tok.is(tok::less) &&
    1124                 :       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
    1125                 :                                   LAngleLoc, EndProtoLoc))
    1126                0:     return DeclPtrTy();
    1127                 : 
    1128                 :   DeclPtrTy ProtoType =
    1129                 :     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
    1130                 :                                         ProtocolRefs.data(),
    1131                 :                                         ProtocolRefs.size(),
    1132                 :                                         ProtocolLocs.data(),
    1133              661:                                         EndProtoLoc, attrList);
    1134              661:   ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
    1135              661:   return ProtoType;
    1136                 : }
    1137                 : 
    1138                 : ///   objc-implementation:
    1139                 : ///     objc-class-implementation-prologue
    1140                 : ///     objc-category-implementation-prologue
    1141                 : ///
    1142                 : ///   objc-class-implementation-prologue:
    1143                 : ///     @implementation identifier objc-superclass[opt]
    1144                 : ///       objc-class-instance-variables[opt]
    1145                 : ///
    1146                 : ///   objc-category-implementation-prologue:
    1147                 : ///     @implementation identifier ( identifier )
    1148                 : Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
    1149              652:   SourceLocation atLoc) {
    1150                 :   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
                      652: branch 1 taken
                        0: branch 2 not taken
    1151              652:          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
    1152              652:   ConsumeToken(); // the "implementation" identifier
    1153                 : 
    1154                 :   // Code completion after '@implementation'.
                        2: branch 1 taken
                      650: branch 2 taken
    1155              652:   if (Tok.is(tok::code_completion)) {
    1156                2:     Actions.CodeCompleteObjCImplementationDecl(CurScope);
    1157                2:     ConsumeToken();
    1158                 :   }
    1159                 : 
                        2: branch 1 taken
                      650: branch 2 taken
    1160              652:   if (Tok.isNot(tok::identifier)) {
    1161                2:     Diag(Tok, diag::err_expected_ident); // missing class or category name.
    1162                2:     return DeclPtrTy();
    1163                 :   }
    1164                 :   // We have a class or category name - consume it.
    1165              650:   IdentifierInfo *nameId = Tok.getIdentifierInfo();
    1166              650:   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
    1167                 : 
                       73: branch 1 taken
                      577: branch 2 taken
    1168              650:   if (Tok.is(tok::l_paren)) {
    1169                 :     // we have a category implementation.
    1170               73:     SourceLocation lparenLoc = ConsumeParen();
    1171               73:     SourceLocation categoryLoc, rparenLoc;
    1172               73:     IdentifierInfo *categoryId = 0;
    1173                 : 
                        3: branch 1 taken
                       70: branch 2 taken
    1174               73:     if (Tok.is(tok::code_completion)) {
    1175                3:       Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId);
    1176                3:       ConsumeToken();
    1177                 :     }
    1178                 :     
                       70: branch 1 taken
                        3: branch 2 taken
    1179               73:     if (Tok.is(tok::identifier)) {
    1180               70:       categoryId = Tok.getIdentifierInfo();
    1181               70:       categoryLoc = ConsumeToken();
    1182                 :     } else {
    1183                3:       Diag(Tok, diag::err_expected_ident); // missing category name.
    1184                3:       return DeclPtrTy();
    1185                 :     }
                        0: branch 1 not taken
                       70: branch 2 taken
    1186               70:     if (Tok.isNot(tok::r_paren)) {
    1187                0:       Diag(Tok, diag::err_expected_rparen);
    1188                0:       SkipUntil(tok::r_paren, false); // don't stop at ';'
    1189                0:       return DeclPtrTy();
    1190                 :     }
    1191               70:     rparenLoc = ConsumeParen();
    1192                 :     DeclPtrTy ImplCatType = Actions.ActOnStartCategoryImplementation(
    1193                 :                                     atLoc, nameId, nameLoc, categoryId,
    1194               70:                                     categoryLoc);
    1195               70:     ObjCImpDecl = ImplCatType;
    1196               70:     PendingObjCImpDecl.push_back(ObjCImpDecl);
    1197               70:     return DeclPtrTy();
    1198                 :   }
    1199                 :   // We have a class implementation
    1200              577:   SourceLocation superClassLoc;
    1201              577:   IdentifierInfo *superClassId = 0;
                       18: branch 1 taken
                      559: branch 2 taken
    1202              577:   if (Tok.is(tok::colon)) {
    1203                 :     // We have a super class
    1204               18:     ConsumeToken();
                        0: branch 1 not taken
                       18: branch 2 taken
    1205               18:     if (Tok.isNot(tok::identifier)) {
    1206                0:       Diag(Tok, diag::err_expected_ident); // missing super class name.
    1207                0:       return DeclPtrTy();
    1208                 :     }
    1209               18:     superClassId = Tok.getIdentifierInfo();
    1210               18:     superClassLoc = ConsumeToken(); // Consume super class name
    1211                 :   }
    1212                 :   DeclPtrTy ImplClsType = Actions.ActOnStartClassImplementation(
    1213                 :                                   atLoc, nameId, nameLoc,
    1214              577:                                   superClassId, superClassLoc);
    1215                 : 
                       14: branch 1 taken
                      563: branch 2 taken
    1216              577:   if (Tok.is(tok::l_brace)) // we have ivars
    1217               14:     ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
    1218              577:   ObjCImpDecl = ImplClsType;
    1219              577:   PendingObjCImpDecl.push_back(ObjCImpDecl);
    1220                 :   
    1221              577:   return DeclPtrTy();
    1222                 : }
    1223                 : 
    1224              633: Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
    1225                 :   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
                      633: branch 1 taken
                        0: branch 2 not taken
    1226              633:          "ParseObjCAtEndDeclaration(): Expected @end");
    1227              633:   DeclPtrTy Result = ObjCImpDecl;
    1228              633:   ConsumeToken(); // the "end" identifier
                      626: branch 1 taken
                        7: branch 2 taken
    1229              633:   if (ObjCImpDecl) {
    1230              626:     Actions.ActOnAtEnd(atEnd, ObjCImpDecl);
    1231              626:     ObjCImpDecl = DeclPtrTy();
    1232              626:     PendingObjCImpDecl.pop_back();
    1233                 :   }
    1234                 :   else {
    1235                 :     // missing @implementation
    1236                7:     Diag(atEnd.getBegin(), diag::warn_expected_implementation);
    1237                 :   }
    1238                 :   return Result;
    1239                 : }
    1240                 : 
    1241             2251: Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
                     2236: branch 1 taken
                       15: branch 2 taken
    1242             2251:   if (PendingObjCImpDecl.empty())
    1243             2236:     return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
    1244               15:   DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
    1245               15:   Actions.ActOnAtEnd(SourceRange(), ImpDecl);
    1246               15:   return Actions.ConvertDeclToDeclGroup(ImpDecl);
    1247                 : }
    1248                 : 
    1249                 : ///   compatibility-alias-decl:
    1250                 : ///     @compatibility_alias alias-name  class-name ';'
    1251                 : ///
    1252               10: Parser::DeclPtrTy Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
    1253                 :   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
                       10: branch 1 taken
                        0: branch 2 not taken
    1254               10:          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
    1255               10:   ConsumeToken(); // consume compatibility_alias
                        0: branch 1 not taken
                       10: branch 2 taken
    1256               10:   if (Tok.isNot(tok::identifier)) {
    1257                0:     Diag(Tok, diag::err_expected_ident);
    1258                0:     return DeclPtrTy();
    1259                 :   }
    1260               10:   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
    1261               10:   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
                        0: branch 1 not taken
                       10: branch 2 taken
    1262               10:   if (Tok.isNot(tok::identifier)) {
    1263                0:     Diag(Tok, diag::err_expected_ident);
    1264                0:     return DeclPtrTy();
    1265                 :   }
    1266               10:   IdentifierInfo *classId = Tok.getIdentifierInfo();
    1267               10:   SourceLocation classLoc = ConsumeToken(); // consume class-name;
                        0: branch 1 not taken
                       10: branch 2 taken
    1268               10:   if (Tok.isNot(tok::semi)) {
    1269                0:     Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
    1270                0:     return DeclPtrTy();
    1271                 :   }
    1272                 :   return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc,
    1273               10:                                         classId, classLoc);
    1274                 : }
    1275                 : 
    1276                 : ///   property-synthesis:
    1277                 : ///     @synthesize property-ivar-list ';'
    1278                 : ///
    1279                 : ///   property-ivar-list:
    1280                 : ///     property-ivar
    1281                 : ///     property-ivar-list ',' property-ivar
    1282                 : ///
    1283                 : ///   property-ivar:
    1284                 : ///     identifier
    1285                 : ///     identifier '=' identifier
    1286                 : ///
    1287              167: Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
    1288                 :   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
                      167: branch 1 taken
                        0: branch 2 not taken
    1289              167:          "ParseObjCPropertyDynamic(): Expected '@synthesize'");
    1290              167:   SourceLocation loc = ConsumeToken(); // consume synthesize
    1291                 : 
    1292               49:   while (true) {
                        2: branch 1 taken
                      214: branch 2 taken
    1293              216:     if (Tok.is(tok::code_completion)) {
    1294                2:       Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
    1295                2:       ConsumeToken();
    1296                 :     }
    1297                 :     
                        3: branch 1 taken
                      213: branch 2 taken
    1298              216:     if (Tok.isNot(tok::identifier)) {
    1299                3:       Diag(Tok, diag::err_synthesized_property_name);
    1300                3:       SkipUntil(tok::semi);
    1301                3:       return DeclPtrTy();
    1302                 :     }
    1303                 :     
    1304              213:     IdentifierInfo *propertyIvar = 0;
    1305              213:     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
    1306              213:     SourceLocation propertyLoc = ConsumeToken(); // consume property name
                       96: branch 1 taken
                      117: branch 2 taken
    1307              213:     if (Tok.is(tok::equal)) {
    1308                 :       // property '=' ivar-name
    1309               96:       ConsumeToken(); // consume '='
    1310                 :       
                        1: branch 1 taken
                       95: branch 2 taken
    1311               96:       if (Tok.is(tok::code_completion)) {
    1312                 :         Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
    1313                1:                                                        ObjCImpDecl);
    1314                1:         ConsumeToken();
    1315                 :       }
    1316                 :       
                        1: branch 1 taken
                       95: branch 2 taken
    1317               96:       if (Tok.isNot(tok::identifier)) {
    1318                1:         Diag(Tok, diag::err_expected_ident);
    1319                1:         break;
    1320                 :       }
    1321               95:       propertyIvar = Tok.getIdentifierInfo();
    1322               95:       ConsumeToken(); // consume ivar-name
    1323                 :     }
    1324                 :     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
    1325              212:                                   propertyId, propertyIvar);
                      163: branch 1 taken
                       49: branch 2 taken
    1326              212:     if (Tok.isNot(tok::comma))
    1327              163:       break;
    1328               49:     ConsumeToken(); // consume ','
    1329                 :   }
                        1: branch 1 taken
                      163: branch 2 taken
    1330              164:   if (Tok.isNot(tok::semi)) {
    1331                1:     Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
    1332                1:     SkipUntil(tok::semi);
    1333                 :   }
    1334                 :   else
    1335              163:     ConsumeToken(); // consume ';'
    1336              164:   return DeclPtrTy();
    1337                 : }
    1338                 : 
    1339                 : ///   property-dynamic:
    1340                 : ///     @dynamic  property-list
    1341                 : ///
    1342                 : ///   property-list:
    1343                 : ///     identifier
    1344                 : ///     property-list ',' identifier
    1345                 : ///
    1346               58: Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
    1347                 :   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
                       58: branch 1 taken
                        0: branch 2 not taken
    1348               58:          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
    1349               58:   SourceLocation loc = ConsumeToken(); // consume dynamic
    1350               26:   while (true) {
                        1: branch 1 taken
                       83: branch 2 taken
    1351               84:     if (Tok.is(tok::code_completion)) {
    1352                1:       Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
    1353                1:       ConsumeToken();
    1354                 :     }
    1355                 :     
                        1: branch 1 taken
                       83: branch 2 taken
    1356               84:     if (Tok.isNot(tok::identifier)) {
    1357                1:       Diag(Tok, diag::err_expected_ident);
    1358                1:       SkipUntil(tok::semi);
    1359                1:       return DeclPtrTy();
    1360                 :     }
    1361                 :     
    1362               83:     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
    1363               83:     SourceLocation propertyLoc = ConsumeToken(); // consume property name
    1364                 :     Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
    1365               83:                                   propertyId, 0);
    1366                 : 
                       26: branch 1 taken
                       57: branch 2 taken
    1367               83:     if (Tok.isNot(tok::comma))
    1368               57:       break;
    1369               26:     ConsumeToken(); // consume ','
    1370                 :   }
                        0: branch 1 not taken
                       57: branch 2 taken
    1371               57:   if (Tok.isNot(tok::semi))
    1372                0:     Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
    1373               57:   return DeclPtrTy();
    1374                 : }
    1375                 : 
    1376                 : ///  objc-throw-statement:
    1377                 : ///    throw expression[opt];
    1378                 : ///
    1379               34: Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
    1380               34:   OwningExprResult Res(Actions);
    1381               34:   ConsumeToken(); // consume throw
                       20: branch 1 taken
                       14: branch 2 taken
    1382               34:   if (Tok.isNot(tok::semi)) {
    1383               20:     Res = ParseExpression();
                        0: branch 1 not taken
                       20: branch 2 taken
    1384               20:     if (Res.isInvalid()) {
    1385                0:       SkipUntil(tok::semi);
    1386                0:       return StmtError();
    1387                 :     }
    1388                 :   }
    1389               34:   ConsumeToken(); // consume ';'
    1390               34:   return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope);
    1391                 : }
    1392                 : 
    1393                 : /// objc-synchronized-statement:
    1394                 : ///   @synchronized '(' expression ')' compound-statement
    1395                 : ///
    1396                 : Parser::OwningStmtResult
    1397               25: Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
    1398               25:   ConsumeToken(); // consume synchronized
                        0: branch 1 not taken
                       25: branch 2 taken
    1399               25:   if (Tok.isNot(tok::l_paren)) {
    1400                0:     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
    1401                0:     return StmtError();
    1402                 :   }
    1403               25:   ConsumeParen();  // '('
    1404               25:   OwningExprResult Res(ParseExpression());
                        1: branch 1 taken
                       24: branch 2 taken
    1405               25:   if (Res.isInvalid()) {
    1406                1:     SkipUntil(tok::semi);
    1407                1:     return StmtError();
    1408                 :   }
                        0: branch 1 not taken
                       24: branch 2 taken
    1409               24:   if (Tok.isNot(tok::r_paren)) {
    1410                0:     Diag(Tok, diag::err_expected_lbrace);
    1411                0:     return StmtError();
    1412                 :   }
    1413               24:   ConsumeParen();  // ')'
                        0: branch 1 not taken
                       24: branch 2 taken
    1414               24:   if (Tok.isNot(tok::l_brace)) {
    1415                0:     Diag(Tok, diag::err_expected_lbrace);
    1416                0:     return StmtError();
    1417                 :   }
    1418                 :   // Enter a scope to hold everything within the compound stmt.  Compound
    1419                 :   // statements can always hold declarations.
    1420               24:   ParseScope BodyScope(this, Scope::DeclScope);
    1421                 : 
    1422               24:   OwningStmtResult SynchBody(ParseCompoundStatementBody());
    1423                 : 
    1424               24:   BodyScope.Exit();
                        0: branch 1 not taken
                       24: branch 2 taken
    1425               24:   if (SynchBody.isInvalid())
    1426                0:     SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
    1427               24:   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody));
    1428                 : }
    1429                 : 
    1430                 : ///  objc-try-catch-statement:
    1431                 : ///    @try compound-statement objc-catch-list[opt]
    1432                 : ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
    1433                 : ///
    1434                 : ///  objc-catch-list:
    1435                 : ///    @catch ( parameter-declaration ) compound-statement
    1436                 : ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
    1437                 : ///  catch-parameter-declaration:
    1438                 : ///     parameter-declaration
    1439                 : ///     '...' [OBJC2]
    1440                 : ///
    1441               54: Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
    1442               54:   bool catch_or_finally_seen = false;
    1443                 : 
    1444               54:   ConsumeToken(); // consume try
                        0: branch 1 not taken
                       54: branch 2 taken
    1445               54:   if (Tok.isNot(tok::l_brace)) {
    1446                0:     Diag(Tok, diag::err_expected_lbrace);
    1447                0:     return StmtError();
    1448                 :   }
    1449               54:   OwningStmtResult CatchStmts(Actions);
    1450               54:   OwningStmtResult FinallyStmt(Actions);
    1451               54:   ParseScope TryScope(this, Scope::DeclScope);
    1452               54:   OwningStmtResult TryBody(ParseCompoundStatementBody());
    1453               54:   TryScope.Exit();
                        0: branch 1 not taken
                       54: branch 2 taken
    1454               54:   if (TryBody.isInvalid())
    1455                0:     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
    1456                 : 
                      100: branch 1 taken
                       24: branch 2 taken
    1457              178:   while (Tok.is(tok::at)) {
    1458                 :     // At this point, we need to lookahead to determine if this @ is the start
    1459                 :     // of an @catch or @finally.  We don't want to consume the @ token if this
    1460                 :     // is an @try or @encode or something else.
    1461              100:     Token AfterAt = GetLookAheadToken(1);
                       30: branch 1 taken
                       70: branch 2 taken
                        7: branch 4 taken
                       23: branch 5 taken
                        7: branch 6 taken
                       93: branch 7 taken
    1462              100:     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
    1463                 :         !AfterAt.isObjCAtKeyword(tok::objc_finally))
    1464                7:       break;
    1465                 : 
    1466               93:     SourceLocation AtCatchFinallyLoc = ConsumeToken();
                       70: branch 1 taken
                       23: branch 2 taken
    1467               93:     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
    1468               70:       DeclPtrTy FirstPart;
    1469               70:       ConsumeToken(); // consume catch
                       70: branch 1 taken
                        0: branch 2 not taken
    1470               70:       if (Tok.is(tok::l_paren)) {
    1471               70:         ConsumeParen();
    1472               70:         ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
                       56: branch 1 taken
                       14: branch 2 taken
    1473               70:         if (Tok.isNot(tok::ellipsis)) {
    1474               56:           DeclSpec DS;
    1475               56:           ParseDeclarationSpecifiers(DS);
    1476                 :           // For some odd reason, the name of the exception variable is
    1477                 :           // optional. As a result, we need to use "PrototypeContext", because
    1478                 :           // we must accept either 'declarator' or 'abstract-declarator' here.
    1479               56:           Declarator ParmDecl(DS, Declarator::PrototypeContext);
    1480               56:           ParseDeclarator(ParmDecl);
    1481                 : 
    1482                 :           // Inform the actions module about the parameter declarator, so it
    1483                 :           // gets added to the current scope.
    1484                 :           // FIXME. Probably can build a VarDecl and avoid setting DeclContext.
    1485               56:           FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
    1486               56:           Actions.ActOnObjCCatchParam(FirstPart);
    1487                 :         } else
    1488               14:           ConsumeToken(); // consume '...'
    1489                 : 
    1490               70:         SourceLocation RParenLoc;
    1491                 : 
                       70: branch 1 taken
                        0: branch 2 not taken
    1492               70:         if (Tok.is(tok::r_paren))
    1493               70:           RParenLoc = ConsumeParen();
    1494                 :         else // Skip over garbage, until we get to ')'.  Eat the ')'.
    1495                0:           SkipUntil(tok::r_paren, true, false);
    1496                 : 
    1497               70:         OwningStmtResult CatchBody(Actions, true);
                       70: branch 1 taken
                        0: branch 2 not taken
    1498               70:         if (Tok.is(tok::l_brace))
    1499               70:           CatchBody = ParseCompoundStatementBody();
    1500                 :         else
    1501                0:           Diag(Tok, diag::err_expected_lbrace);
                        0: branch 1 not taken
                       70: branch 2 taken
    1502               70:         if (CatchBody.isInvalid())
    1503                0:           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
    1504                 :         CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
    1505                 :                         RParenLoc, FirstPart, move(CatchBody),
    1506               70:                         move(CatchStmts));
    1507                 :       } else {
    1508                 :         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
    1509                0:           << "@catch clause";
    1510                0:         return StmtError();
    1511                 :       }
    1512               70:       catch_or_finally_seen = true;
    1513                 :     } else {
                       23: branch 1 taken
                        0: branch 2 not taken
    1514               23:       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
    1515               23:       ConsumeToken(); // consume finally
    1516               23:       ParseScope FinallyScope(this, Scope::DeclScope);
    1517                 : 
    1518               23:       OwningStmtResult FinallyBody(Actions, true);
                       23: branch 1 taken
                        0: branch 2 not taken
    1519               23:       if (Tok.is(tok::l_brace))
    1520               23:         FinallyBody = ParseCompoundStatementBody();
    1521                 :       else
    1522                0:         Diag(Tok, diag::err_expected_lbrace);
                        0: branch 1 not taken
                       23: branch 2 taken
    1523               23:       if (FinallyBody.isInvalid())
    1524                0:         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
    1525                 :       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
    1526               23:                                                    move(FinallyBody));
    1527               23:       catch_or_finally_seen = true;
    1528               23:       break;
    1529                 :     }
    1530                 :   }
                        6: branch 0 taken
                       48: branch 1 taken
    1531               54:   if (!catch_or_finally_seen) {
    1532                6:     Diag(atLoc, diag::err_missing_catch_finally);
    1533                6:     return StmtError();
    1534                 :   }
    1535                 :   return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody), move(CatchStmts),
    1536               48:                                     move(FinallyStmt));
    1537                 : }
    1538                 : 
    1539                 : ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
    1540                 : ///
    1541              924: Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
    1542              924:   DeclPtrTy MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
    1543                 : 
    1544                 :   PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
    1545                 :                                         PP.getSourceManager(),
    1546              924:                                         "parsing Objective-C method");
    1547                 : 
    1548                 :   // parse optional ';'
                        2: branch 1 taken
                      922: branch 2 taken
    1549              924:   if (Tok.is(tok::semi)) {
                        1: branch 1 taken
                        1: branch 2 taken
    1550                2:     if (ObjCImpDecl) {
    1551                 :       Diag(Tok, diag::warn_semicolon_before_method_body)
    1552                1:         << CodeModificationHint::CreateRemoval(Tok.getLocation());
    1553                 :     }
    1554                2:     ConsumeToken();
    1555                 :   }
    1556                 : 
    1557                 :   // We should have an opening brace now.
                        1: branch 1 taken
                      923: branch 2 taken
    1558              924:   if (Tok.isNot(tok::l_brace)) {
    1559                1:     Diag(Tok, diag::err_expected_method_body);
    1560                 : 
    1561                 :     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
    1562                1:     SkipUntil(tok::l_brace, true, true);
    1563                 : 
    1564                 :     // If we didn't find the '{', bail out.
                        1: branch 1 taken
                        0: branch 2 not taken
    1565                1:     if (Tok.isNot(tok::l_brace))
    1566                1:       return DeclPtrTy();
    1567                 :   }
    1568              923:   SourceLocation BraceLoc = Tok.getLocation();
    1569                 : 
    1570                 :   // Enter a scope for the method body.
    1571              923:   ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
    1572                 : 
    1573                 :   // Tell the actions module that we have entered a method definition with the
    1574                 :   // specified Declarator for the method.
    1575              923:   Actions.ActOnStartOfObjCMethodDef(CurScope, MDecl);
    1576                 : 
    1577              923:   OwningStmtResult FnBody(ParseCompoundStatementBody());
    1578                 : 
    1579                 :   // If the function body could not be parsed, make a bogus compoundstmt.
                        8: branch 1 taken
                      915: branch 2 taken
    1580              923:   if (FnBody.isInvalid())
    1581                 :     FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
    1582                8:                                        MultiStmtArg(Actions), false);
    1583                 : 
    1584                 :   // TODO: Pass argument information.
    1585              923:   Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
    1586                 : 
    1587                 :   // Leave the function body scope.
    1588              923:   BodyScope.Exit();
    1589                 : 
    1590              923:   return MDecl;
    1591                 : }
    1592                 : 
    1593              118: Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
                        1: branch 1 taken
                      117: branch 2 taken
    1594              118:   if (Tok.is(tok::code_completion)) {
    1595                1:     Actions.CodeCompleteObjCAtStatement(CurScope);
    1596                1:     ConsumeToken();
    1597                1:     return StmtError();
    1598                 :   }
    1599                 :   
                       54: branch 1 taken
                       63: branch 2 taken
    1600              117:   if (Tok.isObjCAtKeyword(tok::objc_try))
    1601               54:     return ParseObjCTryStmt(AtLoc);
    1602                 :   
                       34: branch 1 taken
                       29: branch 2 taken
    1603               63:   if (Tok.isObjCAtKeyword(tok::objc_throw))
    1604               34:     return ParseObjCThrowStmt(AtLoc);
    1605                 :   
                       25: branch 1 taken
                        4: branch 2 taken
    1606               29:   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
    1607               25:     return ParseObjCSynchronizedStmt(AtLoc);
    1608                 :   
    1609                4:   OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
                        0: branch 1 not taken
                        4: branch 2 taken
    1610                4:   if (Res.isInvalid()) {
    1611                 :     // If the expression is invalid, skip ahead to the next semicolon. Not
    1612                 :     // doing this opens us up to the possibility of infinite loops if
    1613                 :     // ParseExpression does not consume any tokens.
    1614                0:     SkipUntil(tok::semi);
    1615                0:     return StmtError();
    1616                 :   }
    1617                 :   
    1618                 :   // Otherwise, eat the semicolon.
    1619                4:   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
    1620                4:   return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
    1621                 : }
    1622                 : 
    1623              322: Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
                        1: branch 1 taken
                      219: branch 2 taken
                      102: branch 3 taken
    1624              322:   switch (Tok.getKind()) {
    1625                 :   case tok::code_completion:
    1626                1:     Actions.CodeCompleteObjCAtExpression(CurScope);
    1627                1:     ConsumeToken();
    1628                1:     return ExprError();
    1629                 : 
    1630                 :   case tok::string_literal:    // primary-expression: string-literal
    1631                 :   case tok::wide_string_literal:
    1632              219:     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
    1633                 :   default:
                        1: branch 1 taken
                      101: branch 2 taken
    1634              102:     if (Tok.getIdentifierInfo() == 0)
    1635                1:       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
    1636                 : 
                       30: branch 2 taken
                       22: branch 3 taken
                       49: branch 4 taken
                        0: branch 5 not taken
    1637              101:     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
    1638                 :     case tok::objc_encode:
    1639               30:       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
    1640                 :     case tok::objc_protocol:
    1641               22:       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
    1642                 :     case tok::objc_selector:
    1643               49:       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
    1644                 :     default:
    1645                0:       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
    1646                 :     }
    1647                 :   }
    1648                 : }
    1649                 : 
    1650                 : ///   objc-message-expr:
    1651                 : ///     '[' objc-receiver objc-message-args ']'
    1652                 : ///
    1653                 : ///   objc-receiver:
    1654                 : ///     expression
    1655                 : ///     class-name
    1656                 : ///     type-name
    1657             1675: Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
                     1675: branch 1 taken
                        0: branch 2 not taken
    1658             1675:   assert(Tok.is(tok::l_square) && "'[' expected");
    1659             1675:   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
    1660                 : 
    1661                 :   // Parse receiver
                      557: branch 1 taken
                     1118: branch 2 taken
    1662             1675:   if (isTokObjCMessageIdentifierReceiver()) {
    1663              557:     IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
                      113: branch 0 taken
                      444: branch 1 taken
                      112: branch 4 taken
                        1: branch 5 taken
                      556: branch 6 taken
                        1: branch 7 taken
    1664              557:     if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
    1665              556:       SourceLocation NameLoc = ConsumeToken();
    1666                 :       return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
    1667              556:                                             ExprArg(Actions));
    1668                 :     }
    1669                 :   }
    1670                 : 
    1671             1119:   OwningExprResult Res(ParseExpression());
                       11: branch 1 taken
                     1108: branch 2 taken
    1672             1119:   if (Res.isInvalid()) {
    1673               11:     SkipUntil(tok::r_square);
    1674               11:     return move(Res);
    1675                 :   }
    1676                 : 
    1677                 :   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
    1678             1108:                                         0, move(Res));
    1679                 : }
    1680                 : 
    1681                 : /// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
    1682                 : /// the rest of a message expression.
    1683                 : ///
    1684                 : ///   objc-message-args:
    1685                 : ///     objc-selector
    1686                 : ///     objc-keywordarg-list
    1687                 : ///
    1688                 : ///   objc-keywordarg-list:
    1689                 : ///     objc-keywordarg
    1690                 : ///     objc-keywordarg-list objc-keywordarg
    1691                 : ///
    1692                 : ///   objc-keywordarg:
    1693                 : ///     selector-name[opt] ':' objc-keywordexpr
    1694                 : ///
    1695                 : ///   objc-keywordexpr:
    1696                 : ///     nonempty-expr-list
    1697                 : ///
    1698                 : ///   nonempty-expr-list:
    1699                 : ///     assignment-expression
    1700                 : ///     nonempty-expr-list , assignment-expression
    1701                 : ///
    1702                 : Parser::OwningExprResult
    1703                 : Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
    1704                 :                                        SourceLocation NameLoc,
    1705                 :                                        IdentifierInfo *ReceiverName,
    1706             1690:                                        ExprArg ReceiverExpr) {
                       10: branch 1 taken
                     1680: branch 2 taken
    1707             1690:   if (Tok.is(tok::code_completion)) {
                        5: branch 0 taken
                        5: branch 1 taken
    1708               10:     if (ReceiverName)
    1709                 :       Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, 
    1710                5:                                            0, 0);
    1711                 :     else
    1712                 :       Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), 
    1713                5:                                               0, 0);
    1714               10:     ConsumeToken();
    1715                 :   }
    1716                 :   
    1717                 :   // Parse objc-selector
    1718             1690:   SourceLocation Loc;
    1719             1690:   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
    1720                 : 
    1721             1690:   SourceLocation SelectorLoc = Loc;
    1722                 : 
    1723             1690:   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
    1724             1690:   ExprVector KeyExprs(Actions);
    1725                 : 
                      413: branch 1 taken
                     1277: branch 2 taken
    1726             1690:   if (Tok.is(tok::colon)) {
                      268: branch 1 taken
                        0: branch 2 not taken
                      413: branch 3 taken
    1727              681:     while (1) {
    1728                 :       // Each iteration parses a single keyword argument.
    1729              681:       KeyIdents.push_back(selIdent);
    1730                 : 
                        0: branch 1 not taken
                      681: branch 2 taken
    1731              681:       if (Tok.isNot(tok::colon)) {
    1732                0:         Diag(Tok, diag::err_expected_colon);
    1733                 :         // We must manually skip to a ']', otherwise the expression skipper will
    1734                 :         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    1735                 :         // the enclosing expression.
    1736                0:         SkipUntil(tok::r_square);
    1737                0:         return ExprError();
    1738                 :       }
    1739                 : 
    1740              681:       ConsumeToken(); // Eat the ':'.
    1741                 :       ///  Parse the expression after ':'
    1742              681:       OwningExprResult Res(ParseAssignmentExpression());
                        0: branch 1 not taken
                      681: branch 2 taken
    1743              681:       if (Res.isInvalid()) {
    1744                 :         // We must manually skip to a ']', otherwise the expression skipper will
    1745                 :         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    1746                 :         // the enclosing expression.
    1747                0:         SkipUntil(tok::r_square);
    1748                0:         return move(Res);
    1749                 :       }
    1750                 : 
    1751                 :       // We have a valid expression.
    1752              681:       KeyExprs.push_back(Res.release());
    1753                 : 
    1754                 :       // Code completion after each argument.
                        2: branch 1 taken
                      679: branch 2 taken
    1755              681:       if (Tok.is(tok::code_completion)) {
                        0: branch 0 not taken
                        2: branch 1 taken
    1756                2:         if (ReceiverName)
    1757                 :           Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc,
    1758                 :                                                KeyIdents.data(), 
    1759                0:                                                KeyIdents.size());
    1760                 :         else
    1761                 :           Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
    1762                 :                                                   KeyIdents.data(), 
    1763                2:                                                   KeyIdents.size());
    1764                2:         ConsumeToken();
    1765                 :       }
    1766                 :             
    1767                 :       // Check for another keyword selector.
    1768              681:       selIdent = ParseObjCSelectorPiece(Loc);
                      424: branch 0 taken
                      257: branch 1 taken
                      413: branch 3 taken
                       11: branch 4 taken
                      413: branch 5 taken
                      268: branch 6 taken
    1769              681:       if (!selIdent && Tok.isNot(tok::colon))
    1770                 :         break;
    1771                 :       // We have a selector or a colon, continue parsing.
    1772                 :     }
    1773                 :     // Parse the, optional, argument list, comma separated.
                      180: branch 1 taken
                        0: branch 2 not taken
                      180: branch 4 taken
                      413: branch 5 taken
    1774              593:     while (Tok.is(tok::comma)) {
    1775              180:       ConsumeToken(); // Eat the ','.
    1776                 :       ///  Parse the expression after ','
    1777              180:       OwningExprResult Res(ParseAssignmentExpression());
                        0: branch 1 not taken
                      180: branch 2 taken
    1778              180:       if (Res.isInvalid()) {
    1779                 :         // We must manually skip to a ']', otherwise the expression skipper will
    1780                 :         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    1781                 :         // the enclosing expression.
    1782                0:         SkipUntil(tok::r_square);
    1783                0:         return move(Res);
    1784                 :       }
    1785                 : 
    1786                 :       // We have a valid expression.
    1787              180:       KeyExprs.push_back(Res.release());
    1788                 :     }
                       10: branch 0 taken
                     1267: branch 1 taken
    1789             1277:   } else if (!selIdent) {
    1790               10:     Diag(Tok, diag::err_expected_ident); // missing selector name.
    1791                 : 
    1792                 :     // We must manually skip to a ']', otherwise the expression skipper will
    1793                 :     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    1794                 :     // the enclosing expression.
    1795               10:     SkipUntil(tok::r_square);
    1796               10:     return ExprError();
    1797                 :   }
    1798                 : 
                        3: branch 1 taken
                     1677: branch 2 taken
    1799             1680:   if (Tok.isNot(tok::r_square)) {
    1800                3:     Diag(Tok, diag::err_expected_rsquare);
    1801                 :     // We must manually skip to a ']', otherwise the expression skipper will
    1802                 :     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    1803                 :     // the enclosing expression.
    1804                3:     SkipUntil(tok::r_square);
    1805                3:     return ExprError();
    1806                 :   }
    1807                 : 
    1808             1677:   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
    1809                 : 
    1810             1677:   unsigned nKeys = KeyIdents.size();
                     1267: branch 0 taken
                      410: branch 1 taken
    1811             1677:   if (nKeys == 0)
    1812             1267:     KeyIdents.push_back(selIdent);
    1813             1677:   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
    1814                 : 
    1815                 :   // We've just parsed a keyword message.
                      554: branch 0 taken
                     1123: branch 1 taken
    1816             1677:   if (ReceiverName)
    1817                 :     return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
    1818                 :                                            LBracLoc, NameLoc, SelectorLoc,
    1819                 :                                            RBracLoc,
    1820              554:                                            KeyExprs.take(), KeyExprs.size()));
    1821                 :   return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
    1822                 :                                             LBracLoc, SelectorLoc, RBracLoc,
    1823             1123:                                             KeyExprs.take(), KeyExprs.size()));
    1824                 : }
    1825                 : 
    1826              219: Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
    1827              219:   OwningExprResult Res(ParseStringLiteralExpression());
                        0: branch 1 not taken
                      219: branch 2 taken
    1828              219:   if (Res.isInvalid()) return move(Res);
    1829                 : 
    1830                 :   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
    1831                 :   // expressions.  At this point, we know that the only valid thing that starts
    1832                 :   // with '@' is an @"".
    1833              219:   llvm::SmallVector<SourceLocation, 4> AtLocs;
    1834              219:   ExprVector AtStrings(Actions);
    1835              219:   AtLocs.push_back(AtLoc);
    1836              219:   AtStrings.push_back(Res.release());
    1837                 : 
                        8: branch 1 taken
                        0: branch 2 not taken
                       10: branch 4 taken
                      217: branch 5 taken
    1838                8:   while (Tok.is(tok::at)) {
    1839               10:     AtLocs.push_back(ConsumeToken()); // eat the @.
    1840                 : 
    1841                 :     // Invalid unless there is a string literal.
                        2: branch 1 taken
                        8: branch 2 taken
    1842               10:     if (!isTokenStringLiteral())
    1843                2:       return ExprError(Diag(Tok, diag::err_objc_concat_string));
    1844                 : 
    1845                8:     OwningExprResult Lit(ParseStringLiteralExpression());
                        0: branch 1 not taken
                        8: branch 2 taken
    1846                8:     if (Lit.isInvalid())
    1847                0:       return move(Lit);
    1848                 : 
    1849                8:     AtStrings.push_back(Lit.release());
    1850                 :   }
    1851                 : 
    1852                 :   return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
    1853              217:                                               AtStrings.size()));
    1854                 : }
    1855                 : 
    1856                 : ///    objc-encode-expression:
    1857                 : ///      @encode ( type-name )
    1858                 : Parser::OwningExprResult
    1859               30: Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
                       30: branch 1 taken
                        0: branch 2 not taken
    1860               30:   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
    1861                 : 
    1862               30:   SourceLocation EncLoc = ConsumeToken();
    1863                 : 
                        0: branch 1 not taken
                       30: branch 2 taken
    1864               30:   if (Tok.isNot(tok::l_paren))
    1865                0:     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
    1866                 : 
    1867               30:   SourceLocation LParenLoc = ConsumeParen();
    1868                 : 
    1869               30:   TypeResult Ty = ParseTypeName();
    1870                 : 
    1871               30:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1872                 : 
                        0: branch 1 not taken
                       30: branch 2 taken
    1873               30:   if (Ty.isInvalid())
    1874                0:     return ExprError();
    1875                 : 
    1876                 :   return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
    1877               30:                                                  Ty.get(), RParenLoc));
    1878                 : }
    1879                 : 
    1880                 : ///     objc-protocol-expression
    1881                 : ///       @protocol ( protocol-name )
    1882                 : Parser::OwningExprResult
    1883               22: Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
    1884               22:   SourceLocation ProtoLoc = ConsumeToken();
    1885                 : 
                        0: branch 1 not taken
                       22: branch 2 taken
    1886               22:   if (Tok.isNot(tok::l_paren))
    1887                0:     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
    1888                 : 
    1889               22:   SourceLocation LParenLoc = ConsumeParen();
    1890                 : 
                        0: branch 1 not taken
                       22: branch 2 taken
    1891               22:   if (Tok.isNot(tok::identifier))
    1892                0:     return ExprError(Diag(Tok, diag::err_expected_ident));
    1893                 : 
    1894               22:   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
    1895               22:   ConsumeToken();
    1896                 : 
    1897               22:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1898                 : 
    1899                 :   return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
    1900               22:                                                    LParenLoc, RParenLoc));
    1901                 : }
    1902                 : 
    1903                 : ///     objc-selector-expression
    1904                 : ///       @selector '(' objc-keyword-selector ')'
    1905                 : Parser::OwningExprResult
    1906               49: Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
    1907               49:   SourceLocation SelectorLoc = ConsumeToken();
    1908                 : 
                        0: branch 1 not taken
                       49: branch 2 taken
    1909               49:   if (Tok.isNot(tok::l_paren))
    1910                0:     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
    1911                 : 
    1912               49:   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
    1913               49:   SourceLocation LParenLoc = ConsumeParen();
    1914               49:   SourceLocation sLoc;
    1915               49:   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
                        2: branch 0 taken
                       47: branch 1 taken
                        0: branch 3 not taken
                        2: branch 4 taken
                        0: branch 5 not taken
                       49: branch 6 taken
    1916               49:   if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name.
    1917                0:     return ExprError(Diag(Tok, diag::err_expected_ident));
    1918                 : 
    1919               49:   KeyIdents.push_back(SelIdent);
    1920               49:   unsigned nColons = 0;
                       29: branch 1 taken
                       20: branch 2 taken
    1921               49:   if (Tok.isNot(tok::r_paren)) {
    1922               38:     while (1) {
                        0: branch 1 not taken
                       67: branch 2 taken
    1923               67:       if (Tok.isNot(tok::colon))
    1924                0:         return ExprError(Diag(Tok, diag::err_expected_colon));
    1925                 : 
    1926               67:       nColons++;
    1927               67:       ConsumeToken(); // Eat the ':'.
                       38: branch 1 taken
                       29: branch 2 taken
    1928               67:       if (Tok.is(tok::r_paren))
    1929               29:         break;
    1930                 :       // Check for another keyword selector.
    1931               38:       SourceLocation Loc;
    1932               38:       SelIdent = ParseObjCSelectorPiece(Loc);
    1933               38:       KeyIdents.push_back(SelIdent);
                       10: branch 0 taken
                       28: branch 1 taken
                        0: branch 3 not taken
                       10: branch 4 taken
                        0: branch 5 not taken
                       38: branch 6 taken
    1934               38:       if (!SelIdent && Tok.isNot(tok::colon))
    1935                0:         break;
    1936                 :     }
    1937                 :   }
    1938               49:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1939               49:   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
    1940                 :   return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
    1941               49:                                                    LParenLoc, RParenLoc));
    1942                0:  }

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