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" 20 using namespace clang; 21 22 23 /// ParseObjCAtDirectives - Handle parts of the external-declaration production: 24 /// external-declaration: [C99 6.9] 25 /// [OBJC] objc-class-definition 26 /// [OBJC] objc-class-declaration 27 /// [OBJC] objc-alias-declaration 28 /// [OBJC] objc-protocol-definition 29 /// [OBJC] objc-method-definition 30 /// [OBJC] '@' 'end' 31 Parser::DeclTy *Parser::ParseObjCAtDirectives() { 32 SourceLocation AtLoc = ConsumeToken(); // the "@" 33 34 switch (Tok.getObjCKeywordID()) { 35 case tok::objc_class: 36 return ParseObjCAtClassDeclaration(AtLoc); 37 case tok::objc_interface: 38 return ParseObjCAtInterfaceDeclaration(AtLoc); 39 case tok::objc_protocol: 40 return ParseObjCAtProtocolDeclaration(AtLoc); 41 case tok::objc_implementation: 42 return ParseObjCAtImplementationDeclaration(AtLoc); 43 case tok::objc_end: 44 return ParseObjCAtEndDeclaration(AtLoc); 45 case tok::objc_compatibility_alias: 46 return ParseObjCAtAliasDeclaration(AtLoc); 47 case tok::objc_synthesize: 48 return ParseObjCPropertySynthesize(AtLoc); 49 case tok::objc_dynamic: 50 return ParseObjCPropertyDynamic(AtLoc); 51 default: 52 Diag(AtLoc, diag::err_unexpected_at); 53 SkipUntil(tok::semi); 54 return 0; 55 } 56 } 57 58 /// 59 /// objc-class-declaration: 60 /// '@' 'class' identifier-list ';' 61 /// 62 Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { 63 ConsumeToken(); // the identifier "class" 64 llvm::SmallVector<IdentifierInfo *, 8> ClassNames; 65 66 while (1) { 67 if (Tok.isNot(tok::identifier)) { 68 Diag(Tok, diag::err_expected_ident); 69 SkipUntil(tok::semi); 70 return 0; 71 } 72 ClassNames.push_back(Tok.getIdentifierInfo()); 73 ConsumeToken(); 74 75 if (Tok.isNot(tok::comma)) 76 break; 77 78 ConsumeToken(); 79 } 80 81 // Consume the ';'. 82 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) 83 return 0; 84 85 return Actions.ActOnForwardClassDeclaration(atLoc, 86 &ClassNames[0], ClassNames.size()); 87 } 88 89 /// 90 /// objc-interface: 91 /// objc-class-interface-attributes[opt] objc-class-interface 92 /// objc-category-interface 93 /// 94 /// objc-class-interface: 95 /// '@' 'interface' identifier objc-superclass[opt] 96 /// objc-protocol-refs[opt] 97 /// objc-class-instance-variables[opt] 98 /// objc-interface-decl-list 99 /// @end 100 /// 101 /// objc-category-interface: 102 /// '@' 'interface' identifier '(' identifier[opt] ')' 103 /// objc-protocol-refs[opt] 104 /// objc-interface-decl-list 105 /// @end 106 /// 107 /// objc-superclass: 108 /// ':' identifier 109 /// 110 /// objc-class-interface-attributes: 111 /// __attribute__((visibility("default"))) 112 /// __attribute__((visibility("hidden"))) 113 /// __attribute__((deprecated)) 114 /// __attribute__((unavailable)) 115 /// __attribute__((objc_exception)) - used by NSException on 64-bit 116 /// 117 Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( 118 SourceLocation atLoc, AttributeList *attrList) { 119 assert(Tok.isObjCAtKeyword(tok::objc_interface) && 120 "ParseObjCAtInterfaceDeclaration(): Expected @interface"); 121 ConsumeToken(); // the "interface" identifier 122 123 if (Tok.isNot(tok::identifier)) { 124 Diag(Tok, diag::err_expected_ident); // missing class or category name. 125 return 0; 126 } 127 // We have a class or category name - consume it. 128 IdentifierInfo *nameId = Tok.getIdentifierInfo(); 129 SourceLocation nameLoc = ConsumeToken(); 130 131 if (Tok.is(tok::l_paren)) { // we have a category. 132 SourceLocation lparenLoc = ConsumeParen(); 133 SourceLocation categoryLoc, rparenLoc; 134 IdentifierInfo *categoryId = 0; 135 136 // For ObjC2, the category name is optional (not an error). 137 if (Tok.is(tok::identifier)) { 138 categoryId = Tok.getIdentifierInfo(); 139 categoryLoc = ConsumeToken(); 140 } else if (!getLang().ObjC2) { 141 Diag(Tok, diag::err_expected_ident); // missing category name. 142 return 0; 143 } 144 if (Tok.isNot(tok::r_paren)) { 145 Diag(Tok, diag::err_expected_rparen); 146 SkipUntil(tok::r_paren, false); // don't stop at ';' 147 return 0; 148 } 149 rparenLoc = ConsumeParen(); 150 151 // Next, we need to check for any protocol references. 152 SourceLocation EndProtoLoc; 153 llvm::SmallVector<DeclTy *, 8> ProtocolRefs; 154 if (Tok.is(tok::less) && 155 ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc)) 156 return 0; 157 158 if (attrList) // categories don't support attributes. 159 Diag(Tok, diag::err_objc_no_attributes_on_category); 160 161 DeclTy *CategoryType = Actions.ActOnStartCategoryInterface(atLoc, 162 nameId, nameLoc, categoryId, categoryLoc, 163 &ProtocolRefs[0], ProtocolRefs.size(), 164 EndProtoLoc); 165 166 ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); 167 return CategoryType; 168 } 169 // Parse a class interface. 170 IdentifierInfo *superClassId = 0; 171 SourceLocation superClassLoc; 172 173 if (Tok.is(tok::colon)) { // a super class is specified. 174 ConsumeToken(); 175 if (Tok.isNot(tok::identifier)) { 176 Diag(Tok, diag::err_expected_ident); // missing super class name. 177 return 0; 178 } 179 superClassId = Tok.getIdentifierInfo(); 180 superClassLoc = ConsumeToken(); 181 } 182 // Next, we need to check for any protocol references. 183 llvm::SmallVector<Action::DeclTy*, 8> ProtocolRefs; 184 SourceLocation EndProtoLoc; 185 if (Tok.is(tok::less) && 186 ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc)) 187 return 0; 188 189 DeclTy *ClsType = 190 Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc, 191 superClassId, superClassLoc, 192 &ProtocolRefs[0], ProtocolRefs.size(), 193 EndProtoLoc, attrList); 194 195 if (Tok.is(tok::l_brace)) 196 ParseObjCClassInstanceVariables(ClsType, atLoc); 197 198 ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); 199 return ClsType; 200 } 201 202 /// constructSetterName - Return the setter name for the given 203 /// identifier, i.e. "set" + Name where the initial character of Name 204 /// has been capitalized. 205 static IdentifierInfo *constructSetterName(IdentifierTable &Idents, 206 const IdentifierInfo *Name) { 207 llvm::SmallString<100> SelectorName; 208 SelectorName = "set"; 209 SelectorName.append(Name->getName(), Name->getName()+Name->getLength()); 210 SelectorName[3] = toupper(SelectorName[3]); 211 return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]); 212 } 213 214 /// objc-interface-decl-list: 215 /// empty 216 /// objc-interface-decl-list objc-property-decl [OBJC2] 217 /// objc-interface-decl-list objc-method-requirement [OBJC2] 218 /// objc-interface-decl-list objc-method-proto ';' 219 /// objc-interface-decl-list declaration 220 /// objc-interface-decl-list ';' 221 /// 222 /// objc-method-requirement: [OBJC2] 223 /// @required 224 /// @optional 225 /// 226 void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, 227 tok::ObjCKeywordKind contextKey) { 228 llvm::SmallVector<DeclTy*, 32> allMethods; 229 llvm::SmallVector<DeclTy*, 16> allProperties; 230 tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; 231 232 SourceLocation AtEndLoc; 233 234 while (1) { 235 // If this is a method prototype, parse it. 236 if (Tok.is(tok::minus) || Tok.is(tok::plus)) { 237 DeclTy *methodPrototype = 238 ParseObjCMethodPrototype(interfaceDecl, MethodImplKind); 239 allMethods.push_back(methodPrototype); 240 // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for 241 // method definitions. 242 ExpectAndConsume(tok::semi, diag::err_expected_semi_after,"method proto"); 243 continue; 244 } 245 246 // Ignore excess semicolons. 247 if (Tok.is(tok::semi)) { 248 ConsumeToken(); 249 continue; 250 } 251 252 // If we got to the end of the file, exit the loop. 253 if (Tok.is(tok::eof)) 254 break; 255 256 // If we don't have an @ directive, parse it as a function definition. 257 if (Tok.isNot(tok::at)) { 258 // The code below does not consume '}'s because it is afraid of eating the 259 // end of a namespace. Because of the way this code is structured, an 260 // erroneous r_brace would cause an infinite loop if not handled here. 261 if (Tok.is(tok::r_brace)) 262 break; 263 264 // FIXME: as the name implies, this rule allows function definitions. 265 // We could pass a flag or check for functions during semantic analysis. 266 ParseDeclarationOrFunctionDefinition(); 267 continue; 268 } 269 270 // Otherwise, we have an @ directive, eat the @. 271 SourceLocation AtLoc = ConsumeToken(); // the "@" 272 tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); 273 274 if (DirectiveKind == tok::objc_end) { // @end -> terminate list 275 AtEndLoc = AtLoc; 276 break; 277 } 278 279 // Eat the identifier. 280 ConsumeToken(); 281 282 switch (DirectiveKind) { 283 default: 284 // FIXME: If someone forgets an @end on a protocol, this loop will 285 // continue to eat up tons of stuff and spew lots of nonsense errors. It 286 // would probably be better to bail out if we saw an @class or @interface 287 // or something like that. 288 Diag(AtLoc, diag::err_objc_illegal_interface_qual); 289 // Skip until we see an '@' or '}' or ';'. 290 SkipUntil(tok::r_brace, tok::at); 291 break; 292 293 case tok::objc_required: 294 case tok::objc_optional: 295 // This is only valid on protocols. 296 // FIXME: Should this check for ObjC2 being enabled? 297 if (contextKey != tok::objc_protocol) 298 Diag(AtLoc, diag::err_objc_directive_only_in_protocol); 299 else 300 MethodImplKind = DirectiveKind; 301 break; 302 303 case tok::objc_property: 304 if (!getLang().ObjC2) 305 Diag(AtLoc, diag::err_objc_propertoes_require_objc2); 306 307 ObjCDeclSpec OCDS; 308 // Parse property attribute list, if any. 309 if (Tok.is(tok::l_paren)) 310 ParseObjCPropertyAttribute(OCDS); 311 312 // Parse all the comma separated declarators. 313 DeclSpec DS; 314 llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; 315 ParseStructDeclaration(DS, FieldDeclarators); 316 317 ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", 318 tok::at); 319 320 // Convert them all to property declarations. 321 for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { 322 FieldDeclarator &FD = FieldDeclarators[i]; 323 if (FD.D.getIdentifier() == 0) { 324 Diag(AtLoc, diag::err_objc_property_requires_field_name) 325 << FD.D.getSourceRange(); 326 continue; 327 } 328 if (FD.BitfieldSize) { 329 Diag(AtLoc, diag::err_objc_property_bitfield) 330 << FD.D.getSourceRange(); 331 continue; 332 } 333 334 // Install the property declarator into interfaceDecl. 335 IdentifierInfo *SelName = 336 OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); 337 338 Selector GetterSel = 339 PP.getSelectorTable().getNullarySelector(SelName); 340 IdentifierInfo *SetterName = OCDS.getSetterName(); 341 if (!SetterName) 342 SetterName = constructSetterName(PP.getIdentifierTable(), 343 FD.D.getIdentifier()); 344 Selector SetterSel = 345 PP.getSelectorTable().getUnarySelector(SetterName); 346 bool isOverridingProperty = false; 347 DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS, 348 GetterSel, SetterSel, 349 interfaceDecl, 350 &isOverridingProperty, 351 MethodImplKind); 352 if (!isOverridingProperty) 353 allProperties.push_back(Property); 354 } 355 break; 356 } 357 } 358 359 // We break out of the big loop in two cases: when we see @end or when we see 360 // EOF. In the former case, eat the @end. In the later case, emit an error. 361 if (Tok.isObjCAtKeyword(tok::objc_end)) 362 ConsumeToken(); // the "end" identifier 363 else 364 Diag(Tok, diag::err_objc_missing_end); 365 366 // Insert collected methods declarations into the @interface object. 367 // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. 368 Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, 369 allMethods.empty() ? 0 : &allMethods[0], 370 allMethods.size(), 371 allProperties.empty() ? 0 : &allProperties[0], 372 allProperties.size()); 373 } 374 375 /// Parse property attribute declarations. 376 /// 377 /// property-attr-decl: '(' property-attrlist ')' 378 /// property-attrlist: 379 /// property-attribute 380 /// property-attrlist ',' property-attribute 381 /// property-attribute: 382 /// getter '=' identifier 383 /// setter '=' identifier ':' 384 /// readonly 385 /// readwrite 386 /// assign 387 /// retain 388 /// copy 389 /// nonatomic 390 /// 391 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { 392 assert(Tok.getKind() == tok::l_paren); 393 SourceLocation LHSLoc = ConsumeParen(); // consume '(' 394 395 while (1) { 396 const IdentifierInfo *II = Tok.getIdentifierInfo(); 397 398 // If this is not an identifier at all, bail out early. 399 if (II == 0) { 400 MatchRHSPunctuation(tok::r_paren, LHSLoc); 401 return; 402 } 403 404 SourceLocation AttrName = ConsumeToken(); // consume last attribute name 405 406 if (II->isStr("readonly")) 407 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly); 408 else if (II->isStr("assign")) 409 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign); 410 else if (II->isStr("readwrite")) 411 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite); 412 else if (II->isStr("retain")) 413 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain); 414 else if (II->isStr("copy")) 415 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy); 416 else if (II->isStr("nonatomic")) 417 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic); 418 else if (II->isStr("getter") || II->isStr("setter")) { 419 // getter/setter require extra treatment. 420 if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "", 421 tok::r_paren)) 422 return; 423 424 if (Tok.isNot(tok::identifier)) { 425 Diag(Tok, diag::err_expected_ident); 426 SkipUntil(tok::r_paren); 427 return; 428 } 429 430 if (II->getName()[0] == 's') { 431 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); 432 DS.setSetterName(Tok.getIdentifierInfo()); 433 ConsumeToken(); // consume method name 434 435 if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "", 436 tok::r_paren)) 437 return; 438 } else { 439 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); 440 DS.setGetterName(Tok.getIdentifierInfo()); 441 ConsumeToken(); // consume method name 442 } 443 } else { 444 Diag(AttrName, diag::err_objc_expected_property_attr) << II; 445 SkipUntil(tok::r_paren); 446 return; 447 } 448 449 if (Tok.isNot(tok::comma)) 450 break; 451 452 ConsumeToken(); 453 } 454 455 MatchRHSPunctuation(tok::r_paren, LHSLoc); 456 } 457 458 /// objc-method-proto: 459 /// objc-instance-method objc-method-decl objc-method-attributes[opt] 460 /// objc-class-method objc-method-decl objc-method-attributes[opt] 461 /// 462 /// objc-instance-method: '-' 463 /// objc-class-method: '+' 464 /// 465 /// objc-method-attributes: [OBJC2] 466 /// __attribute__((deprecated)) 467 /// 468 Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl, 469 tok::ObjCKeywordKind MethodImplKind) { 470 assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); 471 472 tok::TokenKind methodType = Tok.getKind(); 473 SourceLocation mLoc = ConsumeToken(); 474 475 DeclTy *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl, MethodImplKind); 476 // Since this rule is used for both method declarations and definitions, 477 // the caller is (optionally) responsible for consuming the ';'. 478 return MDecl; 479 } 480 481 /// objc-selector: 482 /// identifier 483 /// one of 484 /// enum struct union if else while do for switch case default 485 /// break continue return goto asm sizeof typeof __alignof 486 /// unsigned long const short volatile signed restrict _Complex 487 /// in out inout bycopy byref oneway int char float double void _Bool 488 /// 489 IdentifierInfo *Parser::ParseObjCSelector(SourceLocation &SelectorLoc) { 490 switch (Tok.getKind()) { 491 default: 492 return 0; 493 case tok::identifier: 494 case tok::kw_asm: 495 case tok::kw_auto: 496 case tok::kw_bool: 497 case tok::kw_break: 498 case tok::kw_case: 499 case tok::kw_catch: 500 case tok::kw_char: 501 case tok::kw_class: 502 case tok::kw_const: 503 case tok::kw_const_cast: 504 case tok::kw_continue: 505 case tok::kw_default: 506 case tok::kw_delete: 507 case tok::kw_do: 508 case tok::kw_double: 509 case tok::kw_dynamic_cast: 510 case tok::kw_else: 511 case tok::kw_enum: 512 case tok::kw_explicit: 513 case tok::kw_export: 514 case tok::kw_extern: 515 case tok::kw_false: 516 case tok::kw_float: 517 case tok::kw_for: 518 case tok::kw_friend: 519 case tok::kw_goto: 520 case tok::kw_if: 521 case tok::kw_inline: 522 case tok::kw_int: 523 case tok::kw_long: 524 case tok::kw_mutable: 525 case tok::kw_namespace: 526 case tok::kw_new: 527 case tok::kw_operator: 528 case tok::kw_private: 529 case tok::kw_protected: 530 case tok::kw_public: 531 case tok::kw_register: 532 case tok::kw_reinterpret_cast: 533 case tok::kw_restrict: 534 case tok::kw_return: 535 case tok::kw_short: 536 case tok::kw_signed: 537 case tok::kw_sizeof: 538 case tok::kw_static: 539 case tok::kw_static_cast: 540 case tok::kw_struct: 541 case tok::kw_switch: 542 case tok::kw_template: 543 case tok::kw_this: 544 case tok::kw_throw: 545 case tok::kw_true: 546 case tok::kw_try: 547 case tok::kw_typedef: 548 case tok::kw_typeid: 549 case tok::kw_typename: 550 case tok::kw_typeof: 551 case tok::kw_union: 552 case tok::kw_unsigned: 553 case tok::kw_using: 554 case tok::kw_virtual: 555 case tok::kw_void: 556 case tok::kw_volatile: 557 case tok::kw_wchar_t: 558 case tok::kw_while: 559 case tok::kw__Bool: 560 case tok::kw__Complex: 561 case tok::kw___alignof: 562 IdentifierInfo *II = Tok.getIdentifierInfo(); 563 SelectorLoc = ConsumeToken(); 564 return II; 565 } 566 } 567 568 /// objc-for-collection-in: 'in' 569 /// 570 bool Parser::isTokIdentifier_in() const { 571 // FIXME: May have to do additional look-ahead to only allow for 572 // valid tokens following an 'in'; such as an identifier, unary operators, 573 // '[' etc. 574 return (getLang().ObjC2 && Tok.is(tok::identifier) && 575 Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); 576 } 577 578 /// ParseObjCTypeQualifierList - This routine parses the objective-c's type 579 /// qualifier list and builds their bitmask representation in the input 580 /// argument. 581 /// 582 /// objc-type-qualifiers: 583 /// objc-type-qualifier 584 /// objc-type-qualifiers objc-type-qualifier 585 /// 586 void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) { 587 while (1) { 588 if (Tok.isNot(tok::identifier)) 589 return; 590 591 const IdentifierInfo *II = Tok.getIdentifierInfo(); 592 for (unsigned i = 0; i != objc_NumQuals; ++i) { 593 if (II != ObjCTypeQuals[i]) 594 continue; 595 596 ObjCDeclSpec::ObjCDeclQualifier Qual; 597 switch (i) { 598 default: assert(0 && "Unknown decl qualifier"); 599 case objc_in: Qual = ObjCDeclSpec::DQ_In; break; 600 case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; 601 case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; 602 case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; 603 case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; 604 case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; 605 } 606 DS.setObjCDeclQualifier(Qual); 607 ConsumeToken(); 608 II = 0; 609 break; 610 } 611 612 // If this wasn't a recognized qualifier, bail out. 613 if (II) return; 614 } 615 } 616 617 /// objc-type-name: 618 /// '(' objc-type-qualifiers[opt] type-name ')' 619 /// '(' objc-type-qualifiers[opt] ')' 620 /// 621 Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) { 622 assert(Tok.is(tok::l_paren) && "expected ("); 623 624 SourceLocation LParenLoc = ConsumeParen(); 625 SourceLocation TypeStartLoc = Tok.getLocation(); 626 627 // Parse type qualifiers, in, inout, etc. 628 ParseObjCTypeQualifierList(DS); 629 630 TypeTy *Ty = 0; 631 if (isTypeSpecifierQualifier()) 632 Ty = ParseTypeName(); 633 634 if (Tok.is(tok::r_paren)) 635 ConsumeParen(); 636 else if (Tok.getLocation() == TypeStartLoc) { 637 // If we didn't eat any tokens, then this isn't a type. 638 Diag(Tok, diag::err_expected_type); 639 SkipUntil(tok::r_paren); 640 } else { 641 // Otherwise, we found *something*, but didn't get a ')' in the right 642 // place. Emit an error then return what we have as the type. 643 MatchRHSPunctuation(tok::r_paren, LParenLoc); 644 } 645 return Ty; 646 } 647 648 /// objc-method-decl: 649 /// objc-selector 650 /// objc-keyword-selector objc-parmlist[opt] 651 /// objc-type-name objc-selector 652 /// objc-type-name objc-keyword-selector objc-parmlist[opt] 653 /// 654 /// objc-keyword-selector: 655 /// objc-keyword-decl 656 /// objc-keyword-selector objc-keyword-decl 657 /// 658 /// objc-keyword-decl: 659 /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier 660 /// objc-selector ':' objc-keyword-attributes[opt] identifier 661 /// ':' objc-type-name objc-keyword-attributes[opt] identifier 662 /// ':' objc-keyword-attributes[opt] identifier 663 /// 664 /// objc-parmlist: 665 /// objc-parms objc-ellipsis[opt] 666 /// 667 /// objc-parms: 668 /// objc-parms , parameter-declaration 669 /// 670 /// objc-ellipsis: 671 /// , ... 672 /// 673 /// objc-keyword-attributes: [OBJC2] 674 /// __attribute__((unused)) 675 /// 676 Parser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc, 677 tok::TokenKind mType, 678 DeclTy *IDecl, 679 tok::ObjCKeywordKind MethodImplKind) 680 { 681 // Parse the return type if present. 682 TypeTy *ReturnType = 0; 683 ObjCDeclSpec DSRet; 684 if (Tok.is(tok::l_paren)) 685 ReturnType = ParseObjCTypeName(DSRet); 686 687 SourceLocation selLoc; 688 IdentifierInfo *SelIdent = ParseObjCSelector(selLoc); 689 690 if (!SelIdent) { // 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 /// 791 bool Parser:: 792 ParseObjCProtocolReferences(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 /// 850 void 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. 937 Parser::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 1014 Parser::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 1077 Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) { 1078 assert(Tok.isObjCAtKeyword(tok::objc_end) && 1079 "ParseObjCAtEndDeclaration(): Expected @end"); 1080 ConsumeToken(); // the "end" identifier 1081 if (ObjCImpDecl) 1082 Actions.ActOnAtEnd(atLoc, ObjCImpDecl); 1083 else 1084 Diag(atLoc, diag::warn_expected_implementation); // missing @implementation 1085 return ObjCImpDecl; 1086 } 1087 1088 /// compatibility-alias-decl: 1089 /// @compatibility_alias alias-name class-name ';' 1090 /// 1091 Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { 1092 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && 1093 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); 1094 ConsumeToken(); // consume compatibility_alias 1095 if (Tok.isNot(tok::identifier)) { 1096 Diag(Tok, diag::err_expected_ident); 1097 return 0; 1098 } 1099 IdentifierInfo *aliasId = Tok.getIdentifierInfo(); 1100 SourceLocation aliasLoc = ConsumeToken(); // consume alias-name 1101 if (Tok.isNot(tok::identifier)) { 1102 Diag(Tok, diag::err_expected_ident); 1103 return 0; 1104 } 1105 IdentifierInfo *classId = Tok.getIdentifierInfo(); 1106 SourceLocation classLoc = ConsumeToken(); // consume class-name; 1107 if (Tok.isNot(tok::semi)) { 1108 Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias"; 1109 return 0; 1110 } 1111 DeclTy *ClsType = Actions.ActOnCompatiblityAlias(atLoc, 1112 aliasId, aliasLoc, 1113 classId, classLoc); 1114 return ClsType; 1115 } 1116 1117 /// property-synthesis: 1118 /// @synthesize property-ivar-list ';' 1119 /// 1120 /// property-ivar-list: 1121 /// property-ivar 1122 /// property-ivar-list ',' property-ivar 1123 /// 1124 /// property-ivar: 1125 /// identifier 1126 /// identifier '=' identifier 1127 /// 1128 Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { 1129 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && 1130 "ParseObjCPropertyDynamic(): Expected '@synthesize'"); 1131 SourceLocation loc = ConsumeToken(); // consume synthesize 1132 if (Tok.isNot(tok::identifier)) { 1133 Diag(Tok, diag::err_expected_ident); 1134 return 0; 1135 } 1136 while (Tok.is(tok::identifier)) { 1137 IdentifierInfo *propertyIvar = 0; 1138 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1139 SourceLocation propertyLoc = ConsumeToken(); // consume property name 1140 if (Tok.is(tok::equal)) { 1141 // property '=' ivar-name 1142 ConsumeToken(); // consume '=' 1143 if (Tok.isNot(tok::identifier)) { 1144 Diag(Tok, diag::err_expected_ident); 1145 break; 1146 } 1147 propertyIvar = Tok.getIdentifierInfo(); 1148 ConsumeToken(); // consume ivar-name 1149 } 1150 Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl, 1151 propertyId, propertyIvar); 1152 if (Tok.isNot(tok::comma)) 1153 break; 1154 ConsumeToken(); // consume ',' 1155 } 1156 if (Tok.isNot(tok::semi)) 1157 Diag(Tok, diag::err_expected_semi_after) << "@synthesize"; 1158 return 0; 1159 } 1160 1161 /// property-dynamic: 1162 /// @dynamic property-list 1163 /// 1164 /// property-list: 1165 /// identifier 1166 /// property-list ',' identifier 1167 /// 1168 Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { 1169 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && 1170 "ParseObjCPropertyDynamic(): Expected '@dynamic'"); 1171 SourceLocation loc = ConsumeToken(); // consume dynamic 1172 if (Tok.isNot(tok::identifier)) { 1173 Diag(Tok, diag::err_expected_ident); 1174 return 0; 1175 } 1176 while (Tok.is(tok::identifier)) { 1177 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1178 SourceLocation propertyLoc = ConsumeToken(); // consume property name 1179 Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl, 1180 propertyId, 0); 1181 1182 if (Tok.isNot(tok::comma)) 1183 break; 1184 ConsumeToken(); // consume ',' 1185 } 1186 if (Tok.isNot(tok::semi)) 1187 Diag(Tok, diag::err_expected_semi_after) << "@dynamic"; 1188 return 0; 1189 } 1190 1191 /// objc-throw-statement: 1192 /// throw expression[opt]; 1193 /// 1194 Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { 1195 OwningExprResult Res(Actions); 1196 ConsumeToken(); // consume throw 1197 if (Tok.isNot(tok::semi)) { 1198 Res = ParseExpression(); 1199 if (Res.isInvalid()) { 1200 SkipUntil(tok::semi); 1201 return StmtError(); 1202 } 1203 } 1204 ConsumeToken(); // consume ';' 1205 return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope); 1206 } 1207 1208 /// objc-synchronized-statement: 1209 /// @synchronized '(' expression ')' compound-statement 1210 /// 1211 Parser::OwningStmtResult 1212 Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { 1213 ConsumeToken(); // consume synchronized 1214 if (Tok.isNot(tok::l_paren)) { 1215 Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; 1216 return StmtError(); 1217 } 1218 ConsumeParen(); // '(' 1219 OwningExprResult Res(ParseExpression()); 1220 if (Res.isInvalid()) { 1221 SkipUntil(tok::semi); 1222 return StmtError(); 1223 } 1224 if (Tok.isNot(tok::r_paren)) { 1225 Diag(Tok, diag::err_expected_lbrace); 1226 return StmtError(); 1227 } 1228 ConsumeParen(); // ')' 1229 if (Tok.isNot(tok::l_brace)) { 1230 Diag(Tok, diag::err_expected_lbrace); 1231 return StmtError(); 1232 } 1233 // Enter a scope to hold everything within the compound stmt. Compound 1234 // statements can always hold declarations. 1235 ParseScope BodyScope(this, Scope::DeclScope); 1236 1237 OwningStmtResult SynchBody(ParseCompoundStatementBody()); 1238 1239 BodyScope.Exit(); 1240 if (SynchBody.isInvalid()) 1241 SynchBody = Actions.ActOnNullStmt(Tok.getLocation()); 1242 return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody)); 1243 } 1244 1245 /// objc-try-catch-statement: 1246 /// @try compound-statement objc-catch-list[opt] 1247 /// @try compound-statement objc-catch-list[opt] @finally compound-statement 1248 /// 1249 /// objc-catch-list: 1250 /// @catch ( parameter-declaration ) compound-statement 1251 /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement 1252 /// catch-parameter-declaration: 1253 /// parameter-declaration 1254 /// '...' [OBJC2] 1255 /// 1256 Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { 1257 bool catch_or_finally_seen = false; 1258 1259 ConsumeToken(); // consume try 1260 if (Tok.isNot(tok::l_brace)) { 1261 Diag(Tok, diag::err_expected_lbrace); 1262 return StmtError(); 1263 } 1264 OwningStmtResult CatchStmts(Actions); 1265 OwningStmtResult FinallyStmt(Actions); 1266 ParseScope TryScope(this, Scope::DeclScope); 1267 OwningStmtResult TryBody(ParseCompoundStatementBody()); 1268 TryScope.Exit(); 1269 if (TryBody.isInvalid()) 1270 TryBody = Actions.ActOnNullStmt(Tok.getLocation()); 1271 1272 while (Tok.is(tok::at)) { 1273 // At this point, we need to lookahead to determine if this @ is the start 1274 // of an @catch or @finally. We don't want to consume the @ token if this 1275 // is an @try or @encode or something else. 1276 Token AfterAt = GetLookAheadToken(1); 1277 if (!AfterAt.isObjCAtKeyword(tok::objc_catch) && 1278 !AfterAt.isObjCAtKeyword(tok::objc_finally)) 1279 break; 1280 1281 SourceLocation AtCatchFinallyLoc = ConsumeToken(); 1282 if (Tok.isObjCAtKeyword(tok::objc_catch)) { 1283 OwningStmtResult FirstPart(Actions); 1284 ConsumeToken(); // consume catch 1285 if (Tok.is(tok::l_paren)) { 1286 ConsumeParen(); 1287 ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope); 1288 if (Tok.isNot(tok::ellipsis)) { 1289 DeclSpec DS; 1290 ParseDeclarationSpecifiers(DS); 1291 // For some odd reason, the name of the exception variable is 1292 // optional. As a result, we need to use PrototypeContext. 1293 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext); 1294 ParseDeclarator(DeclaratorInfo); 1295 if (DeclaratorInfo.getIdentifier()) { 1296 DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope, 1297 DeclaratorInfo, 0); 1298 FirstPart = 1299 Actions.ActOnDeclStmt(aBlockVarDecl, 1300 DS.getSourceRange().getBegin(), 1301 DeclaratorInfo.getSourceRange().getEnd()); 1302 } 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, move(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 /// 1351 Parser::DeclTy *Parser::ParseObjCMethodDefinition() { 1352 DeclTy *MDecl = ParseObjCMethodPrototype(ObjCImpDecl); 1353 // parse optional ';' 1354 if (Tok.is(tok::semi)) 1355 ConsumeToken(); 1356 1357 // We should have an opening brace now. 1358 if (Tok.isNot(tok::l_brace)) { 1359 Diag(Tok, diag::err_expected_method_body); 1360 1361 // Skip over garbage, until we get to '{'. Don't eat the '{'. 1362 SkipUntil(tok::l_brace, true, true); 1363 1364 // If we didn't find the '{', bail out. 1365 if (Tok.isNot(tok::l_brace)) 1366 return 0; 1367 } 1368 SourceLocation BraceLoc = Tok.getLocation(); 1369 1370 // Enter a scope for the method body. 1371 ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); 1372 1373 // Tell the actions module that we have entered a method definition with the 1374 // specified Declarator for the method. 1375 Actions.ObjCActOnStartOfMethodDef(CurScope, MDecl); 1376 1377 OwningStmtResult FnBody(ParseCompoundStatementBody()); 1378 1379 // If the function body could not be parsed, make a bogus compoundstmt. 1380 if (FnBody.isInvalid()) 1381 FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, 1382 MultiStmtArg(Actions), false); 1383 1384 // Leave the function body scope. 1385 BodyScope.Exit(); 1386 1387 // TODO: Pass argument information. 1388 Actions.ActOnFinishFunctionBody(MDecl, move(FnBody)); 1389 return MDecl; 1390 } 1391 1392 Parser::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 1412 Parser::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 1441 Parser::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 /// 1484 Parser::OwningExprResult 1485 Parser::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 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; 1494 ExprVector KeyExprs(Actions); 1495 1496 if (Tok.is(tok::colon)) { 1497 while (1) { 1498 // Each iteration parses a single keyword argument. 1499 KeyIdents.push_back(selIdent); 1500 1501 if (Tok.isNot(tok::colon)) { 1502 Diag(Tok, diag::err_expected_colon); 1503 // We must manually skip to a ']', otherwise the expression skipper will 1504 // stop at the ']' when it skips to the ';'. We want it to skip beyond 1505 // the enclosing expression. 1506 SkipUntil(tok::r_square); 1507 return ExprError(); 1508 } 1509 1510 ConsumeToken(); // Eat the ':'. 1511 /// Parse the expression after ':' 1512 OwningExprResult Res(ParseAssignmentExpression()); 1513 if (Res.isInvalid()) { 1514 // We must manually skip to a ']', otherwise the expression skipper will 1515 // stop at the ']' when it skips to the ';'. We want it to skip beyond 1516 // the enclosing expression. 1517 SkipUntil(tok::r_square); 1518 return move(Res); 1519 } 1520 1521 // We have a valid expression. 1522 KeyExprs.push_back(Res.release()); 1523 1524 // Check for another keyword selector. 1525 selIdent = ParseObjCSelector(Loc); 1526 if (!selIdent && Tok.isNot(tok::colon)) 1527 break; 1528 // We have a selector or a colon, continue parsing. 1529 } 1530 // Parse the, optional, argument list, comma separated. 1531 while (Tok.is(tok::comma)) { 1532 ConsumeToken(); // Eat the ','. 1533 /// Parse the expression after ',' 1534 OwningExprResult Res(ParseAssignmentExpression()); 1535 if (Res.isInvalid()) { 1536 // We must manually skip to a ']', otherwise the expression skipper will 1537 // stop at the ']' when it skips to the ';'. We want it to skip beyond 1538 // the enclosing expression. 1539 SkipUntil(tok::r_square); 1540 return move(Res); 1541 } 1542 1543 // We have a valid expression. 1544 KeyExprs.push_back(Res.release()); 1545 } 1546 } else if (!selIdent) { 1547 Diag(Tok, diag::err_expected_ident); // missing selector name. 1548 1549 // We must manually skip to a ']', otherwise the expression skipper will 1550 // stop at the ']' when it skips to the ';'. We want it to skip beyond 1551 // the enclosing expression. 1552 SkipUntil(tok::r_square); 1553 return ExprError(); 1554 } 1555 1556 if (Tok.isNot(tok::r_square)) { 1557 Diag(Tok, diag::err_expected_rsquare); 1558 // We must manually skip to a ']', otherwise the expression skipper will 1559 // stop at the ']' when it skips to the ';'. We want it to skip beyond 1560 // the enclosing expression. 1561 SkipUntil(tok::r_square); 1562 return ExprError(); 1563 } 1564 1565 SourceLocation RBracLoc = ConsumeBracket(); // consume ']' 1566 1567 unsigned nKeys = KeyIdents.size(); 1568 if (nKeys == 0) 1569 KeyIdents.push_back(selIdent); 1570 Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); 1571 1572 // We've just parsed a keyword message. 1573 if (ReceiverName) 1574 return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel, 1575 LBracLoc, NameLoc, RBracLoc, 1576 KeyExprs.take(), KeyExprs.size())); 1577 return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel, 1578 LBracLoc, RBracLoc, 1579 KeyExprs.take(), KeyExprs.size())); 1580 } 1581 1582 Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { 1583 OwningExprResult Res(ParseStringLiteralExpression()); 1584 if (Res.isInvalid()) return move(Res); 1585 1586 // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string 1587 // expressions. At this point, we know that the only valid thing that starts 1588 // with '@' is an @"". 1589 llvm::SmallVector<SourceLocation, 4> AtLocs; 1590 ExprVector AtStrings(Actions); 1591 AtLocs.push_back(AtLoc); 1592 AtStrings.push_back(Res.release()); 1593 1594 while (Tok.is(tok::at)) { 1595 AtLocs.push_back(ConsumeToken()); // eat the @. 1596 1597 // Invalid unless there is a string literal. 1598 OwningExprResult Lit(Actions, true); 1599 if (isTokenStringLiteral()) 1600 Lit = ParseStringLiteralExpression(); 1601 else 1602 Diag(Tok, diag::err_objc_concat_string); 1603 1604 if (Lit.isInvalid()) 1605 return move(Lit); 1606 1607 AtStrings.push_back(Lit.release()); 1608 } 1609 1610 return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(), 1611 AtStrings.size())); 1612 } 1613 1614 /// objc-encode-expression: 1615 /// @encode ( type-name ) 1616 Parser::OwningExprResult 1617 Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { 1618 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!"); 1619 1620 SourceLocation EncLoc = ConsumeToken(); 1621 1622 if (Tok.isNot(tok::l_paren)) 1623 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode"); 1624 1625 SourceLocation LParenLoc = ConsumeParen(); 1626 1627 TypeTy *Ty = ParseTypeName(); 1628 1629 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 1630 1631 return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty, 1632 RParenLoc)); 1633 } 1634 1635 /// objc-protocol-expression 1636 /// @protocol ( protocol-name ) 1637 Parser::OwningExprResult 1638 Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { 1639 SourceLocation ProtoLoc = ConsumeToken(); 1640 1641 if (Tok.isNot(tok::l_paren)) 1642 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol"); 1643 1644 SourceLocation LParenLoc = ConsumeParen(); 1645 1646 if (Tok.isNot(tok::identifier)) 1647 return ExprError(Diag(Tok, diag::err_expected_ident)); 1648 1649 IdentifierInfo *protocolId = Tok.getIdentifierInfo(); 1650 ConsumeToken(); 1651 1652 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 1653 1654 return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, 1655 LParenLoc, RParenLoc)); 1656 } 1657 1658 /// objc-selector-expression 1659 /// @selector '(' objc-keyword-selector ')' 1660 Parser::OwningExprResult 1661 Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { 1662 SourceLocation SelectorLoc = ConsumeToken(); 1663 1664 if (Tok.isNot(tok::l_paren)) 1665 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector"); 1666 1667 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; 1668 SourceLocation LParenLoc = ConsumeParen(); 1669 SourceLocation sLoc; 1670 IdentifierInfo *SelIdent = ParseObjCSelector(sLoc); 1671 if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name. 1672 return ExprError(Diag(Tok, diag::err_expected_ident)); 1673 1674 KeyIdents.push_back(SelIdent); 1675 unsigned nColons = 0; 1676 if (Tok.isNot(tok::r_paren)) { 1677 while (1) { 1678 if (Tok.isNot(tok::colon)) 1679 return ExprError(Diag(Tok, diag::err_expected_colon)); 1680 1681 nColons++; 1682 ConsumeToken(); // Eat the ':'. 1683 if (Tok.is(tok::r_paren)) 1684 break; 1685 // Check for another keyword selector. 1686 SourceLocation Loc; 1687 SelIdent = ParseObjCSelector(Loc); 1688 KeyIdents.push_back(SelIdent); 1689 if (!SelIdent && Tok.isNot(tok::colon)) 1690 break; 1691 } 1692 } 1693 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 1694 Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); 1695 return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, 1696 LParenLoc, RParenLoc)); 1697 } 1698