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