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