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