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