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