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