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