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