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