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