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