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