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