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