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 "", tok::semi); 244 continue; 245 } 246 247 // Ignore excess semicolons. 248 if (Tok.is(tok::semi)) { 249 ConsumeToken(); 250 continue; 251 } 252 253 // If we got to the end of the file, exit the loop. 254 if (Tok.is(tok::eof)) 255 break; 256 257 // If we don't have an @ directive, parse it as a function definition. 258 if (Tok.isNot(tok::at)) { 259 // The code below does not consume '}'s because it is afraid of eating the 260 // end of a namespace. Because of the way this code is structured, an 261 // erroneous r_brace would cause an infinite loop if not handled here. 262 if (Tok.is(tok::r_brace)) 263 break; 264 265 // FIXME: as the name implies, this rule allows function definitions. 266 // We could pass a flag or check for functions during semantic analysis. 267 ParseDeclarationOrFunctionDefinition(); 268 continue; 269 } 270 271 // Otherwise, we have an @ directive, eat the @. 272 SourceLocation AtLoc = ConsumeToken(); // the "@" 273 tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); 274 275 if (DirectiveKind == tok::objc_end) { // @end -> terminate list 276 AtEndLoc = AtLoc; 277 break; 278 } 279 280 // Eat the identifier. 281 ConsumeToken(); 282 283 switch (DirectiveKind) { 284 default: 285 // FIXME: If someone forgets an @end on a protocol, this loop will 286 // continue to eat up tons of stuff and spew lots of nonsense errors. It 287 // would probably be better to bail out if we saw an @class or @interface 288 // or something like that. 289 Diag(AtLoc, diag::err_objc_illegal_interface_qual); 290 // Skip until we see an '@' or '}' or ';'. 291 SkipUntil(tok::r_brace, tok::at); 292 break; 293 294 case tok::objc_required: 295 case tok::objc_optional: 296 // This is only valid on protocols. 297 // FIXME: Should this check for ObjC2 being enabled? 298 if (contextKey != tok::objc_protocol) 299 Diag(AtLoc, diag::err_objc_directive_only_in_protocol); 300 else 301 MethodImplKind = DirectiveKind; 302 break; 303 304 case tok::objc_property: 305 if (!getLang().ObjC2) 306 Diag(AtLoc, diag::err_objc_propertoes_require_objc2); 307 308 ObjCDeclSpec OCDS; 309 // Parse property attribute list, if any. 310 if (Tok.is(tok::l_paren)) 311 ParseObjCPropertyAttribute(OCDS); 312 313 // Parse all the comma separated declarators. 314 DeclSpec DS; 315 llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; 316 ParseStructDeclaration(DS, FieldDeclarators); 317 318 ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", 319 tok::at); 320 321 // Convert them all to property declarations. 322 for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { 323 FieldDeclarator &FD = FieldDeclarators[i]; 324 if (FD.D.getIdentifier() == 0) { 325 Diag(AtLoc, diag::err_objc_property_requires_field_name) 326 << FD.D.getSourceRange(); 327 continue; 328 } 329 if (FD.BitfieldSize) { 330 Diag(AtLoc, diag::err_objc_property_bitfield) 331 << FD.D.getSourceRange(); 332 continue; 333 } 334 335 // Install the property declarator into interfaceDecl. 336 IdentifierInfo *SelName = 337 OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); 338 339 Selector GetterSel = 340 PP.getSelectorTable().getNullarySelector(SelName); 341 IdentifierInfo *SetterName = OCDS.getSetterName(); 342 if (!SetterName) 343 SetterName = constructSetterName(PP.getIdentifierTable(), 344 FD.D.getIdentifier()); 345 Selector SetterSel = 346 PP.getSelectorTable().getUnarySelector(SetterName); 347 bool isOverridingProperty = false; 348 DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS, 349 GetterSel, SetterSel, 350 interfaceDecl, 351 &isOverridingProperty, 352 MethodImplKind); 353 if (!isOverridingProperty) 354 allProperties.push_back(Property); 355 } 356 break; 357 } 358 } 359 360 // We break out of the big loop in two cases: when we see @end or when we see 361 // EOF. In the former case, eat the @end. In the later case, emit an error. 362 if (Tok.isObjCAtKeyword(tok::objc_end)) 363 ConsumeToken(); // the "end" identifier 364 else 365 Diag(Tok, diag::err_objc_missing_end); 366 367 // Insert collected methods declarations into the @interface object. 368 // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. 369 Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, 370 allMethods.empty() ? 0 : &allMethods[0], 371 allMethods.size(), 372 allProperties.empty() ? 0 : &allProperties[0], 373 allProperties.size()); 374 } 375 376 /// Parse property attribute declarations. 377 /// 378 /// property-attr-decl: '(' property-attrlist ')' 379 /// property-attrlist: 380 /// property-attribute 381 /// property-attrlist ',' property-attribute 382 /// property-attribute: 383 /// getter '=' identifier 384 /// setter '=' identifier ':' 385 /// readonly 386 /// readwrite 387 /// assign 388 /// retain 389 /// copy 390 /// nonatomic 391 /// 392 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { 393 assert(Tok.getKind() == tok::l_paren); 394 SourceLocation LHSLoc = ConsumeParen(); // consume '(' 395 396 while (1) { 397 const IdentifierInfo *II = Tok.getIdentifierInfo(); 398 399 // If this is not an identifier at all, bail out early. 400 if (II == 0) { 401 MatchRHSPunctuation(tok::r_paren, LHSLoc); 402 return; 403 } 404 405 SourceLocation AttrName = ConsumeToken(); // consume last attribute name 406 407 if (II->isStr("readonly")) 408 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly); 409 else if (II->isStr("assign")) 410 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign); 411 else if (II->isStr("readwrite")) 412 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite); 413 else if (II->isStr("retain")) 414 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain); 415 else if (II->isStr("copy")) 416 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy); 417 else if (II->isStr("nonatomic")) 418 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic); 419 else if (II->isStr("getter") || II->isStr("setter")) { 420 // getter/setter require extra treatment. 421 if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "", 422 tok::r_paren)) 423 return; 424 425 if (Tok.isNot(tok::identifier)) { 426 Diag(Tok, diag::err_expected_ident); 427 SkipUntil(tok::r_paren); 428 return; 429 } 430 431 if (II->getName()[0] == 's') { 432 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); 433 DS.setSetterName(Tok.getIdentifierInfo()); 434 ConsumeToken(); // consume method name 435 436 if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "", 437 tok::r_paren)) 438 return; 439 } else { 440 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); 441 DS.setGetterName(Tok.getIdentifierInfo()); 442 ConsumeToken(); // consume method name 443 } 444 } else { 445 Diag(AttrName, diag::err_objc_expected_property_attr) << II; 446 SkipUntil(tok::r_paren); 447 return; 448 } 449 450 if (Tok.isNot(tok::comma)) 451 break; 452 453 ConsumeToken(); 454 } 455 456 MatchRHSPunctuation(tok::r_paren, LHSLoc); 457 } 458 459 /// objc-method-proto: 460 /// objc-instance-method objc-method-decl objc-method-attributes[opt] 461 /// objc-class-method objc-method-decl objc-method-attributes[opt] 462 /// 463 /// objc-instance-method: '-' 464 /// objc-class-method: '+' 465 /// 466 /// objc-method-attributes: [OBJC2] 467 /// __attribute__((deprecated)) 468 /// 469 Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl, 470 tok::ObjCKeywordKind MethodImplKind) { 471 assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); 472 473 tok::TokenKind methodType = Tok.getKind(); 474 SourceLocation mLoc = ConsumeToken(); 475 476 DeclTy *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl, MethodImplKind); 477 // Since this rule is used for both method declarations and definitions, 478 // the caller is (optionally) responsible for consuming the ';'. 479 return MDecl; 480 } 481 482 /// objc-selector: 483 /// identifier 484 /// one of 485 /// enum struct union if else while do for switch case default 486 /// break continue return goto asm sizeof typeof __alignof 487 /// unsigned long const short volatile signed restrict _Complex 488 /// in out inout bycopy byref oneway int char float double void _Bool 489 /// 490 IdentifierInfo *Parser::ParseObjCSelector(SourceLocation &SelectorLoc) { 491 switch (Tok.getKind()) { 492 default: 493 return 0; 494 case tok::identifier: 495 case tok::kw_asm: 496 case tok::kw_auto: 497 case tok::kw_bool: 498 case tok::kw_break: 499 case tok::kw_case: 500 case tok::kw_catch: 501 case tok::kw_char: 502 case tok::kw_class: 503 case tok::kw_const: 504 case tok::kw_const_cast: 505 case tok::kw_continue: 506 case tok::kw_default: 507 case tok::kw_delete: 508 case tok::kw_do: 509 case tok::kw_double: 510 case tok::kw_dynamic_cast: 511 case tok::kw_else: 512 case tok::kw_enum: 513 case tok::kw_explicit: 514 case tok::kw_export: 515 case tok::kw_extern: 516 case tok::kw_false: 517 case tok::kw_float: 518 case tok::kw_for: 519 case tok::kw_friend: 520 case tok::kw_goto: 521 case tok::kw_if: 522 case tok::kw_inline: 523 case tok::kw_int: 524 case tok::kw_long: 525 case tok::kw_mutable: 526 case tok::kw_namespace: 527 case tok::kw_new: 528 case tok::kw_operator: 529 case tok::kw_private: 530 case tok::kw_protected: 531 case tok::kw_public: 532 case tok::kw_register: 533 case tok::kw_reinterpret_cast: 534 case tok::kw_restrict: 535 case tok::kw_return: 536 case tok::kw_short: 537 case tok::kw_signed: 538 case tok::kw_sizeof: 539 case tok::kw_static: 540 case tok::kw_static_cast: 541 case tok::kw_struct: 542 case tok::kw_switch: 543 case tok::kw_template: 544 case tok::kw_this: 545 case tok::kw_throw: 546 case tok::kw_true: 547 case tok::kw_try: 548 case tok::kw_typedef: 549 case tok::kw_typeid: 550 case tok::kw_typename: 551 case tok::kw_typeof: 552 case tok::kw_union: 553 case tok::kw_unsigned: 554 case tok::kw_using: 555 case tok::kw_virtual: 556 case tok::kw_void: 557 case tok::kw_volatile: 558 case tok::kw_wchar_t: 559 case tok::kw_while: 560 case tok::kw__Bool: 561 case tok::kw__Complex: 562 case tok::kw___alignof: 563 IdentifierInfo *II = Tok.getIdentifierInfo(); 564 SelectorLoc = ConsumeToken(); 565 return II; 566 } 567 } 568 569 /// objc-for-collection-in: 'in' 570 /// 571 bool Parser::isTokIdentifier_in() const { 572 // FIXME: May have to do additional look-ahead to only allow for 573 // valid tokens following an 'in'; such as an identifier, unary operators, 574 // '[' etc. 575 return (getLang().ObjC2 && Tok.is(tok::identifier) && 576 Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); 577 } 578 579 /// ParseObjCTypeQualifierList - This routine parses the objective-c's type 580 /// qualifier list and builds their bitmask representation in the input 581 /// argument. 582 /// 583 /// objc-type-qualifiers: 584 /// objc-type-qualifier 585 /// objc-type-qualifiers objc-type-qualifier 586 /// 587 void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) { 588 while (1) { 589 if (Tok.isNot(tok::identifier)) 590 return; 591 592 const IdentifierInfo *II = Tok.getIdentifierInfo(); 593 for (unsigned i = 0; i != objc_NumQuals; ++i) { 594 if (II != ObjCTypeQuals[i]) 595 continue; 596 597 ObjCDeclSpec::ObjCDeclQualifier Qual; 598 switch (i) { 599 default: assert(0 && "Unknown decl qualifier"); 600 case objc_in: Qual = ObjCDeclSpec::DQ_In; break; 601 case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; 602 case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; 603 case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; 604 case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; 605 case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; 606 } 607 DS.setObjCDeclQualifier(Qual); 608 ConsumeToken(); 609 II = 0; 610 break; 611 } 612 613 // If this wasn't a recognized qualifier, bail out. 614 if (II) return; 615 } 616 } 617 618 /// objc-type-name: 619 /// '(' objc-type-qualifiers[opt] type-name ')' 620 /// '(' objc-type-qualifiers[opt] ')' 621 /// 622 Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) { 623 assert(Tok.is(tok::l_paren) && "expected ("); 624 625 SourceLocation LParenLoc = ConsumeParen(); 626 SourceLocation TypeStartLoc = Tok.getLocation(); 627 628 // Parse type qualifiers, in, inout, etc. 629 ParseObjCTypeQualifierList(DS); 630 631 TypeTy *Ty = 0; 632 if (isTypeSpecifierQualifier()) { 633 TypeResult TypeSpec = ParseTypeName(); 634 if (!TypeSpec.isInvalid()) 635 Ty = TypeSpec.get(); 636 } 637 638 if (Tok.is(tok::r_paren)) 639 ConsumeParen(); 640 else if (Tok.getLocation() == TypeStartLoc) { 641 // If we didn't eat any tokens, then this isn't a type. 642 Diag(Tok, diag::err_expected_type); 643 SkipUntil(tok::r_paren); 644 } else { 645 // Otherwise, we found *something*, but didn't get a ')' in the right 646 // place. Emit an error then return what we have as the type. 647 MatchRHSPunctuation(tok::r_paren, LParenLoc); 648 } 649 return Ty; 650 } 651 652 /// objc-method-decl: 653 /// objc-selector 654 /// objc-keyword-selector objc-parmlist[opt] 655 /// objc-type-name objc-selector 656 /// objc-type-name objc-keyword-selector objc-parmlist[opt] 657 /// 658 /// objc-keyword-selector: 659 /// objc-keyword-decl 660 /// objc-keyword-selector objc-keyword-decl 661 /// 662 /// objc-keyword-decl: 663 /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier 664 /// objc-selector ':' objc-keyword-attributes[opt] identifier 665 /// ':' objc-type-name objc-keyword-attributes[opt] identifier 666 /// ':' objc-keyword-attributes[opt] identifier 667 /// 668 /// objc-parmlist: 669 /// objc-parms objc-ellipsis[opt] 670 /// 671 /// objc-parms: 672 /// objc-parms , parameter-declaration 673 /// 674 /// objc-ellipsis: 675 /// , ... 676 /// 677 /// objc-keyword-attributes: [OBJC2] 678 /// __attribute__((unused)) 679 /// 680 Parser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc, 681 tok::TokenKind mType, 682 DeclTy *IDecl, 683 tok::ObjCKeywordKind MethodImplKind) 684 { 685 // Parse the return type if present. 686 TypeTy *ReturnType = 0; 687 ObjCDeclSpec DSRet; 688 if (Tok.is(tok::l_paren)) 689 ReturnType = ParseObjCTypeName(DSRet); 690 691 SourceLocation selLoc; 692 IdentifierInfo *SelIdent = ParseObjCSelector(selLoc); 693 694 // An unnamed colon is valid. 695 if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name. 696 Diag(Tok, diag::err_expected_selector_for_method) 697 << SourceRange(mLoc, Tok.getLocation()); 698 // Skip until we get a ; or {}. 699 SkipUntil(tok::r_brace); 700 return 0; 701 } 702 703 llvm::SmallVector<Declarator, 8> CargNames; 704 if (Tok.isNot(tok::colon)) { 705 // If attributes exist after the method, parse them. 706 AttributeList *MethodAttrs = 0; 707 if (getLang().ObjC2 && Tok.is(tok::kw___attribute)) 708 MethodAttrs = ParseAttributes(); 709 710 Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); 711 return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), 712 mType, IDecl, DSRet, ReturnType, Sel, 713 0, 0, 0, CargNames, 714 MethodAttrs, MethodImplKind); 715 } 716 717 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; 718 llvm::SmallVector<Action::TypeTy *, 12> KeyTypes; 719 llvm::SmallVector<ObjCDeclSpec, 12> ArgTypeQuals; 720 llvm::SmallVector<IdentifierInfo *, 12> ArgNames; 721 722 Action::TypeTy *TypeInfo; 723 while (1) { 724 KeyIdents.push_back(SelIdent); 725 726 // Each iteration parses a single keyword argument. 727 if (Tok.isNot(tok::colon)) { 728 Diag(Tok, diag::err_expected_colon); 729 break; 730 } 731 ConsumeToken(); // Eat the ':'. 732 ObjCDeclSpec DSType; 733 if (Tok.is(tok::l_paren)) // Parse the argument type. 734 TypeInfo = ParseObjCTypeName(DSType); 735 else 736 TypeInfo = 0; 737 KeyTypes.push_back(TypeInfo); 738 ArgTypeQuals.push_back(DSType); 739 740 // If attributes exist before the argument name, parse them. 741 if (getLang().ObjC2 && Tok.is(tok::kw___attribute)) 742 ParseAttributes(); // FIXME: pass attributes through. 743 744 if (Tok.isNot(tok::identifier)) { 745 Diag(Tok, diag::err_expected_ident); // missing argument name. 746 break; 747 } 748 ArgNames.push_back(Tok.getIdentifierInfo()); 749 ConsumeToken(); // Eat the identifier. 750 751 // Check for another keyword selector. 752 SourceLocation Loc; 753 SelIdent = ParseObjCSelector(Loc); 754 if (!SelIdent && Tok.isNot(tok::colon)) 755 break; 756 // We have a selector or a colon, continue parsing. 757 } 758 759 bool isVariadic = false; 760 761 // Parse the (optional) parameter list. 762 while (Tok.is(tok::comma)) { 763 ConsumeToken(); 764 if (Tok.is(tok::ellipsis)) { 765 isVariadic = true; 766 ConsumeToken(); 767 break; 768 } 769 DeclSpec DS; 770 ParseDeclarationSpecifiers(DS); 771 // Parse the declarator. 772 Declarator ParmDecl(DS, Declarator::PrototypeContext); 773 ParseDeclarator(ParmDecl); 774 CargNames.push_back(ParmDecl); 775 } 776 777 // FIXME: Add support for optional parmameter list... 778 // If attributes exist after the method, parse them. 779 AttributeList *MethodAttrs = 0; 780 if (getLang().ObjC2 && Tok.is(tok::kw___attribute)) 781 MethodAttrs = ParseAttributes(); 782 783 Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), 784 &KeyIdents[0]); 785 return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), 786 mType, IDecl, DSRet, ReturnType, Sel, 787 &ArgTypeQuals[0], &KeyTypes[0], 788 &ArgNames[0], CargNames, 789 MethodAttrs, 790 MethodImplKind, isVariadic); 791 } 792 793 /// objc-protocol-refs: 794 /// '<' identifier-list '>' 795 /// 796 bool Parser:: 797 ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclTy*> &Protocols, 798 bool WarnOnDeclarations, SourceLocation &EndLoc) { 799 assert(Tok.is(tok::less) && "expected <"); 800 801 ConsumeToken(); // the "<" 802 803 llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents; 804 805 while (1) { 806 if (Tok.isNot(tok::identifier)) { 807 Diag(Tok, diag::err_expected_ident); 808 SkipUntil(tok::greater); 809 return true; 810 } 811 ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(), 812 Tok.getLocation())); 813 ConsumeToken(); 814 815 if (Tok.isNot(tok::comma)) 816 break; 817 ConsumeToken(); 818 } 819 820 // Consume the '>'. 821 if (Tok.isNot(tok::greater)) { 822 Diag(Tok, diag::err_expected_greater); 823 return true; 824 } 825 826 EndLoc = ConsumeAnyToken(); 827 828 // Convert the list of protocols identifiers into a list of protocol decls. 829 Actions.FindProtocolDeclaration(WarnOnDeclarations, 830 &ProtocolIdents[0], ProtocolIdents.size(), 831 Protocols); 832 return false; 833 } 834 835 /// objc-class-instance-variables: 836 /// '{' objc-instance-variable-decl-list[opt] '}' 837 /// 838 /// objc-instance-variable-decl-list: 839 /// objc-visibility-spec 840 /// objc-instance-variable-decl ';' 841 /// ';' 842 /// objc-instance-variable-decl-list objc-visibility-spec 843 /// objc-instance-variable-decl-list objc-instance-variable-decl ';' 844 /// objc-instance-variable-decl-list ';' 845 /// 846 /// objc-visibility-spec: 847 /// @private 848 /// @protected 849 /// @public 850 /// @package [OBJC2] 851 /// 852 /// objc-instance-variable-decl: 853 /// struct-declaration 854 /// 855 void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, 856 SourceLocation atLoc) { 857 assert(Tok.is(tok::l_brace) && "expected {"); 858 llvm::SmallVector<DeclTy*, 32> AllIvarDecls; 859 llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; 860 861 ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); 862 863 SourceLocation LBraceLoc = ConsumeBrace(); // the "{" 864 865 tok::ObjCKeywordKind visibility = tok::objc_protected; 866 // While we still have something to read, read the instance variables. 867 while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { 868 // Each iteration of this loop reads one objc-instance-variable-decl. 869 870 // Check for extraneous top-level semicolon. 871 if (Tok.is(tok::semi)) { 872 Diag(Tok, diag::ext_extra_struct_semi); 873 ConsumeToken(); 874 continue; 875 } 876 877 // Set the default visibility to private. 878 if (Tok.is(tok::at)) { // parse objc-visibility-spec 879 ConsumeToken(); // eat the @ sign 880 switch (Tok.getObjCKeywordID()) { 881 case tok::objc_private: 882 case tok::objc_public: 883 case tok::objc_protected: 884 case tok::objc_package: 885 visibility = Tok.getObjCKeywordID(); 886 ConsumeToken(); 887 continue; 888 default: 889 Diag(Tok, diag::err_objc_illegal_visibility_spec); 890 continue; 891 } 892 } 893 894 // Parse all the comma separated declarators. 895 DeclSpec DS; 896 FieldDeclarators.clear(); 897 ParseStructDeclaration(DS, FieldDeclarators); 898 899 // Convert them all to fields. 900 for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { 901 FieldDeclarator &FD = FieldDeclarators[i]; 902 // Install the declarator into interfaceDecl. 903 DeclTy *Field = Actions.ActOnIvar(CurScope, 904 DS.getSourceRange().getBegin(), 905 FD.D, FD.BitfieldSize, visibility); 906 AllIvarDecls.push_back(Field); 907 } 908 909 if (Tok.is(tok::semi)) { 910 ConsumeToken(); 911 } else { 912 Diag(Tok, diag::err_expected_semi_decl_list); 913 // Skip to end of block or statement 914 SkipUntil(tok::r_brace, true, true); 915 } 916 } 917 SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); 918 // Call ActOnFields() even if we don't have any decls. This is useful 919 // for code rewriting tools that need to be aware of the empty list. 920 Actions.ActOnFields(CurScope, atLoc, interfaceDecl, 921 &AllIvarDecls[0], AllIvarDecls.size(), 922 LBraceLoc, RBraceLoc, 0); 923 return; 924 } 925 926 /// objc-protocol-declaration: 927 /// objc-protocol-definition 928 /// objc-protocol-forward-reference 929 /// 930 /// objc-protocol-definition: 931 /// @protocol identifier 932 /// objc-protocol-refs[opt] 933 /// objc-interface-decl-list 934 /// @end 935 /// 936 /// objc-protocol-forward-reference: 937 /// @protocol identifier-list ';' 938 /// 939 /// "@protocol identifier ;" should be resolved as "@protocol 940 /// identifier-list ;": objc-interface-decl-list may not start with a 941 /// semicolon in the first alternative if objc-protocol-refs are omitted. 942 Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, 943 AttributeList *attrList) { 944 assert(Tok.isObjCAtKeyword(tok::objc_protocol) && 945 "ParseObjCAtProtocolDeclaration(): Expected @protocol"); 946 ConsumeToken(); // the "protocol" identifier 947 948 if (Tok.isNot(tok::identifier)) { 949 Diag(Tok, diag::err_expected_ident); // missing protocol name. 950 return 0; 951 } 952 // Save the protocol name, then consume it. 953 IdentifierInfo *protocolName = Tok.getIdentifierInfo(); 954 SourceLocation nameLoc = ConsumeToken(); 955 956 if (Tok.is(tok::semi)) { // forward declaration of one protocol. 957 IdentifierLocPair ProtoInfo(protocolName, nameLoc); 958 ConsumeToken(); 959 return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, 960 attrList); 961 } 962 963 if (Tok.is(tok::comma)) { // list of forward declarations. 964 llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs; 965 ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); 966 967 // Parse the list of forward declarations. 968 while (1) { 969 ConsumeToken(); // the ',' 970 if (Tok.isNot(tok::identifier)) { 971 Diag(Tok, diag::err_expected_ident); 972 SkipUntil(tok::semi); 973 return 0; 974 } 975 ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(), 976 Tok.getLocation())); 977 ConsumeToken(); // the identifier 978 979 if (Tok.isNot(tok::comma)) 980 break; 981 } 982 // Consume the ';'. 983 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol")) 984 return 0; 985 986 return Actions.ActOnForwardProtocolDeclaration(AtLoc, 987 &ProtocolRefs[0], 988 ProtocolRefs.size(), 989 attrList); 990 } 991 992 // Last, and definitely not least, parse a protocol declaration. 993 SourceLocation EndProtoLoc; 994 995 llvm::SmallVector<DeclTy *, 8> ProtocolRefs; 996 if (Tok.is(tok::less) && 997 ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc)) 998 return 0; 999 1000 DeclTy *ProtoType = 1001 Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, 1002 &ProtocolRefs[0], ProtocolRefs.size(), 1003 EndProtoLoc, attrList); 1004 ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); 1005 return ProtoType; 1006 } 1007 1008 /// objc-implementation: 1009 /// objc-class-implementation-prologue 1010 /// objc-category-implementation-prologue 1011 /// 1012 /// objc-class-implementation-prologue: 1013 /// @implementation identifier objc-superclass[opt] 1014 /// objc-class-instance-variables[opt] 1015 /// 1016 /// objc-category-implementation-prologue: 1017 /// @implementation identifier ( identifier ) 1018 1019 Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration( 1020 SourceLocation atLoc) { 1021 assert(Tok.isObjCAtKeyword(tok::objc_implementation) && 1022 "ParseObjCAtImplementationDeclaration(): Expected @implementation"); 1023 ConsumeToken(); // the "implementation" identifier 1024 1025 if (Tok.isNot(tok::identifier)) { 1026 Diag(Tok, diag::err_expected_ident); // missing class or category name. 1027 return 0; 1028 } 1029 // We have a class or category name - consume it. 1030 IdentifierInfo *nameId = Tok.getIdentifierInfo(); 1031 SourceLocation nameLoc = ConsumeToken(); // consume class or category name 1032 1033 if (Tok.is(tok::l_paren)) { 1034 // we have a category implementation. 1035 SourceLocation lparenLoc = ConsumeParen(); 1036 SourceLocation categoryLoc, rparenLoc; 1037 IdentifierInfo *categoryId = 0; 1038 1039 if (Tok.is(tok::identifier)) { 1040 categoryId = Tok.getIdentifierInfo(); 1041 categoryLoc = ConsumeToken(); 1042 } else { 1043 Diag(Tok, diag::err_expected_ident); // missing category name. 1044 return 0; 1045 } 1046 if (Tok.isNot(tok::r_paren)) { 1047 Diag(Tok, diag::err_expected_rparen); 1048 SkipUntil(tok::r_paren, false); // don't stop at ';' 1049 return 0; 1050 } 1051 rparenLoc = ConsumeParen(); 1052 DeclTy *ImplCatType = Actions.ActOnStartCategoryImplementation( 1053 atLoc, nameId, nameLoc, categoryId, 1054 categoryLoc); 1055 ObjCImpDecl = ImplCatType; 1056 return 0; 1057 } 1058 // We have a class implementation 1059 SourceLocation superClassLoc; 1060 IdentifierInfo *superClassId = 0; 1061 if (Tok.is(tok::colon)) { 1062 // We have a super class 1063 ConsumeToken(); 1064 if (Tok.isNot(tok::identifier)) { 1065 Diag(Tok, diag::err_expected_ident); // missing super class name. 1066 return 0; 1067 } 1068 superClassId = Tok.getIdentifierInfo(); 1069 superClassLoc = ConsumeToken(); // Consume super class name 1070 } 1071 DeclTy *ImplClsType = Actions.ActOnStartClassImplementation( 1072 atLoc, nameId, nameLoc, 1073 superClassId, superClassLoc); 1074 1075 if (Tok.is(tok::l_brace)) // we have ivars 1076 ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc); 1077 ObjCImpDecl = ImplClsType; 1078 1079 return 0; 1080 } 1081 1082 Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) { 1083 assert(Tok.isObjCAtKeyword(tok::objc_end) && 1084 "ParseObjCAtEndDeclaration(): Expected @end"); 1085 ConsumeToken(); // the "end" identifier 1086 if (ObjCImpDecl) 1087 Actions.ActOnAtEnd(atLoc, ObjCImpDecl); 1088 else 1089 Diag(atLoc, diag::warn_expected_implementation); // missing @implementation 1090 return ObjCImpDecl; 1091 } 1092 1093 /// compatibility-alias-decl: 1094 /// @compatibility_alias alias-name class-name ';' 1095 /// 1096 Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { 1097 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && 1098 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); 1099 ConsumeToken(); // consume compatibility_alias 1100 if (Tok.isNot(tok::identifier)) { 1101 Diag(Tok, diag::err_expected_ident); 1102 return 0; 1103 } 1104 IdentifierInfo *aliasId = Tok.getIdentifierInfo(); 1105 SourceLocation aliasLoc = ConsumeToken(); // consume alias-name 1106 if (Tok.isNot(tok::identifier)) { 1107 Diag(Tok, diag::err_expected_ident); 1108 return 0; 1109 } 1110 IdentifierInfo *classId = Tok.getIdentifierInfo(); 1111 SourceLocation classLoc = ConsumeToken(); // consume class-name; 1112 if (Tok.isNot(tok::semi)) { 1113 Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias"; 1114 return 0; 1115 } 1116 DeclTy *ClsType = Actions.ActOnCompatiblityAlias(atLoc, 1117 aliasId, aliasLoc, 1118 classId, classLoc); 1119 return ClsType; 1120 } 1121 1122 /// property-synthesis: 1123 /// @synthesize property-ivar-list ';' 1124 /// 1125 /// property-ivar-list: 1126 /// property-ivar 1127 /// property-ivar-list ',' property-ivar 1128 /// 1129 /// property-ivar: 1130 /// identifier 1131 /// identifier '=' identifier 1132 /// 1133 Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { 1134 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && 1135 "ParseObjCPropertyDynamic(): Expected '@synthesize'"); 1136 SourceLocation loc = ConsumeToken(); // consume synthesize 1137 if (Tok.isNot(tok::identifier)) { 1138 Diag(Tok, diag::err_expected_ident); 1139 return 0; 1140 } 1141 while (Tok.is(tok::identifier)) { 1142 IdentifierInfo *propertyIvar = 0; 1143 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1144 SourceLocation propertyLoc = ConsumeToken(); // consume property name 1145 if (Tok.is(tok::equal)) { 1146 // property '=' ivar-name 1147 ConsumeToken(); // consume '=' 1148 if (Tok.isNot(tok::identifier)) { 1149 Diag(Tok, diag::err_expected_ident); 1150 break; 1151 } 1152 propertyIvar = Tok.getIdentifierInfo(); 1153 ConsumeToken(); // consume ivar-name 1154 } 1155 Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl, 1156 propertyId, propertyIvar); 1157 if (Tok.isNot(tok::comma)) 1158 break; 1159 ConsumeToken(); // consume ',' 1160 } 1161 if (Tok.isNot(tok::semi)) 1162 Diag(Tok, diag::err_expected_semi_after) << "@synthesize"; 1163 return 0; 1164 } 1165 1166 /// property-dynamic: 1167 /// @dynamic property-list 1168 /// 1169 /// property-list: 1170 /// identifier 1171 /// property-list ',' identifier 1172 /// 1173 Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { 1174 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && 1175 "ParseObjCPropertyDynamic(): Expected '@dynamic'"); 1176 SourceLocation loc = ConsumeToken(); // consume dynamic 1177 if (Tok.isNot(tok::identifier)) { 1178 Diag(Tok, diag::err_expected_ident); 1179 return 0; 1180 } 1181 while (Tok.is(tok::identifier)) { 1182 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); 1183 SourceLocation propertyLoc = ConsumeToken(); // consume property name 1184 Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl, 1185 propertyId, 0); 1186 1187 if (Tok.isNot(tok::comma)) 1188 break; 1189 ConsumeToken(); // consume ',' 1190 } 1191 if (Tok.isNot(tok::semi)) 1192 Diag(Tok, diag::err_expected_semi_after) << "@dynamic"; 1193 return 0; 1194 } 1195 1196 /// objc-throw-statement: 1197 /// throw expression[opt]; 1198 /// 1199 Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { 1200 OwningExprResult Res(Actions); 1201 ConsumeToken(); // consume throw 1202 if (Tok.isNot(tok::semi)) { 1203 Res = ParseExpression(); 1204 if (Res.isInvalid()) { 1205 SkipUntil(tok::semi); 1206 return StmtError(); 1207 } 1208 } 1209 ConsumeToken(); // consume ';' 1210 return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope); 1211 } 1212 1213 /// objc-synchronized-statement: 1214 /// @synchronized '(' expression ')' compound-statement 1215 /// 1216 Parser::OwningStmtResult 1217 Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { 1218 ConsumeToken(); // consume synchronized 1219 if (Tok.isNot(tok::l_paren)) { 1220 Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; 1221 return StmtError(); 1222 } 1223 ConsumeParen(); // '(' 1224 OwningExprResult Res(ParseExpression()); 1225 if (Res.isInvalid()) { 1226 SkipUntil(tok::semi); 1227 return StmtError(); 1228 } 1229 if (Tok.isNot(tok::r_paren)) { 1230 Diag(Tok, diag::err_expected_lbrace); 1231 return StmtError(); 1232 } 1233 ConsumeParen(); // ')' 1234 if (Tok.isNot(tok::l_brace)) { 1235 Diag(Tok, diag::err_expected_lbrace); 1236 return StmtError(); 1237 } 1238 // Enter a scope to hold everything within the compound stmt. Compound 1239 // statements can always hold declarations. 1240 ParseScope BodyScope(this, Scope::DeclScope); 1241 1242 OwningStmtResult SynchBody(ParseCompoundStatementBody()); 1243 1244 BodyScope.Exit(); 1245 if (SynchBody.isInvalid()) 1246 SynchBody = Actions.ActOnNullStmt(Tok.getLocation()); 1247 return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody)); 1248 } 1249 1250 /// objc-try-catch-statement: 1251 /// @try compound-statement objc-catch-list[opt] 1252 /// @try compound-statement objc-catch-list[opt] @finally compound-statement 1253 /// 1254 /// objc-catch-list: 1255 /// @catch ( parameter-declaration ) compound-statement 1256 /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement 1257 /// catch-parameter-declaration: 1258 /// parameter-declaration 1259 /// '...' [OBJC2] 1260 /// 1261 Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { 1262 bool catch_or_finally_seen = false; 1263 1264 ConsumeToken(); // consume try 1265 if (Tok.isNot(tok::l_brace)) { 1266 Diag(Tok, diag::err_expected_lbrace); 1267 return StmtError(); 1268 } 1269 OwningStmtResult CatchStmts(Actions); 1270 OwningStmtResult FinallyStmt(Actions); 1271 ParseScope TryScope(this, Scope::DeclScope); 1272 OwningStmtResult TryBody(ParseCompoundStatementBody()); 1273 TryScope.Exit(); 1274 if (TryBody.isInvalid()) 1275 TryBody = Actions.ActOnNullStmt(Tok.getLocation()); 1276 1277 while (Tok.is(tok::at)) { 1278 // At this point, we need to lookahead to determine if this @ is the start 1279 // of an @catch or @finally. We don't want to consume the @ token if this 1280 // is an @try or @encode or something else. 1281 Token AfterAt = GetLookAheadToken(1); 1282 if (!AfterAt.isObjCAtKeyword(tok::objc_catch) && 1283 !AfterAt.isObjCAtKeyword(tok::objc_finally)) 1284 break; 1285 1286 SourceLocation AtCatchFinallyLoc = ConsumeToken(); 1287 if (Tok.isObjCAtKeyword(tok::objc_catch)) { 1288 OwningStmtResult FirstPart(Actions); 1289 ConsumeToken(); // consume catch 1290 if (Tok.is(tok::l_paren)) { 1291 ConsumeParen(); 1292 ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope); 1293 if (Tok.isNot(tok::ellipsis)) { 1294 DeclSpec DS; 1295 ParseDeclarationSpecifiers(DS); 1296 // For some odd reason, the name of the exception variable is 1297 // optional. As a result, we need to use PrototypeContext. 1298 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext); 1299 ParseDeclarator(DeclaratorInfo); 1300 if (DeclaratorInfo.getIdentifier()) { 1301 DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope, 1302 DeclaratorInfo, 0); 1303 FirstPart = 1304 Actions.ActOnDeclStmt(aBlockVarDecl, 1305 DS.getSourceRange().getBegin(), 1306 DeclaratorInfo.getSourceRange().getEnd()); 1307 } 1308 } else 1309 ConsumeToken(); // consume '...' 1310 SourceLocation RParenLoc = ConsumeParen(); 1311 1312 OwningStmtResult CatchBody(Actions, true); 1313 if (Tok.is(tok::l_brace)) 1314 CatchBody = ParseCompoundStatementBody(); 1315 else 1316 Diag(Tok, diag::err_expected_lbrace); 1317 if (CatchBody.isInvalid()) 1318 CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); 1319 CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, 1320 RParenLoc, move(FirstPart), move(CatchBody), 1321 move(CatchStmts)); 1322 } else { 1323 Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) 1324 << "@catch clause"; 1325 return StmtError(); 1326 } 1327 catch_or_finally_seen = true; 1328 } else { 1329 assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); 1330 ConsumeToken(); // consume finally 1331 ParseScope FinallyScope(this, Scope::DeclScope); 1332 1333 OwningStmtResult FinallyBody(Actions, true); 1334 if (Tok.is(tok::l_brace)) 1335 FinallyBody = ParseCompoundStatementBody(); 1336 else 1337 Diag(Tok, diag::err_expected_lbrace); 1338 if (FinallyBody.isInvalid()) 1339 FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); 1340 FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, 1341 move(FinallyBody)); 1342 catch_or_finally_seen = true; 1343 break; 1344 } 1345 } 1346 if (!catch_or_finally_seen) { 1347 Diag(atLoc, diag::err_missing_catch_finally); 1348 return StmtError(); 1349 } 1350 return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody), move(CatchStmts), 1351 move(FinallyStmt)); 1352 } 1353 1354 /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' 1355 /// 1356 Parser::DeclTy *Parser::ParseObjCMethodDefinition() { 1357 DeclTy *MDecl = ParseObjCMethodPrototype(ObjCImpDecl); 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 1398 Parser::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 1418 Parser::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 1447 Parser::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 /// 1490 Parser::OwningExprResult 1491 Parser::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 1591 Parser::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 ) 1623 Parser::OwningExprResult 1624 Parser::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 ) 1647 Parser::OwningExprResult 1648 Parser::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 ')' 1670 Parser::OwningExprResult 1671 Parser::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