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