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