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