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