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