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