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