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