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