ParseObjc.cpp revision 76ad2e85575722e8a38a2bd4648ab4304d9fcd24
1a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This file implements the Objective-C portions of the Parser interface.
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1419510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Parse/Parser.h"
150fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor#include "clang/Parse/DeclSpec.h"
163f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Parse/Scope.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "AstGuard.h"
1819510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Parse/ParseDiagnostic.h"
19f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall#include "llvm/ADT/SmallVector.h"
2019510856727e0e14a3696b2a72c35163bff2a71fJohn McCallusing namespace clang;
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2208602359845e668194d111b794b8965358babfe6Fariborz Jahanian
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseObjCAtDirectives - Handle parts of the external-declaration production:
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       external-declaration: [C99 6.9]
259f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber/// [OBJC]  objc-class-definition
26e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber/// [OBJC]  objc-class-declaration
279f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber/// [OBJC]  objc-alias-declaration
289f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber/// [OBJC]  objc-protocol-definition
29e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber/// [OBJC]  objc-method-definition
30e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber/// [OBJC]  '@' 'end'
31e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico WeberParser::DeclTy *Parser::ParseObjCAtDirectives() {
32e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber  SourceLocation AtLoc = ConsumeToken(); // the "@"
33e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber
349f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber  switch (Tok.getObjCKeywordID()) {
359f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber  case tok::objc_class:
369f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber    return ParseObjCAtClassDeclaration(AtLoc);
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::objc_interface:
38891dca671a80c865c6def7259f170ba785e4faaaChris Lattner    return ParseObjCAtInterfaceDeclaration(AtLoc);
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::objc_protocol:
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseObjCAtProtocolDeclaration(AtLoc);
4191fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff  case tok::objc_implementation:
4291fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff    return ParseObjCAtImplementationDeclaration(AtLoc);
4391fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff  case tok::objc_end:
4491fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff    return ParseObjCAtEndDeclaration(AtLoc);
4591fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff  case tok::objc_compatibility_alias:
4695ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian    return ParseObjCAtAliasDeclaration(AtLoc);
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::objc_synthesize:
481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return ParseObjCPropertySynthesize(AtLoc);
49c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor  case tok::objc_dynamic:
50a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    return ParseObjCPropertyDynamic(AtLoc);
517d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  default:
527d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    Diag(AtLoc, diag::err_unexpected_at);
53c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor    SkipUntil(tok::semi);
5495ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian    return 0;
5595ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian  }
56861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff}
575ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
585ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner///
597f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall/// objc-class-declaration:
600b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall///    '@' 'class' identifier-list ';'
6195ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///
6295ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz JahanianParser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
637f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall  ConsumeToken(); // the identifier "class"
647f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall  llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
650b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
66bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor  while (1) {
677f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall    if (Tok.isNot(tok::identifier)) {
685ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner      Diag(Tok, diag::err_expected_ident);
69849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      SkipUntil(tok::semi);
705ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner      return 0;
71140ab234c23f392d5422691c5de1ee3c15026defFariborz Jahanian    }
725ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner    ClassNames.push_back(Tok.getIdentifierInfo());
7395ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian    ConsumeToken();
7495ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian
755ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner    if (Tok.isNot(tok::comma))
7695ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian      break;
7795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian
785ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner    ConsumeToken();
7995ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian  }
8095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian
811b257afbae854c6817f26b7d61c4fed8ff7aebadDouglas Gregor  // Consume the ';'.
824e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
8394ad28b31433058445a27db722f60402ee820beaDouglas Gregor    return 0;
8494ad28b31433058445a27db722f60402ee820beaDouglas Gregor
8594ad28b31433058445a27db722f60402ee820beaDouglas Gregor  return Actions.ActOnForwardClassDeclaration(atLoc,
8694ad28b31433058445a27db722f60402ee820beaDouglas Gregor                                      &ClassNames[0], ClassNames.size());
875ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner}
885ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
895ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner///
9095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///   objc-interface:
9195ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///     objc-class-interface-attributes[opt] objc-class-interface
925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     objc-category-interface
9395ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///
945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///   objc-class-interface:
955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     '@' 'interface' identifier objc-superclass[opt]
965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       objc-protocol-refs[opt]
971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///       objc-class-instance-variables[opt]
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       objc-interface-decl-list
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     @end
10095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///
10195ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///   objc-category-interface:
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     '@' 'interface' identifier '(' identifier[opt] ')'
1035f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner///       objc-protocol-refs[opt]
1045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner///       objc-interface-decl-list
105c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek///     @end
1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///   objc-superclass:
108e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber///     ':' identifier
109df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner///
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///   objc-class-interface-attributes:
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     __attribute__((visibility("default")))
11295ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian///     __attribute__((visibility("hidden")))
1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     __attribute__((deprecated))
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///     __attribute__((unavailable))
115c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek///     __attribute__((objc_exception)) - used by NSException on 64-bit
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1171eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpParser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
118df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  SourceLocation atLoc, AttributeList *attrList) {
1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         "ParseObjCAtInterfaceDeclaration(): Expected @interface");
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken(); // the "interface" identifier
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (Tok.isNot(tok::identifier)) {
1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_expected_ident); // missing class or category name.
1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
12695ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian  }
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // We have a class or category name - consume it.
128c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek  IdentifierInfo *nameId = Tok.getIdentifierInfo();
129c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek  SourceLocation nameLoc = ConsumeToken();
130c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek
1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (Tok.is(tok::l_paren)) { // we have a category.
1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SourceLocation lparenLoc = ConsumeParen();
133d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    SourceLocation categoryLoc, rparenLoc;
134d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    IdentifierInfo *categoryId = 0;
135d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen
136d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    // For ObjC2, the category name is optional (not an error).
137d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    if (Tok.is(tok::identifier)) {
138d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      categoryId = Tok.getIdentifierInfo();
139849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      categoryLoc = ConsumeToken();
140849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    } else if (!getLang().ObjC2) {
141849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      Diag(Tok, diag::err_expected_ident); // missing category name.
142849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      return 0;
143849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    }
144849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    if (Tok.isNot(tok::r_paren)) {
145d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      Diag(Tok, diag::err_expected_rparen);
146d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      SkipUntil(tok::r_paren, false); // don't stop at ';'
147d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      return 0;
148d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    }
149d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    rparenLoc = ConsumeParen();
150d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen
151d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    // Next, we need to check for any protocol references.
152dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    SourceLocation EndProtoLoc;
153dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    llvm::SmallVector<DeclTy *, 8> ProtocolRefs;
154dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (Tok.is(tok::less) &&
155dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
156dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      return 0;
157dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (attrList) // categories don't support attributes.
159dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      Diag(Tok, diag::err_objc_no_attributes_on_category);
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
161dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    DeclTy *CategoryType = Actions.ActOnStartCategoryInterface(atLoc,
162dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                     nameId, nameLoc, categoryId, categoryLoc,
163dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                     &ProtocolRefs[0], ProtocolRefs.size(),
164dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                     EndProtoLoc);
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
166dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
167dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    return CategoryType;
168dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
169dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Parse a class interface.
170dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  IdentifierInfo *superClassId = 0;
171dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  SourceLocation superClassLoc;
172dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
173dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (Tok.is(tok::colon)) { // a super class is specified.
174dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    ConsumeToken();
175dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (Tok.isNot(tok::identifier)) {
176dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      Diag(Tok, diag::err_expected_ident); // missing super class name.
177dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      return 0;
178dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    }
179b2f6820773aabff3c5c9e0dbb1cbbbda0d80c41fPatrick Beard    superClassId = Tok.getIdentifierInfo();
180dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    superClassLoc = ConsumeToken();
181d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  }
1827f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall  // Next, we need to check for any protocol references.
183861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff  llvm::SmallVector<Action::DeclTy*, 8> ProtocolRefs;
184dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  SourceLocation EndProtoLoc;
185d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  if (Tok.is(tok::less) &&
186dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return 0;
1883b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
1893b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  DeclTy *ClsType =
19023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
1917d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis                                     superClassId, superClassLoc,
1927d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis                                     &ProtocolRefs[0], ProtocolRefs.size(),
1933b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor                                     EndProtoLoc, attrList);
1943b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
195e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber  if (Tok.is(tok::l_brace))
1969f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber    ParseObjCClassInstanceVariables(ClsType, atLoc);
197df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
198dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
199d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  return ClsType;
200dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
20163e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian
202dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff/// constructSetterName - Return the setter name for the given
2037ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff/// identifier, i.e. "set" + Name where the initial character of Name
204dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff/// has been capitalized.
2055512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanianstatic IdentifierInfo *constructSetterName(IdentifierTable &Idents,
2065512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian                                           const IdentifierInfo *Name) {
2074a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  llvm::SmallString<100> SelectorName;
2084a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  SelectorName = "set";
2094a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
2104a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  SelectorName[3] = toupper(SelectorName[3]);
2114a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
212dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
21333ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor
21423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor///   objc-interface-decl-list:
2157d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///     empty
2167d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///     objc-interface-decl-list objc-property-decl [OBJC2]
21733ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor///     objc-interface-decl-list objc-method-requirement [OBJC2]
21833ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor///     objc-interface-decl-list objc-method-proto ';'
219527fe23f8cbc6a4da1737a547a2517bc92fa88c8Steve Naroff///     objc-interface-decl-list declaration
220df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner///     objc-interface-decl-list ';'
221dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///
222dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///   objc-method-requirement: [OBJC2]
22305511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian///     @required
2244e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie///     @optional
225527fe23f8cbc6a4da1737a547a2517bc92fa88c8Steve Naroff///
226d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallvoid Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
227dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                        tok::ObjCKeywordKind contextKey) {
2284a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  llvm::SmallVector<DeclTy*, 32> allMethods;
2294a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  llvm::SmallVector<DeclTy*, 16> allProperties;
2304a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
231d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
23213d05ac08974ccb41f7da7595d769c158f58fbd6Douglas Gregor  SourceLocation AtEndLoc;
23313d05ac08974ccb41f7da7595d769c158f58fbd6Douglas Gregor
23413d05ac08974ccb41f7da7595d769c158f58fbd6Douglas Gregor  while (1) {
23513d05ac08974ccb41f7da7595d769c158f58fbd6Douglas Gregor    // If this is a method prototype, parse it.
236dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
23713d05ac08974ccb41f7da7595d769c158f58fbd6Douglas Gregor      DeclTy *methodPrototype =
2385512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian        ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
2395512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      allMethods.push_back(methodPrototype);
2405f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
2415f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      // method definitions.
2425512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      ExpectAndConsume(tok::semi, diag::err_expected_semi_after,"method proto");
2435512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      continue;
24471b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis    }
245d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
24605511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian    // Ignore excess semicolons.
247d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    if (Tok.is(tok::semi)) {
248d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      ConsumeToken();
2495512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      continue;
2505512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian    }
251beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad
252beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad    // If we got to the end of the file, exit the loop.
25318df52bbb5d28ca082064d31ae7558dbdae52377Douglas Gregor    if (Tok.is(tok::eof))
2545512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      break;
255e6f07f538fd0eddd6c087fcc01d4e4ff19129c71Fariborz Jahanian
256a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    // If we don't have an @ directive, parse it as a function definition.
257d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    if (Tok.isNot(tok::at)) {
258a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian      // The code below does not consume '}'s because it is afraid of eating the
2592f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian      // end of a namespace.  Because of the way this code is structured, an
2605512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian      // erroneous r_brace would cause an infinite loop if not handled here.
261dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      if (Tok.is(tok::r_brace))
262dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        break;
263dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
264dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      // FIXME: as the name implies, this rule allows function definitions.
2657ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // We could pass a flag or check for functions during semantic analysis.
266df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      ParseDeclarationOrFunctionDefinition();
267dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      continue;
2683b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor    }
2693b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
2703b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor    // Otherwise, we have an @ directive, eat the @.
27123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    SourceLocation AtLoc = ConsumeToken(); // the "@"
2727d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
2737d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis
2743b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor    if (DirectiveKind == tok::objc_end) { // @end -> terminate list
2753b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor      AtEndLoc = AtLoc;
276df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      break;
277dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    }
278d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
279dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // Eat the identifier.
280dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    ConsumeToken();
281dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
282dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    switch (DirectiveKind) {
283dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    default:
2845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      // FIXME: If someone forgets an @end on a protocol, this loop will
2855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      // continue to eat up tons of stuff and spew lots of nonsense errors.  It
28671b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis      // would probably be better to bail out if we saw an @class or @interface
28706036d3709955a53297b4cbe14e20db88f321470Chris Lattner      // or something like that.
28871b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis      Diag(AtLoc, diag::err_objc_illegal_interface_qual);
28971b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis      // Skip until we see an '@' or '}' or ';'.
290d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      SkipUntil(tok::r_brace, tok::at);
2911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      break;
292d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
293d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    case tok::objc_required:
29406036d3709955a53297b4cbe14e20db88f321470Chris Lattner    case tok::objc_optional:
295beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad      // This is only valid on protocols.
29618df52bbb5d28ca082064d31ae7558dbdae52377Douglas Gregor      // FIXME: Should this check for ObjC2 being enabled?
2977f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall      if (contextKey != tok::objc_protocol)
2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
299df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      else
300d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen        MethodImplKind = DirectiveKind;
301dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      break;
3022f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian
3035512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian    case tok::objc_property:
304dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      if (!getLang().ObjC2)
305dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        Diag(AtLoc, diag::err_objc_propertoes_require_objc2);
306d0014540005f2a5ab837365db6bd40f479406758John McCall
307d0014540005f2a5ab837365db6bd40f479406758John McCall      ObjCDeclSpec OCDS;
308d0014540005f2a5ab837365db6bd40f479406758John McCall      // Parse property attribute list, if any.
30999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie      if (Tok.is(tok::l_paren))
31099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie        ParseObjCPropertyAttribute(OCDS);
31199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie
312d0014540005f2a5ab837365db6bd40f479406758John McCall      // Parse all the comma separated declarators.
3135f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      DeclSpec DS;
314d0014540005f2a5ab837365db6bd40f479406758John McCall      llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
315d0014540005f2a5ab837365db6bd40f479406758John McCall      ParseStructDeclaration(DS, FieldDeclarators);
31677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian
317d0014540005f2a5ab837365db6bd40f479406758John McCall      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
318d0014540005f2a5ab837365db6bd40f479406758John McCall                       tok::at);
319a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian
3205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      // Convert them all to property declarations.
321d0014540005f2a5ab837365db6bd40f479406758John McCall      for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
32277bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian        FieldDeclarator &FD = FieldDeclarators[i];
323d0014540005f2a5ab837365db6bd40f479406758John McCall        if (FD.D.getIdentifier() == 0) {
32477bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian          Diag(AtLoc, diag::err_objc_property_requires_field_name)
325d0014540005f2a5ab837365db6bd40f479406758John McCall            << FD.D.getSourceRange();
326d0014540005f2a5ab837365db6bd40f479406758John McCall          continue;
327d0014540005f2a5ab837365db6bd40f479406758John McCall        }
328dcdff46dd8e6d749283fe6c43adfcfe780c1d562Eli Friedman        if (FD.BitfieldSize) {
329d0014540005f2a5ab837365db6bd40f479406758John McCall          Diag(AtLoc, diag::err_objc_property_bitfield)
330d0014540005f2a5ab837365db6bd40f479406758John McCall            << FD.D.getSourceRange();
331d0014540005f2a5ab837365db6bd40f479406758John McCall          continue;
332dcdff46dd8e6d749283fe6c43adfcfe780c1d562Eli Friedman        }
333d0014540005f2a5ab837365db6bd40f479406758John McCall
334d0014540005f2a5ab837365db6bd40f479406758John McCall        // Install the property declarator into interfaceDecl.
335d0014540005f2a5ab837365db6bd40f479406758John McCall        IdentifierInfo *SelName =
336d0014540005f2a5ab837365db6bd40f479406758John McCall          OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
337dcdff46dd8e6d749283fe6c43adfcfe780c1d562Eli Friedman
338d0014540005f2a5ab837365db6bd40f479406758John McCall        Selector GetterSel =
339d0014540005f2a5ab837365db6bd40f479406758John McCall          PP.getSelectorTable().getNullarySelector(SelName);
340d0014540005f2a5ab837365db6bd40f479406758John McCall        IdentifierInfo *SetterName = OCDS.getSetterName();
341d0014540005f2a5ab837365db6bd40f479406758John McCall        if (!SetterName)
342d0014540005f2a5ab837365db6bd40f479406758John McCall          SetterName = constructSetterName(PP.getIdentifierTable(),
343d0014540005f2a5ab837365db6bd40f479406758John McCall                                           FD.D.getIdentifier());
344d0014540005f2a5ab837365db6bd40f479406758John McCall        Selector SetterSel =
345d0014540005f2a5ab837365db6bd40f479406758John McCall          PP.getSelectorTable().getUnarySelector(SetterName);
346d0014540005f2a5ab837365db6bd40f479406758John McCall        bool isOverridingProperty = false;
347d0014540005f2a5ab837365db6bd40f479406758John McCall        DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
348d0014540005f2a5ab837365db6bd40f479406758John McCall                                                 GetterSel, SetterSel,
349d0014540005f2a5ab837365db6bd40f479406758John McCall                                                 interfaceDecl,
350d0014540005f2a5ab837365db6bd40f479406758John McCall                                                 &isOverridingProperty,
35180e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl                                                 MethodImplKind);
35280e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl        if (!isOverridingProperty)
35380e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl          allProperties.push_back(Property);
35480e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl      }
355d0014540005f2a5ab837365db6bd40f479406758John McCall      break;
356d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    }
35777bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  }
35877bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian
359a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  // We break out of the big loop in two cases: when we see @end or when we see
360d0014540005f2a5ab837365db6bd40f479406758John McCall  // EOF.  In the former case, eat the @end.  In the later case, emit an error.
361d0014540005f2a5ab837365db6bd40f479406758John McCall  if (Tok.isObjCAtKeyword(tok::objc_end))
362d0014540005f2a5ab837365db6bd40f479406758John McCall    ConsumeToken(); // the "end" identifier
363d0014540005f2a5ab837365db6bd40f479406758John McCall  else
364d0014540005f2a5ab837365db6bd40f479406758John McCall    Diag(Tok, diag::err_objc_missing_end);
365f66a0dda541cd859a928193efba6dc5d7ba8fe54Eli Friedman
366d0014540005f2a5ab837365db6bd40f479406758John McCall  // Insert collected methods declarations into the @interface object.
367d0014540005f2a5ab837365db6bd40f479406758John McCall  // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
368d0014540005f2a5ab837365db6bd40f479406758John McCall  Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
36999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie                     allMethods.empty() ? 0 : &allMethods[0],
37099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie                     allMethods.size(),
37199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie                     allProperties.empty() ? 0 : &allProperties[0],
372dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                     allProperties.size());
373dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
374dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
375294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///   Parse property attribute declarations.
3763536b443bc50d58a79f14fca9b6842541a434854Steve Naroff///
377dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///   property-attr-decl: '(' property-attrlist ')'
378dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///   property-attrlist:
379dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///     property-attribute
380294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     property-attrlist ',' property-attribute
381294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///   property-attribute:
382294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     getter '=' identifier
383294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     setter '=' identifier ':'
3842f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian///     readonly
3852f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian///     readwrite
3865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner///     assign
3875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner///     retain
3885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner///     copy
38900933591a2795d09dd1acff12a2d21bce7cb12c5Fariborz Jahanian///     nonatomic
3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
391782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenekvoid Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
3922f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian  assert(Tok.getKind() == tok::l_paren);
393294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  SourceLocation LHSLoc = ConsumeParen(); // consume '('
394e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
395df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  while (1) {
396d30ec7076fef736754206ac87a4f2c67251cc4d8Fariborz Jahanian    const IdentifierInfo *II = Tok.getIdentifierInfo();
397d30ec7076fef736754206ac87a4f2c67251cc4d8Fariborz Jahanian
398d30ec7076fef736754206ac87a4f2c67251cc4d8Fariborz Jahanian    // If this is not an identifier at all, bail out early.
3993536b443bc50d58a79f14fca9b6842541a434854Steve Naroff    if (II == 0) {
4003536b443bc50d58a79f14fca9b6842541a434854Steve Naroff      MatchRHSPunctuation(tok::r_paren, LHSLoc);
4010db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis      return;
4020db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis    }
4030db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis
4040db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis    SourceLocation AttrName = ConsumeToken(); // consume last attribute name
4050db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis
4060db9f4dad563a335641f5b9d4a42504d638b6c85Argyrios Kyrtzidis    if (II->isStr("readonly"))
407294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
408294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    else if (II->isStr("assign"))
40905511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
41005511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian    else if (II->isStr("readwrite"))
411d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
412d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    else if (II->isStr("retain"))
41390ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz Jahanian      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
41405511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian    else if (II->isStr("copy"))
41505511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
416e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner    else if (II->isStr("nonatomic"))
417e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
418294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    else if (II->isStr("getter") || II->isStr("setter")) {
419e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner      // getter/setter require extra treatment.
420e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner      if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "",
4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                           tok::r_paren))
422bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner        return;
423e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
424e3a2ca7e30601cdd31c77a830f4cc487851e8096Fariborz Jahanian      if (Tok.isNot(tok::identifier)) {
4251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        Diag(Tok, diag::err_expected_ident);
426b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor        SkipUntil(tok::r_paren);
427b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor        return;
42823c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor      }
429849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
430f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall      if (II->getName()[0] == 's') {
4317d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
432b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor        DS.setSetterName(Tok.getIdentifierInfo());
433b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor        ConsumeToken();  // consume method name
434e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
435e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner        if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "",
4361fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner                             tok::r_paren))
4371fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner          return;
4381fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner      } else {
4391fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
4401fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner        DS.setGetterName(Tok.getIdentifierInfo());
4412edf0a2520313cde900799b1eb9bd11c9c776afeSean Hunt        ConsumeToken();  // consume method name
4427f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall      }
443e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner    } else {
444e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner      Diag(AttrName, diag::err_objc_expected_property_attr) << II;
4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      SkipUntil(tok::r_paren);
446e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner      return;
447e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner    }
448c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
449a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    if (Tok.isNot(tok::comma))
4507d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis      break;
451c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
452c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor    ConsumeToken();
453a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  }
4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
455a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  MatchRHSPunctuation(tok::r_paren, LHSLoc);
456782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek}
457782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek
458e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner///   objc-method-proto:
459c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor///     objc-instance-method objc-method-decl objc-method-attributes[opt]
460c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor///     objc-class-method objc-method-decl objc-method-attributes[opt]
461c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor///
462c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor///   objc-instance-method: '-'
463bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner///   objc-class-method: '+'
4641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
465bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner///   objc-method-attributes:         [OBJC2]
466bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner///     __attribute__((deprecated))
467bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner///
468a2449b2bf739545494241e189b59587d5ca5c2c1Chris LattnerParser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
469a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner                          tok::ObjCKeywordKind MethodImplKind) {
470bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
471bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
472bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  tok::TokenKind methodType = Tok.getKind();
473bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  SourceLocation mLoc = ConsumeToken();
474f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner
475bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  DeclTy *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl, MethodImplKind);
476a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  // Since this rule is used for both method declarations and definitions,
477a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  // the caller is (optionally) responsible for consuming the ';'.
47846d545e355a4fea2a201652c3c8bbf22a13187a6Fariborz Jahanian  return MDecl;
47946d545e355a4fea2a201652c3c8bbf22a13187a6Fariborz Jahanian}
480df81c2c6ce37f4ae3c45dd01093b6274fa0b6692Fariborz Jahanian
481d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen///   objc-selector:
482d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen///     identifier
483d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen///     one of
484d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen///       enum struct union if else while do for switch case default
48546d545e355a4fea2a201652c3c8bbf22a13187a6Fariborz Jahanian///       break continue return goto asm sizeof typeof __alignof
48646d545e355a4fea2a201652c3c8bbf22a13187a6Fariborz Jahanian///       unsigned long const short volatile signed restrict _Complex
48746d545e355a4fea2a201652c3c8bbf22a13187a6Fariborz Jahanian///       in out inout bycopy byref oneway int char float double void _Bool
488a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner///
489a2449b2bf739545494241e189b59587d5ca5c2c1Chris LattnerIdentifierInfo *Parser::ParseObjCSelector(SourceLocation &SelectorLoc) {
490a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  switch (Tok.getKind()) {
491bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  default:
492e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner    return 0;
493bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::identifier:
494a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  case tok::kw_asm:
495bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_auto:
496a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  case tok::kw_bool:
4971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  case tok::kw_break:
498a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  case tok::kw_case:
4994e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  case tok::kw_catch:
500b321c0c0ba957d78475e72cebde4028fdaa00f8fChris Lattner  case tok::kw_char:
501f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  case tok::kw_class:
502e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  case tok::kw_const:
50377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  case tok::kw_const_cast:
5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  case tok::kw_continue:
50577bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  case tok::kw_default:
50677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  case tok::kw_delete:
507a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  case tok::kw_do:
50877bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  case tok::kw_double:
5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  case tok::kw_dynamic_cast:
510a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  case tok::kw_else:
51177bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian  case tok::kw_enum:
512bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  case tok::kw_explicit:
513e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  case tok::kw_export:
514f66a0dda541cd859a928193efba6dc5d7ba8fe54Eli Friedman  case tok::kw_extern:
515bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  case tok::kw_false:
5161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  case tok::kw_float:
5177da19ea50d4161fcda40d135735bcf450cabeb50John McCall  case tok::kw_for:
518a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  case tok::kw_friend:
519f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff  case tok::kw_goto:
520294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  case tok::kw_if:
521bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_inline:
522bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_int:
523bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_long:
524c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor  case tok::kw_mutable:
525a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  case tok::kw_namespace:
5267d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  case tok::kw_new:
527d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_operator:
528bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_private:
529d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_protected:
530d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_public:
531d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_register:
532d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_reinterpret_cast:
533d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_restrict:
534d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_return:
535d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_short:
536d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  case tok::kw_signed:
5371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  case tok::kw_sizeof:
538a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  case tok::kw_static:
539bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  case tok::kw_static_cast:
540a3c6246950f23d7d4cd748badaf8f05d7bc3f14aFariborz Jahanian  case tok::kw_struct:
541294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  case tok::kw_switch:
542294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  case tok::kw_template:
543d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_this:
544d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_throw:
545d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_true:
546d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_try:
547d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_typedef:
548d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_typeid:
549d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_typename:
550d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_typeof:
551d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_union:
552d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_unsigned:
553d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_using:
554d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_virtual:
555d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_void:
556d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_volatile:
557d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  case tok::kw_wchar_t:
558f85e193739c953358c865005855253af4f68a497John McCall  case tok::kw_while:
559f85e193739c953358c865005855253af4f68a497John McCall  case tok::kw__Bool:
560f85e193739c953358c865005855253af4f68a497John McCall  case tok::kw__Complex:
561f85e193739c953358c865005855253af4f68a497John McCall  case tok::kw___alignof:
562d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian    IdentifierInfo *II = Tok.getIdentifierInfo();
563a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    SelectorLoc = ConsumeToken();
5648ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    return II;
5654a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  }
5664a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor}
5671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
568cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner///  objc-for-collection-in: 'in'
569ece8e71d12b6f4cb2dc501297afef126dab8ad74Steve Naroff///
57023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregorbool Parser::isTokIdentifier_in() const {
5717d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  // FIXME: May have to do additional look-ahead to only allow for
572ece8e71d12b6f4cb2dc501297afef126dab8ad74Steve Naroff  // valid tokens following an 'in'; such as an identifier, unary operators,
573d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  // '[' etc.
5741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return (getLang().ObjC2 && Tok.is(tok::identifier) &&
575f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner          Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
576f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner}
5774a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor
578f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner/// ParseObjCTypeQualifierList - This routine parses the objective-c's type
579f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner/// qualifier list and builds their bitmask representation in the input
5801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// argument.
581156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner///
5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///   objc-type-qualifiers:
58392e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner///     objc-type-qualifier
584e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner///     objc-type-qualifiers objc-type-qualifier
58592e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner///
586e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattnervoid Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
587f85e193739c953358c865005855253af4f68a497John McCall  while (1) {
588f85e193739c953358c865005855253af4f68a497John McCall    if (Tok.isNot(tok::identifier))
58992e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner      return;
590e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner
59192e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner    const IdentifierInfo *II = Tok.getIdentifierInfo();
592e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner    for (unsigned i = 0; i != objc_NumQuals; ++i) {
593f85e193739c953358c865005855253af4f68a497John McCall      if (II != ObjCTypeQuals[i])
594f85e193739c953358c865005855253af4f68a497John McCall        continue;
59592e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner
596e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner      ObjCDeclSpec::ObjCDeclQualifier Qual;
59792e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner      switch (i) {
598e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner      default: assert(0 && "Unknown decl qualifier");
59945937ae10a0f70f74508165aab4f2b63e18ea747Fariborz Jahanian      case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
60045937ae10a0f70f74508165aab4f2b63e18ea747Fariborz Jahanian      case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
601f85e193739c953358c865005855253af4f68a497John McCall      case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
602f85e193739c953358c865005855253af4f68a497John McCall      case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
60392e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner      case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
60442499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson      case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
60542499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson      }
606e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner      DS.setObjCDeclQualifier(Qual);
60742499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson      ConsumeToken();
60842499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson      II = 0;
60942499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson      break;
61042499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson    }
611dd5b5f2bb73d037745940431b71eb98393d12d4fChris Lattner
6121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // If this wasn't a recognized qualifier, bail out.
6134ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor    if (II) return;
61442499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  }
615a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian}
6164ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor
617a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///   objc-type-name:
6187d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///     '(' objc-type-qualifiers[opt] type-name ')'
6194ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor///     '(' objc-type-qualifiers[opt] ')'
6204ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor///
62142499be29b620d2eae34beb0f4d0f9da5a9584daAnders CarlssonParser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
62242499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  assert(Tok.is(tok::l_paren) && "expected (");
62342499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson
62442499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  SourceLocation LParenLoc = ConsumeParen();
62542499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  SourceLocation TypeStartLoc = Tok.getLocation();
62642499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson
62742499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  // Parse type qualifiers, in, inout, etc.
628cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner  ParseObjCTypeQualifierList(DS);
629dd5b5f2bb73d037745940431b71eb98393d12d4fChris Lattner
630d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  TypeTy *Ty = 0;
6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (isTypeSpecifierQualifier())
63242499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson    Ty = ParseTypeName();
6338ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner
63442499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson  if (Tok.is(tok::r_paren))
6351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    ConsumeParen();
636e0097db2848c463a534c18c235c6d3e53f2f1b87Fariborz Jahanian  else if (Tok.getLocation() == TypeStartLoc) {
637e0097db2848c463a534c18c235c6d3e53f2f1b87Fariborz Jahanian    // If we didn't eat any tokens, then this isn't a type.
638156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner    Diag(Tok, diag::err_expected_type);
6398ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    SkipUntil(tok::r_paren);
6408ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner  } else {
6418ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    // Otherwise, we found *something*, but didn't get a ')' in the right
64242499be29b620d2eae34beb0f4d0f9da5a9584daAnders Carlsson    // place.  Emit an error then return what we have as the type.
6438ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    MatchRHSPunctuation(tok::r_paren, LParenLoc);
644e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner  }
645a9500f05ba6c09bbd84d342236863833067cd816Chris Lattner  return Ty;
646cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner}
647cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner
648cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner///   objc-method-decl:
6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     objc-selector
650156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner///     objc-keyword-selector objc-parmlist[opt]
651156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner///     objc-type-name objc-selector
6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     objc-type-name objc-keyword-selector objc-parmlist[opt]
653156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner///
654d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian///   objc-keyword-selector:
6551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     objc-keyword-decl
6564a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor///     objc-keyword-selector objc-keyword-decl
657d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian///
658d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian///   objc-keyword-decl:
6593536b443bc50d58a79f14fca9b6842541a434854Steve Naroff///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
6601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     objc-selector ':' objc-keyword-attributes[opt] identifier
6613536b443bc50d58a79f14fca9b6842541a434854Steve Naroff///     ':' objc-type-name objc-keyword-attributes[opt] identifier
662294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     ':' objc-keyword-attributes[opt] identifier
663294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///
664294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///   objc-parmlist:
665294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     objc-parms objc-ellipsis[opt]
6664985aceceb9b9261b876b515d32726175c13a775Steve Naroff///
6674985aceceb9b9261b876b515d32726175c13a775Steve Naroff///   objc-parms:
6684985aceceb9b9261b876b515d32726175c13a775Steve Naroff///     objc-parms , parameter-declaration
669a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///
67090ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz Jahanian///   objc-ellipsis:
671df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner///     , ...
672294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///
6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///   objc-keyword-attributes:         [OBJC2]
674bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff///     __attribute__((unused))
675a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///
67690ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz JahanianParser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
6773536b443bc50d58a79f14fca9b6842541a434854Steve Naroff                                            tok::TokenKind mType,
6782bd42fadafddc8acf744b57a970bdc96a077c617Steve Naroff                                            DeclTy *IDecl,
679f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff                                            tok::ObjCKeywordKind MethodImplKind)
680294494e1cce92043562b4680c613df7fd028c02eSteve Naroff{
681294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  // Parse the return type if present.
682294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  TypeTy *ReturnType = 0;
683294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  ObjCDeclSpec DSRet;
684294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (Tok.is(tok::l_paren))
685294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ReturnType = ParseObjCTypeName(DSRet);
686294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
687294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  SourceLocation selLoc;
688294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  IdentifierInfo *SelIdent = ParseObjCSelector(selLoc);
689294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
6902fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner  if (!SelIdent) { // missing selector name.
691be74740cc246ce08d42804a684385a42eb814edbFariborz Jahanian    Diag(Tok, diag::err_expected_selector_for_method)
692ff38491c18b060526d754765b952f4a497a89416Chris Lattner      << SourceRange(mLoc, Tok.getLocation());
693ff38491c18b060526d754765b952f4a497a89416Chris Lattner    // Skip until we get a ; or {}.
694ff38491c18b060526d754765b952f4a497a89416Chris Lattner    SkipUntil(tok::r_brace);
695afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian    return 0;
696afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  }
697afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian
698afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  llvm::SmallVector<Declarator, 8> CargNames;
699afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  if (Tok.isNot(tok::colon)) {
700afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian    // If attributes exist after the method, parse them.
701afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian    AttributeList *MethodAttrs = 0;
702afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian    if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
703afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian      MethodAttrs = ParseAttributes();
704afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian
705afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian    Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
7063846ca29a8cc1d376a4b695194c29952dbbfb544Fariborz Jahanian    return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
7073f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose                                          mType, IDecl, DSRet, ReturnType, Sel,
708afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian                                          0, 0, 0, CargNames,
709afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian                                          MethodAttrs, MethodImplKind);
710afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  }
711afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian
712afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
713afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  llvm::SmallVector<Action::TypeTy *, 12> KeyTypes;
714afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  llvm::SmallVector<ObjCDeclSpec, 12> ArgTypeQuals;
715afbc68177cc11b8bfa47464b20e15d5f8fb21d4eFariborz Jahanian  llvm::SmallVector<IdentifierInfo *, 12> ArgNames;
716ff38491c18b060526d754765b952f4a497a89416Chris Lattner
717ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  Action::TypeTy *TypeInfo;
718ff38491c18b060526d754765b952f4a497a89416Chris Lattner  while (1) {
7199298d9655aed28b2d9f6cc65c81401b209f03fdcChris Lattner    KeyIdents.push_back(SelIdent);
720ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
721ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    // Each iteration parses a single keyword argument.
722ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (Tok.isNot(tok::colon)) {
723ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      Diag(Tok, diag::err_expected_colon);
724ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      break;
725ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
726ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ConsumeToken(); // Eat the ':'.
727ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ObjCDeclSpec DSType;
728ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (Tok.is(tok::l_paren)) // Parse the argument type.
729ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      TypeInfo = ParseObjCTypeName(DSType);
730ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    else
731ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      TypeInfo = 0;
732ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    KeyTypes.push_back(TypeInfo);
733ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ArgTypeQuals.push_back(DSType);
734ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
735ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    // If attributes exist before the argument name, parse them.
736ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
737ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      ParseAttributes(); // FIXME: pass attributes through.
738ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
739ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (Tok.isNot(tok::identifier)) {
740ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      Diag(Tok, diag::err_expected_ident); // missing argument name.
741ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      break;
742ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
743ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ArgNames.push_back(Tok.getIdentifierInfo());
744ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ConsumeToken(); // Eat the identifier.
745ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
746ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    // Check for another keyword selector.
747ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    SourceLocation Loc;
748ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    SelIdent = ParseObjCSelector(Loc);
749ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (!SelIdent && Tok.isNot(tok::colon))
750ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      break;
751ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    // We have a selector or a colon, continue parsing.
752ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
753ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
754ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  bool isVariadic = false;
755ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
756ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  // Parse the (optional) parameter list.
757ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  while (Tok.is(tok::comma)) {
758ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ConsumeToken();
759ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (Tok.is(tok::ellipsis)) {
760ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      isVariadic = true;
761ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      ConsumeToken();
762ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      break;
763ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
764ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    DeclSpec DS;
765ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ParseDeclarationSpecifiers(DS);
766ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    // Parse the declarator.
767ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    Declarator ParmDecl(DS, Declarator::PrototypeContext);
768ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ParseDeclarator(ParmDecl);
769ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    CargNames.push_back(ParmDecl);
770ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
771ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
772ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  // FIXME: Add support for optional parmameter list...
773ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  // If attributes exist after the method, parse them.
774ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  AttributeList *MethodAttrs = 0;
775ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
776ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    MethodAttrs = ParseAttributes();
777ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
778ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
779ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                                                   &KeyIdents[0]);
780ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
781ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                                        mType, IDecl, DSRet, ReturnType, Sel,
782ff38491c18b060526d754765b952f4a497a89416Chris Lattner                                        &ArgTypeQuals[0], &KeyTypes[0],
783ff38491c18b060526d754765b952f4a497a89416Chris Lattner                                        &ArgNames[0], CargNames,
784ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                                        MethodAttrs,
785ff38491c18b060526d754765b952f4a497a89416Chris Lattner                                        MethodImplKind, isVariadic);
7864b6c9051c6522894978c9ba6a819a659d102db36Fariborz Jahanian}
787ff38491c18b060526d754765b952f4a497a89416Chris Lattner
788d064951b0dcc95f8604d0d69ae82d9ecbd38c796Fariborz Jahanian///   objc-protocol-refs:
789294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///     '<' identifier-list '>'
790294494e1cce92043562b4680c613df7fd028c02eSteve Naroff///
7910196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanianbool Parser::
7920196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz JahanianParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclTy*> &Protocols,
793335a2d4122e41343fe11a775889b8bec5b14be60Fariborz Jahanian                            bool WarnOnDeclarations, SourceLocation &EndLoc) {
7943ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian  assert(Tok.is(tok::less) && "expected <");
7953ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian
7963ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian  ConsumeToken(); // the "<"
7974e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie
7985ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner  llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
7990196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanian
8000196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanian  while (1) {
801a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    if (Tok.isNot(tok::identifier)) {
802e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      Diag(Tok, diag::err_expected_ident);
803e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      SkipUntil(tok::greater);
804294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      return true;
805294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    }
806294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
807294494e1cce92043562b4680c613df7fd028c02eSteve Naroff                                       Tok.getLocation()));
808294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ConsumeToken();
809b77cab97f17f946744c920629ca17271308d8ebfDouglas Gregor
810cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    if (Tok.isNot(tok::comma))
811cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      break;
812cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    ConsumeToken();
813cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  }
814e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner
815d32b0225e29fcafb2b2b2a4b1c51dcb1518af9c6Douglas Gregor  // Consume the '>'.
816b77cab97f17f946744c920629ca17271308d8ebfDouglas Gregor  if (Tok.isNot(tok::greater)) {
817cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    Diag(Tok, diag::err_expected_greater);
8187d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    return true;
819d32b0225e29fcafb2b2b2a4b1c51dcb1518af9c6Douglas Gregor  }
820d32b0225e29fcafb2b2b2a4b1c51dcb1518af9c6Douglas Gregor
821cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner  EndLoc = ConsumeAnyToken();
822e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner
8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Convert the list of protocols identifiers into a list of protocol decls.
824e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  Actions.FindProtocolDeclaration(WarnOnDeclarations,
825e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner                                  &ProtocolIdents[0], ProtocolIdents.size(),
826a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek                                  Protocols);
827e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  return false;
8281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
829a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek
830e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///   objc-class-instance-variables:
831b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie///     '{' objc-instance-variable-decl-list[opt] '}'
832a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///
833a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///   objc-instance-variable-decl-list:
834a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///     objc-visibility-spec
835a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///     objc-instance-variable-decl ';'
836a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///     ';'
837a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///     objc-instance-variable-decl-list objc-visibility-spec
838e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
839a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek///     objc-instance-variable-decl-list ';'
840e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///
841e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///   objc-visibility-spec:
842e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///     @private
843e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner///     @protected
8441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     @public
845dcc2cbcd40bb7ba48b3d222c831bbb5e04140343Chris Lattner///     @package [OBJC2]
846dcc2cbcd40bb7ba48b3d222c831bbb5e04140343Chris Lattner///
84719d74e1494fe399f0e2a94e9419c095f8214851bFariborz Jahanian///   objc-instance-variable-decl:
84819d74e1494fe399f0e2a94e9419c095f8214851bFariborz Jahanian///     struct-declaration
84919d74e1494fe399f0e2a94e9419c095f8214851bFariborz Jahanian///
850cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCallvoid Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
851cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall                                             SourceLocation atLoc) {
852cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  assert(Tok.is(tok::l_brace) && "expected {");
853cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
854cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
855cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
856cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
857cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
858cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
859cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
860cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  tok::ObjCKeywordKind visibility = tok::objc_protected;
861cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  // While we still have something to read, read the instance variables.
862cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
863cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    // Each iteration of this loop reads one objc-instance-variable-decl.
864cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
865cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    // Check for extraneous top-level semicolon.
866cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    if (Tok.is(tok::semi)) {
867cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      Diag(Tok, diag::ext_extra_struct_semi);
868cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      ConsumeToken();
869cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      continue;
870cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    }
871cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
872cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    // Set the default visibility to private.
873cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    if (Tok.is(tok::at)) { // parse objc-visibility-spec
874cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      ConsumeToken(); // eat the @ sign
875cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      switch (Tok.getObjCKeywordID()) {
876cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      case tok::objc_private:
877cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      case tok::objc_public:
878cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      case tok::objc_protected:
879cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      case tok::objc_package:
880cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall        visibility = Tok.getObjCKeywordID();
881cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall        ConsumeToken();
882cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall        continue;
883cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      default:
884294494e1cce92043562b4680c613df7fd028c02eSteve Naroff        Diag(Tok, diag::err_objc_illegal_visibility_spec);
885294494e1cce92043562b4680c613df7fd028c02eSteve Naroff        continue;
886294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      }
887294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    }
888b77cab97f17f946744c920629ca17271308d8ebfDouglas Gregor
889cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    // Parse all the comma separated declarators.
890cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    DeclSpec DS;
891cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    FieldDeclarators.clear();
892cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    ParseStructDeclaration(DS, FieldDeclarators);
893cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
894cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    // Convert them all to fields.
895df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
8961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      FieldDeclarator &FD = FieldDeclarators[i];
8974a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor      // Install the declarator into interfaceDecl.
8984a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor      DeclTy *Field = Actions.ActOnIvar(CurScope,
8994a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor                                         DS.getSourceRange().getBegin(),
900e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner                                         FD.D, FD.BitfieldSize, visibility);
9019735c5e60027b26a809df19677ff16a4d13f1321Fariborz Jahanian      AllIvarDecls.push_back(Field);
9029735c5e60027b26a809df19677ff16a4d13f1321Fariborz Jahanian    }
90319d74e1494fe399f0e2a94e9419c095f8214851bFariborz Jahanian
904cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    if (Tok.is(tok::semi)) {
9054fa7afd07421e7276d1717e4fdf43a5fdd65a622Steve Naroff      ConsumeToken();
906b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall    } else {
907809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor      Diag(Tok, diag::err_expected_semi_decl_list);
908cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      // Skip to end of block or statement
909cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall      SkipUntil(tok::r_brace, true, true);
910cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    }
911cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  }
9126d1de1b8663fe652903bda2927b885d1ec0f2613Fariborz Jahanian  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
913cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  // Call ActOnFields() even if we don't have any decls. This is useful
914cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  // for code rewriting tools that need to be aware of the empty list.
915cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  Actions.ActOnFields(CurScope, atLoc, interfaceDecl,
916cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall                      &AllIvarDecls[0], AllIvarDecls.size(),
917cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall                      LBraceLoc, RBraceLoc, 0);
918cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall  return;
919cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall}
920cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall
921cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///   objc-protocol-declaration:
922cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///     objc-protocol-definition
923cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///     objc-protocol-forward-reference
924cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///
925cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///   objc-protocol-definition:
926cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///     @protocol identifier
927cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///       objc-protocol-refs[opt]
928cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall///       objc-interface-decl-list
929e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///     @end
930e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///
931e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///   objc-protocol-forward-reference:
932e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///     @protocol identifier-list ';'
933e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///
934e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///   "@protocol identifier ;" should be resolved as "@protocol
935e97179c675b341927807c718be215c8d1aab8acbDouglas Gregor///   identifier-list ;": objc-interface-decl-list may not start with a
936809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor///   semicolon in the first alternative if objc-protocol-refs are omitted.
937e97179c675b341927807c718be215c8d1aab8acbDouglas GregorParser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
9384a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner                                               AttributeList *attrList) {
9394a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
9404a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner         "ParseObjCAtProtocolDeclaration(): Expected @protocol");
941e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner  ConsumeToken(); // the "protocol" identifier
9421ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner
9434a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner  if (Tok.isNot(tok::identifier)) {
9444a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    Diag(Tok, diag::err_expected_ident); // missing protocol name.
9454a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    return 0;
9464a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner  }
9474a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor  // Save the protocol name, then consume it.
948294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  IdentifierInfo *protocolName = Tok.getIdentifierInfo();
949f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff  SourceLocation nameLoc = ConsumeToken();
950294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
951294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (Tok.is(tok::semi)) { // forward declaration of one protocol.
952294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    IdentifierLocPair ProtoInfo(protocolName, nameLoc);
953294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ConsumeToken();
9544985aceceb9b9261b876b515d32726175c13a775Steve Naroff    return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
955294494e1cce92043562b4680c613df7fd028c02eSteve Naroff                                                   attrList);
9564985aceceb9b9261b876b515d32726175c13a775Steve Naroff  }
957294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
958294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (Tok.is(tok::comma)) { // list of forward declarations.
9591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
960294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
961294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
962294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    // Parse the list of forward declarations.
9637ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    while (1) {
9647ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      ConsumeToken(); // the ','
9657ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      if (Tok.isNot(tok::identifier)) {
9667ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff        Diag(Tok, diag::err_expected_ident);
967294494e1cce92043562b4680c613df7fd028c02eSteve Naroff        SkipUntil(tok::semi);
9684985aceceb9b9261b876b515d32726175c13a775Steve Naroff        return 0;
9694985aceceb9b9261b876b515d32726175c13a775Steve Naroff      }
970294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
9714985aceceb9b9261b876b515d32726175c13a775Steve Naroff                                               Tok.getLocation()));
9724985aceceb9b9261b876b515d32726175c13a775Steve Naroff      ConsumeToken(); // the identifier
973294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
9744985aceceb9b9261b876b515d32726175c13a775Steve Naroff      if (Tok.isNot(tok::comma))
975294494e1cce92043562b4680c613df7fd028c02eSteve Naroff        break;
976294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    }
9777ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    // Consume the ';'.
9787ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
9797ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      return 0;
980d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
9812ccccb3ff40c64927817a7e1ddf1da8c188ed224Douglas Gregor    return Actions.ActOnForwardProtocolDeclaration(AtLoc,
98290ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz Jahanian                                                   &ProtocolRefs[0],
98390ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz Jahanian                                                   ProtocolRefs.size(),
9849257664568bf375b7790131a84d9a4fa30a5b7e3John McCall                                                   attrList);
98554abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  }
986e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor
98723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  // Last, and definitely not least, parse a protocol declaration.
988a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  SourceLocation EndProtoLoc;
9897d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis
9907d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  llvm::SmallVector<DeclTy *, 8> ProtocolRefs;
991e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  if (Tok.is(tok::less) &&
992e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor      ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
993e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner    return 0;
994b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall
995a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek  DeclTy *ProtoType =
996df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
997cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall                                        &ProtocolRefs[0], ProtocolRefs.size(),
9981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                        EndProtoLoc, attrList);
9999e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek  ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
10000b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return ProtoType;
10014e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie}
10020b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
10039e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek///   objc-implementation:
1004e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor///     objc-class-implementation-prologue
100523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor///     objc-category-implementation-prologue
1006a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///
10077d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///   objc-class-implementation-prologue:
10087d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///     @implementation identifier objc-superclass[opt]
1009e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor///       objc-class-instance-variables[opt]
1010e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor///
10119e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek///   objc-category-implementation-prologue:
1012bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff///     @implementation identifier ( identifier )
10132fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner
1014e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris LattnerParser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
101584c431088693e216193094d1dbf327a01173f57fSteve Naroff  SourceLocation atLoc) {
101684c431088693e216193094d1dbf327a01173f57fSteve Naroff  assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
10171ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner         "ParseObjCAtImplementationDeclaration(): Expected @implementation");
10181ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner  ConsumeToken(); // the "implementation" identifier
1019d30ec7076fef736754206ac87a4f2c67251cc4d8Fariborz Jahanian
1020d30ec7076fef736754206ac87a4f2c67251cc4d8Fariborz Jahanian  if (Tok.isNot(tok::identifier)) {
1021d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    Diag(Tok, diag::err_expected_ident); // missing class or category name.
1022e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner    return 0;
10231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
10245f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  // We have a class or category name - consume it.
1025df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  IdentifierInfo *nameId = Tok.getIdentifierInfo();
1026ff38491c18b060526d754765b952f4a497a89416Chris Lattner  SourceLocation nameLoc = ConsumeToken(); // consume class or category name
10274e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie
10280b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (Tok.is(tok::l_paren)) {
10291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // we have a category implementation.
1030ff38491c18b060526d754765b952f4a497a89416Chris Lattner    SourceLocation lparenLoc = ConsumeParen();
1031d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    SourceLocation categoryLoc, rparenLoc;
10327f53253223b29d77f1e9c5c0ce93a19932761b77Fariborz Jahanian    IdentifierInfo *categoryId = 0;
1033a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian
1034926df6cfabf3eaa4afc990c097fa4619b76a9b57Douglas Gregor    if (Tok.is(tok::identifier)) {
10354f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian      categoryId = Tok.getIdentifierInfo();
10360b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      categoryLoc = ConsumeToken();
10370b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    } else {
103854abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall      Diag(Tok, diag::err_expected_ident); // missing category name.
103954abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall      return 0;
1040ff38491c18b060526d754765b952f4a497a89416Chris Lattner    }
1041f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff    if (Tok.isNot(tok::r_paren)) {
10425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      Diag(Tok, diag::err_expected_rparen);
104311d77169555480ee0a04c6e5bc390d8fde41175dArgyrios Kyrtzidis      SkipUntil(tok::r_paren, false); // don't stop at ';'
10445f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      return 0;
10453a2b7a18a4504f39e3ded0d2b5749c5c80b8b9b5Richard Smith    }
10463a2b7a18a4504f39e3ded0d2b5749c5c80b8b9b5Richard Smith    rparenLoc = ConsumeParen();
10470b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    DeclTy *ImplCatType = Actions.ActOnStartCategoryImplementation(
10480b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall                                    atLoc, nameId, nameLoc, categoryId,
1049ff38491c18b060526d754765b952f4a497a89416Chris Lattner                                    categoryLoc);
10500b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    ObjCImpDecl = ImplCatType;
1051f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall    return 0;
10521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
1053ff38491c18b060526d754765b952f4a497a89416Chris Lattner  // We have a class implementation
1054df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  SourceLocation superClassLoc;
1055ff38491c18b060526d754765b952f4a497a89416Chris Lattner  IdentifierInfo *superClassId = 0;
1056ff38491c18b060526d754765b952f4a497a89416Chris Lattner  if (Tok.is(tok::colon)) {
1057ff38491c18b060526d754765b952f4a497a89416Chris Lattner    // We have a super class
1058ff38491c18b060526d754765b952f4a497a89416Chris Lattner    ConsumeToken();
10591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (Tok.isNot(tok::identifier)) {
1060b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall      Diag(Tok, diag::err_expected_ident); // missing super class name.
1061e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner      return 0;
1062cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    }
1063cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    superClassId = Tok.getIdentifierInfo();
1064cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall    superClassLoc = ConsumeToken(); // Consume super class name
1065e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  }
1066ff38491c18b060526d754765b952f4a497a89416Chris Lattner  DeclTy *ImplClsType = Actions.ActOnStartClassImplementation(
1067cdda47faab5c2c61c239491a1a091e071ed3e38eJohn McCall                                  atLoc, nameId, nameLoc,
1068e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner                                  superClassId, superClassLoc);
10694e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie
10700b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (Tok.is(tok::l_brace)) // we have ivars
10710b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
10727f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall  ObjCImpDecl = ImplClsType;
10737ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff
107440ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  return 0;
107540ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor}
107640ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor
107740ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas GregorParser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
107840ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  assert(Tok.isObjCAtKeyword(tok::objc_end) &&
107940ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor         "ParseObjCAtEndDeclaration(): Expected @end");
1080050315bfd0473323a68f2da99b51bbe2842f6c36Dmitri Gribenko  ConsumeToken(); // the "end" identifier
10817d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  if (ObjCImpDecl)
10827d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
108340ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  else
108440ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor    Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
1085df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  return ObjCImpDecl;
1086ff38491c18b060526d754765b952f4a497a89416Chris Lattner}
1087ff38491c18b060526d754765b952f4a497a89416Chris Lattner
10884985aceceb9b9261b876b515d32726175c13a775Steve Naroff///   compatibility-alias-decl:
10891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     @compatibility_alias alias-name  class-name ';'
1090e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner///
1091e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris LattnerParser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
1092ff38491c18b060526d754765b952f4a497a89416Chris Lattner  assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
1094e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  ConsumeToken(); // consume compatibility_alias
1095e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  if (Tok.isNot(tok::identifier)) {
109611d77169555480ee0a04c6e5bc390d8fde41175dArgyrios Kyrtzidis    Diag(Tok, diag::err_expected_ident);
1097e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner    return 0;
10980b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  }
10990b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  IdentifierInfo *aliasId = Tok.getIdentifierInfo();
11000b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
11011f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  if (Tok.isNot(tok::identifier)) {
11021f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor    Diag(Tok, diag::err_expected_ident);
11031f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor    return 0;
11041f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  }
110540ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  IdentifierInfo *classId = Tok.getIdentifierInfo();
1106050315bfd0473323a68f2da99b51bbe2842f6c36Dmitri Gribenko  SourceLocation classLoc = ConsumeToken(); // consume class-name;
11077d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  if (Tok.isNot(tok::semi)) {
11087d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
11091f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor    return 0;
11101f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  }
1111ff38491c18b060526d754765b952f4a497a89416Chris Lattner  DeclTy *ClsType = Actions.ActOnCompatiblityAlias(atLoc,
111211d77169555480ee0a04c6e5bc390d8fde41175dArgyrios Kyrtzidis                                                   aliasId, aliasLoc,
1113b648cf02f13ae74ec346f8d22933298f9977e4e0Ted Kremenek                                                   classId, classLoc);
1114b648cf02f13ae74ec346f8d22933298f9977e4e0Ted Kremenek  return ClsType;
111503ebd3b4af9e4ab8e14a3f136d8a28df463f54ecFariborz Jahanian}
111608602359845e668194d111b794b8965358babfe6Fariborz Jahanian
111708602359845e668194d111b794b8965358babfe6Fariborz Jahanian///   property-synthesis:
111803ebd3b4af9e4ab8e14a3f136d8a28df463f54ecFariborz Jahanian///     @synthesize property-ivar-list ';'
111903ebd3b4af9e4ab8e14a3f136d8a28df463f54ecFariborz Jahanian///
112003ebd3b4af9e4ab8e14a3f136d8a28df463f54ecFariborz Jahanian///   property-ivar-list:
112108602359845e668194d111b794b8965358babfe6Fariborz Jahanian///     property-ivar
112208602359845e668194d111b794b8965358babfe6Fariborz Jahanian///     property-ivar-list ',' property-ivar
1123ff38491c18b060526d754765b952f4a497a89416Chris Lattner///
1124ff38491c18b060526d754765b952f4a497a89416Chris Lattner///   property-ivar:
11251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///     identifier
1126335eafa5be51f6440672a74c73d588af72e96732Steve Naroff///     identifier '=' identifier
112756242baaae6c45b24fbdd5bc56fe4ee516fa9e6bFariborz Jahanian///
1128ff38491c18b060526d754765b952f4a497a89416Chris LattnerParser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1129df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1130ff38491c18b060526d754765b952f4a497a89416Chris Lattner         "ParseObjCPropertyDynamic(): Expected '@synthesize'");
1131df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  SourceLocation loc = ConsumeToken(); // consume synthesize
1132335eafa5be51f6440672a74c73d588af72e96732Steve Naroff  if (Tok.isNot(tok::identifier)) {
11334985aceceb9b9261b876b515d32726175c13a775Steve Naroff    Diag(Tok, diag::err_expected_ident);
1134ff38491c18b060526d754765b952f4a497a89416Chris Lattner    return 0;
11354985aceceb9b9261b876b515d32726175c13a775Steve Naroff  }
113656242baaae6c45b24fbdd5bc56fe4ee516fa9e6bFariborz Jahanian  while (Tok.is(tok::identifier)) {
113756242baaae6c45b24fbdd5bc56fe4ee516fa9e6bFariborz Jahanian    IdentifierInfo *propertyIvar = 0;
113856242baaae6c45b24fbdd5bc56fe4ee516fa9e6bFariborz Jahanian    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
113956242baaae6c45b24fbdd5bc56fe4ee516fa9e6bFariborz Jahanian    SourceLocation propertyLoc = ConsumeToken(); // consume property name
11400b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    if (Tok.is(tok::equal)) {
1141ff38491c18b060526d754765b952f4a497a89416Chris Lattner      // property '=' ivar-name
11421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      ConsumeToken(); // consume '='
1143ff38491c18b060526d754765b952f4a497a89416Chris Lattner      if (Tok.isNot(tok::identifier)) {
1144ff38491c18b060526d754765b952f4a497a89416Chris Lattner        Diag(Tok, diag::err_expected_ident);
11454f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian        break;
1146d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      }
11474f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian      propertyIvar = Tok.getIdentifierInfo();
11484f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian      ConsumeToken(); // consume ivar-name
11494f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian    }
11504f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian    Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
11514985aceceb9b9261b876b515d32726175c13a775Steve Naroff                                  propertyId, propertyIvar);
11521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (Tok.isNot(tok::comma))
11539c4bb2c08989265411925a04252fd4f93c26e3b1Cameron Esfahani      break;
1154e3a2ca7e30601cdd31c77a830f4cc487851e8096Fariborz Jahanian    ConsumeToken(); // consume ','
11554e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  }
11560b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (Tok.isNot(tok::semi))
11577f53253223b29d77f1e9c5c0ce93a19932761b77Fariborz Jahanian    Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
1158a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian  return 0;
1159d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
11607f53253223b29d77f1e9c5c0ce93a19932761b77Fariborz Jahanian
1161ff38491c18b060526d754765b952f4a497a89416Chris Lattner///   property-dynamic:
1162ff38491c18b060526d754765b952f4a497a89416Chris Lattner///     @dynamic  property-list
1163d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall///
11647f53253223b29d77f1e9c5c0ce93a19932761b77Fariborz Jahanian///   property-list:
1165a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///     identifier
116611d77169555480ee0a04c6e5bc390d8fde41175dArgyrios Kyrtzidis///     property-list ',' identifier
11674f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian///
11680b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallParser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
116990ba78c64d0c24cfbc1bf88728db9775d44d7f9fFariborz Jahanian  assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
11707f53253223b29d77f1e9c5c0ce93a19932761b77Fariborz Jahanian         "ParseObjCPropertyDynamic(): Expected '@dynamic'");
117154abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  SourceLocation loc = ConsumeToken(); // consume dynamic
117254abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  if (Tok.isNot(tok::identifier)) {
1173294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    Diag(Tok, diag::err_expected_ident);
1174294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    return 0;
1175dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
1176dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  while (Tok.is(tok::identifier)) {
1177dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
11787caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner    SourceLocation propertyLoc = ConsumeToken(); // consume property name
11795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
11805f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                  propertyId, 0);
118171b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis
118271b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis    if (Tok.isNot(tok::comma))
1183e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner      break;
11841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    ConsumeToken(); // consume ','
118571b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  }
11861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (Tok.isNot(tok::semi))
11875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
11881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return 0;
1189e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner}
119055385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor
119155385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor///  objc-throw-statement:
119255385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor///    throw expression[opt];
11937d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis///
11947d100872341f233c81e1d7b72b40457e62c36862Argyrios KyrtzidisParser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
119555385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor  OwningExprResult Res(Actions);
119655385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor  ConsumeToken(); // consume throw
1197df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  if (Tok.isNot(tok::semi)) {
1198dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    Res = ParseExpression();
1199dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (Res.isInvalid()) {
1200dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      SkipUntil(tok::semi);
1201dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      return StmtError();
1202e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner    }
1203e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  }
120471b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  ConsumeToken(); // consume ';'
1205e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res));
12061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
1207e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
1208e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner/// objc-synchronized-statement:
1209e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner///   @synchronized '(' expression ')' compound-statement
1210e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner///
12111eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpParser::OwningStmtResult
1212e13b9595dc1e2f4288bec34f3412359f648e84a5Chris LattnerParser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
1213b707a4762fcc47c12b5f487856ba0781c9399295Nico Weber  ConsumeToken(); // consume synchronized
1214e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  if (Tok.isNot(tok::l_paren)) {
12151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
1216e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner    return StmtError();
1217e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  }
1218e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  ConsumeParen();  // '('
1219e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  OwningExprResult Res(ParseExpression());
1220e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  if (Res.isInvalid()) {
1221e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner    SkipUntil(tok::semi);
1222e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner    return StmtError();
12239bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  }
12249bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  if (Tok.isNot(tok::r_paren)) {
122546f936e055d763437accd1e5a1bc49e7e5dbc0a3Douglas Gregor    Diag(Tok, diag::err_expected_lbrace);
12269bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor    return StmtError();
12274e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  }
12289bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  ConsumeParen();  // ')'
12295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  if (Tok.isNot(tok::l_brace)) {
12305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    Diag(Tok, diag::err_expected_lbrace);
123146f936e055d763437accd1e5a1bc49e7e5dbc0a3Douglas Gregor    return StmtError();
123246f936e055d763437accd1e5a1bc49e7e5dbc0a3Douglas Gregor  }
12339bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  // Enter a scope to hold everything within the compound stmt.  Compound
12349bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  // statements can always hold declarations.
12359bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  ParseScope BodyScope(this, Scope::DeclScope);
12369bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor
123746f936e055d763437accd1e5a1bc49e7e5dbc0a3Douglas Gregor  OwningStmtResult SynchBody(ParseCompoundStatementBody());
12389bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor
12399bd1d8d174a9d15ae343246c8322299248b9e92aDouglas Gregor  BodyScope.Exit();
12404cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian  if (SynchBody.isInvalid())
12414cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian    SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
12424cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian  return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody));
12434cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian}
12444cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian
12454cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian///  objc-try-catch-statement:
12464cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian///    @try compound-statement objc-catch-list[opt]
1247a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///    @try compound-statement objc-catch-list[opt] @finally compound-statement
12484a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor///
124910af87932fe4bffad539b24d512a33a1803daeaeFariborz Jahanian///  objc-catch-list:
12508749be53f53384e7846502791ceda6c657228d07Steve Naroff///    @catch ( parameter-declaration ) compound-statement
12518749be53f53384e7846502791ceda6c657228d07Steve Naroff///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
125223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor///  catch-parameter-declaration:
125377b6de07be9186063c12928d2e9785a5d4eecbf6David Blaikie///     parameter-declaration
12544a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor///     '...' [OBJC2]
12554cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian///
12569bd1d8d174a9d15ae343246c8322299248b9e92aDouglas GregorParser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
1257dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  bool catch_or_finally_seen = false;
1258dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1259dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ConsumeToken(); // consume try
1260dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (Tok.isNot(tok::l_brace)) {
1261dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    Diag(Tok, diag::err_expected_lbrace);
1262dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    return StmtError();
1263dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
1264dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  OwningStmtResult CatchStmts(Actions);
1265dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  OwningStmtResult FinallyStmt(Actions);
1266dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ParseScope TryScope(this, Scope::DeclScope);
1267dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  OwningStmtResult TryBody(ParseCompoundStatementBody());
1268dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  TryScope.Exit();
1269dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (TryBody.isInvalid())
1270dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    TryBody = Actions.ActOnNullStmt(Tok.getLocation());
1271dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1272ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  while (Tok.is(tok::at)) {
1273dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // At this point, we need to lookahead to determine if this @ is the start
1274dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // of an @catch or @finally.  We don't want to consume the @ token if this
12751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // is an @try or @encode or something else.
1276dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    Token AfterAt = GetLookAheadToken(1);
1277d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
127883c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian        !AfterAt.isObjCAtKeyword(tok::objc_finally))
127960fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff      break;
1280df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
12815f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SourceLocation AtCatchFinallyLoc = ConsumeToken();
1282a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    if (Tok.isObjCAtKeyword(tok::objc_catch)) {
12831a0d31a3d7f14ddc6370ba912c778aece6c12cf0Douglas Gregor      OwningStmtResult FirstPart(Actions);
12843a387441ae339363ee5b254658f295e97bd9e913Argyrios Kyrtzidis      ConsumeToken(); // consume catch
128572de6676bd30f9081ee4166bbe07b4c270258ce6Douglas Gregor      if (Tok.is(tok::l_paren)) {
12864a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor        ConsumeParen();
12874a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor        ParseScope CatchScope(this, Scope::DeclScope);
1288ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff        if (Tok.isNot(tok::ellipsis)) {
1289df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner          DeclSpec DS;
1290ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          ParseDeclarationSpecifiers(DS);
12911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          // For some odd reason, the name of the exception variable is
1292ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          // optional. As a result, we need to use PrototypeContext.
1293df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner          Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
12944b0e6f1da341510c1ad83eaf4c836f3134d0156aRichard Trieu          ParseDeclarator(DeclaratorInfo);
1295ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          if (DeclaratorInfo.getIdentifier()) {
1296ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff            DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope,
12971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                          DeclaratorInfo, 0);
1298ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff            FirstPart =
1299df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner              Actions.ActOnDeclStmt(aBlockVarDecl,
1300ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                                    DS.getSourceRange().getBegin(),
1301c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                                    DeclaratorInfo.getSourceRange().getEnd());
1302c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor          }
130323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor        } else
13047d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis          ConsumeToken(); // consume '...'
1305c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor        SourceLocation RParenLoc = ConsumeParen();
1306c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor
1307861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff        OwningStmtResult CatchBody(Actions, true);
1308ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff        if (Tok.is(tok::l_brace))
1309ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          CatchBody = ParseCompoundStatementBody();
1310ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff        else
1311ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          Diag(Tok, diag::err_expected_lbrace);
1312861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff        if (CatchBody.isInvalid())
1313ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff          CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
1315695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian                        RParenLoc, move(FirstPart), move(CatchBody),
1316695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian                        move(CatchStmts));
1317695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian      } else {
13184cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian        Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
13194cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian          << "@catch clause";
13204cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian        return StmtError();
13214cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian      }
13224cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian      catch_or_finally_seen = true;
13234cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian    } else {
13244cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian      assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
1325695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian      ConsumeToken(); // consume finally
1326695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian      ParseScope FinallyScope(this, Scope::DeclScope);
1327695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian
1328695031cd78fe789efbb88504372413432ae2feaaFariborz Jahanian      OwningStmtResult FinallyBody(Actions, true);
1329ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff      if (Tok.is(tok::l_brace))
1330ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff        FinallyBody = ParseCompoundStatementBody();
13311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      else
1332c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor        Diag(Tok, diag::err_expected_lbrace);
133323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor      if (FinallyBody.isInvalid())
1334f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall        FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
13357d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis      FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
1336c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                                                   move(FinallyBody));
1337c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor      catch_or_finally_seen = true;
1338bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall      break;
1339bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall    }
1340d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  }
1341bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  if (!catch_or_finally_seen) {
13425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    Diag(atLoc, diag::err_missing_catch_finally);
1343bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall    return StmtError();
1344d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  }
13455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody), move(CatchStmts),
1346bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall                                    move(FinallyStmt));
1347bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall}
1348bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
1349dcdff46dd8e6d749283fe6c43adfcfe780c1d562Eli Friedman///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
1350a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///
1351bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCallParser::DeclTy *Parser::ParseObjCMethodDefinition() {
1352d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  DeclTy *MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
135323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  // parse optional ';'
1354bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  if (Tok.is(tok::semi))
1355a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    ConsumeToken();
135610af87932fe4bffad539b24d512a33a1803daeaeFariborz Jahanian
13570bd04596e4645ff145a046dfb3475f39674060d9Fariborz Jahanian  // We should have an opening brace now.
13580bd04596e4645ff145a046dfb3475f39674060d9Fariborz Jahanian  if (Tok.isNot(tok::l_brace)) {
1359f66a0dda541cd859a928193efba6dc5d7ba8fe54Eli Friedman    Diag(Tok, diag::err_expected_method_body);
1360bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
1361bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall    // Skip over garbage, until we get to '{'.  Don't eat the '{'.
1362d097be8f81fbf4ed96ac10bae18562dd8202666bFariborz Jahanian    SkipUntil(tok::l_brace, true, true);
1363e13594279a952537ac903325efff57e3edca79d9Chris Lattner
1364f66a0dda541cd859a928193efba6dc5d7ba8fe54Eli Friedman    // If we didn't find the '{', bail out.
1365bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall    if (Tok.isNot(tok::l_brace))
13661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return 0;
1367df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  }
1368ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  SourceLocation BraceLoc = Tok.getLocation();
1369ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1370ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  // Enter a scope for the method body.
1371ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
1372ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1373ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  // Tell the actions module that we have entered a method definition with the
1374ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  // specified Declarator for the method.
13754cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian  Actions.ObjCActOnStartOfMethodDef(CurScope, MDecl);
13764cc0cf1a54541b26b258c45cd7a3c80c9401eaadFariborz Jahanian
1377ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  OwningStmtResult FnBody(ParseCompoundStatementBody());
13785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1379dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // If the function body could not be parsed, make a bogus compoundstmt.
1380dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (FnBody.isInvalid())
1381dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
1382dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                       MultiStmtArg(Actions), false);
1383dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1384dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Leave the function body scope.
138517d26a6c1f2cb921d0000c337b4967699dc928fdJames Dennett  BodyScope.Exit();
13861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // TODO: Pass argument information.
138817d26a6c1f2cb921d0000c337b4967699dc928fdJames Dennett  Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
1389dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  return MDecl;
1390dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
139117d26a6c1f2cb921d0000c337b4967699dc928fdJames Dennett
1392dac269b65eed82182fc3e96566dedd6562dfe11eSteve NaroffParser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
139317d26a6c1f2cb921d0000c337b4967699dc928fdJames Dennett  if (Tok.isObjCAtKeyword(tok::objc_try)) {
13943536b443bc50d58a79f14fca9b6842541a434854Steve Naroff    return ParseObjCTryStmt(AtLoc);
1395dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  } else if (Tok.isObjCAtKeyword(tok::objc_throw))
1396bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor    return ParseObjCThrowStmt(AtLoc);
1397bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor  else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
1398bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor    return ParseObjCSynchronizedStmt(AtLoc);
1399861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff  OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
14007ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  if (Res.isInvalid()) {
14017ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    // If the expression is invalid, skip ahead to the next semicolon. Not
14021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // doing this opens us up to the possibility of infinite loops if
1403083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor    // ParseExpression does not consume any tokens.
140423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    SkipUntil(tok::semi);
14057d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    return StmtError();
1406bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor  }
1407083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor  // Otherwise, eat the semicolon.
1408083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor  ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1409e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber  return Actions.ActOnExprStmt(move(Res));
14109f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber}
1411df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
14127ef58fdbefddf693910e6403a71b3d367444c897Steve NaroffParser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
1413bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor  switch (Tok.getKind()) {
14147ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  case tok::string_literal:    // primary-expression: string-literal
14157ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  case tok::wide_string_literal:
14167ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
14177ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  default:
14181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (Tok.getIdentifierInfo() == 0)
1419df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      return ExprError(Diag(AtLoc, diag::err_unexpected_at));
14207caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner
14217ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    case tok::objc_encode:
14237f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall      return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
14247ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    case tok::objc_protocol:
14251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
142690ec96f3026480fa41057b05d58f338aed585f62Erik Verbruggen    case tok::objc_selector:
142790ec96f3026480fa41057b05d58f338aed585f62Erik Verbruggen      return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
1428df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    default:
14295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      return ExprError(Diag(AtLoc, diag::err_unexpected_at));
14307caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner    }
14317caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner  }
14327ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff}
14337ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff
14347ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff///   objc-message-expr:
1435df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner///     '[' objc-receiver objc-message-args ']'
14367ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff///
14377ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff///   objc-receiver:
1438bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor///     expression
14397ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff///     class-name
14407caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner///     type-name
14417caeabd868d46cf4e68478c6e9136dae4e735d21Chris LattnerParser::OwningExprResult Parser::ParseObjCMessageExpression() {
14427ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  assert(Tok.is(tok::l_square) && "'[' expected");
14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  SourceLocation LBracLoc = ConsumeBracket(); // consume '['
1444df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
14457ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  // Parse receiver
14467ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  if (isTokObjCMessageIdentifierReceiver()) {
14477ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
14487ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    SourceLocation NameLoc = ConsumeToken();
1449bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor    return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
14501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                          ExprArg(Actions));
1451e440eb8158e71deb1e4ab11618ae3d680aac6da1Steve Naroff  }
14521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1453bc1c877fe28fb6a825f0b226a0a2da99e713ea03Fariborz Jahanian  OwningExprResult Res(ParseExpression());
14547f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall  if (Res.isInvalid()) {
14557caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner    SkipUntil(tok::r_square);
14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return move(Res);
14577ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  }
145871b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis
14597caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner  return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
14605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        0, move(Res));
14615f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner}
14627caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner
146371b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis/// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
146471b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis/// the rest of a message expression.
1465bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor///
14661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///   objc-message-args:
1467d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall///     objc-selector
1468e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner///     objc-keywordarg-list
1469beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad///
1470beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad///   objc-keywordarg-list:
147118df52bbb5d28ca082064d31ae7558dbdae52377Douglas Gregor///     objc-keywordarg
14727f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall///     objc-keywordarg-list objc-keywordarg
1473a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian///
14742f64cfe19e8bf6b6ba1660e38da8c421440457feFariborz Jahanian///   objc-keywordarg:
1475bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor///     selector-name[opt] ':' objc-keywordexpr
1476dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///
1477dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///   objc-keywordexpr:
1478dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///     nonempty-expr-list
1479dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///
1480dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///   nonempty-expr-list:
1481dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///     assignment-expression
1482dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///     nonempty-expr-list , assignment-expression
1483dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff///
1484dac269b65eed82182fc3e96566dedd6562dfe11eSteve NaroffParser::OwningExprResult
1485dac269b65eed82182fc3e96566dedd6562dfe11eSteve NaroffParser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
1486dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                       SourceLocation NameLoc,
1487dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                                       IdentifierInfo *ReceiverName,
1488849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis                                       ExprArg ReceiverExpr) {
1489849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  // Parse objc-selector
1490ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  SourceLocation Loc;
1491ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  IdentifierInfo *selIdent = ParseObjCSelector(Loc);
1492d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen
1493ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
14941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ExprVector KeyExprs(Actions);
14953b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
14963b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  if (Tok.is(tok::colon)) {
149723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    while (1) {
14987d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis      // Each iteration parses a single keyword argument.
1499849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      KeyIdents.push_back(selIdent);
15003b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
15013b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor      if (Tok.isNot(tok::colon)) {
1502e145bfd06c7eaf0cff0f7d825d1c6244127c26dfNico Weber        Diag(Tok, diag::err_expected_colon);
15039f4f5f1ca1e1967daf64d5422717c9b1e75eeb9eNico Weber        // We must manually skip to a ']', otherwise the expression skipper will
1504df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1505ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        // the enclosing expression.
1506849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis        SkipUntil(tok::r_square);
1507ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        return ExprError();
1508ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      }
1509ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian
1510ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      ConsumeToken(); // Eat the ':'.
1511849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      ///  Parse the expression after ':'
15121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      OwningExprResult Res(ParseAssignmentExpression());
15131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      if (Res.isInvalid()) {
1514ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        // We must manually skip to a ']', otherwise the expression skipper will
1515dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1516ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        // the enclosing expression.
1517ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        SkipUntil(tok::r_square);
15181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        return move(Res);
151933ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor      }
152023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
15217d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis      // We have a valid expression.
1522849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      KeyExprs.push_back(Res.release());
152333ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor
152433ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor      // Check for another keyword selector.
1525df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      selIdent = ParseObjCSelector(Loc);
1526ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      if (!selIdent && Tok.isNot(tok::colon))
1527ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        break;
1528ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      // We have a selector or a colon, continue parsing.
1529ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    }
1530849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // Parse the, optional, argument list, comma separated.
15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    while (Tok.is(tok::comma)) {
1532df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      ConsumeToken(); // Eat the ','.
1533ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      ///  Parse the expression after ','
1534ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      OwningExprResult Res(ParseAssignmentExpression());
1535849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      if (Res.isInvalid()) {
1536ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        // We must manually skip to a ']', otherwise the expression skipper will
1537ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1538e4bb74973cfdf0c82aca2088ccfae5e61727c846Fariborz Jahanian        // the enclosing expression.
1539e4bb74973cfdf0c82aca2088ccfae5e61727c846Fariborz Jahanian        SkipUntil(tok::r_square);
154051c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian        return move(Res);
154151c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian      }
154251c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian
154351c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian      // We have a valid expression.
1544849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      KeyExprs.push_back(Res.release());
1545d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen    }
15468f3fde00ad4d4f943321e338b914ae4740711c84Fariborz Jahanian  } else if (!selIdent) {
1547a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian    Diag(Tok, diag::err_expected_ident); // missing selector name.
1548849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1549849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // We must manually skip to a ']', otherwise the expression skipper will
1550849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1551849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // the enclosing expression.
1552849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    SkipUntil(tok::r_square);
1553849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    return ExprError();
1554849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  }
1555849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1556849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  if (Tok.isNot(tok::r_square)) {
1557849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    Diag(Tok, diag::err_expected_rsquare);
1558849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // We must manually skip to a ']', otherwise the expression skipper will
1559849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
1560849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    // the enclosing expression.
1561ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    SkipUntil(tok::r_square);
1562849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    return ExprError();
1563849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  }
1564849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1565849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
1566849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1567849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  unsigned nKeys = KeyIdents.size();
156851c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian  if (nKeys == 0)
156951c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian    KeyIdents.push_back(selIdent);
157051c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian  Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
157151c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian
157251c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian  // We've just parsed a keyword message.
157351c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian  if (ReceiverName)
157451c30afe7e2eb9273dd706229f42d87524fb8660Fariborz Jahanian    return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
1575ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian                                           LBracLoc, NameLoc, RBracLoc,
1576849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis                                           KeyExprs.take(), KeyExprs.size()));
15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
1578849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis                                            LBracLoc, RBracLoc,
1579a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian                                            KeyExprs.take(), KeyExprs.size()));
1580849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis}
1581849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1582849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios KyrtzidisParser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
1583849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  OwningExprResult Res(ParseStringLiteralExpression());
15844e24f0f711e2c9fde79f19fa1c80deaab3f3b356Richard Smith  if (Res.isInvalid()) return move(Res);
1585849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1586849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
1587849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  // expressions.  At this point, we know that the only valid thing that starts
1588849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  // with '@' is an @"".
1589849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  llvm::SmallVector<SourceLocation, 4> AtLocs;
1590849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  ExprVector AtStrings(Actions);
1591849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  AtLocs.push_back(AtLoc);
1592849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  AtStrings.push_back(Res.release());
1593644af7b50bd0541468b45c197f5b637e934d48a0Argyrios Kyrtzidis
15945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  while (Tok.is(tok::at)) {
159560fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff    AtLocs.push_back(ConsumeToken()); // eat the @.
1596140ab234c23f392d5422691c5de1ee3c15026defFariborz Jahanian
1597140ab234c23f392d5422691c5de1ee3c15026defFariborz Jahanian    // Invalid unless there is a string literal.
1598ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    OwningExprResult Lit(Actions, true);
1599ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    if (isTokenStringLiteral())
1600ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      Lit = ParseStringLiteralExpression();
1601849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    else
1602849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis      Diag(Tok, diag::err_objc_concat_string);
16038697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian
1604782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek    if (Lit.isInvalid())
1605d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen      return move(Lit);
1606849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
16075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    AtStrings.push_back(Lit.release());
1608e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian  }
1609849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1610849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
1611849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis                                              AtStrings.size()));
1612849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis}
1613849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1614849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis///    objc-encode-expression:
1615849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis///      @encode ( type-name )
1616849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios KyrtzidisParser::OwningExprResult
1617849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios KyrtzidisParser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
1618849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
1619849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1620849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  SourceLocation EncLoc = ConsumeToken();
1621849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1622d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  if (Tok.isNot(tok::l_paren))
1623849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
1624849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1625849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  SourceLocation LParenLoc = ConsumeParen();
1626849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
16276c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian  TypeTy *Ty = ParseTypeName();
16286c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian
1629d64251fd56577dd5c78903454632361e094c6dc1Erik Verbruggen  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1630849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
163163e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian  return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty,
16326c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian                                                 RParenLoc));
16336c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian}
16346c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian
16356c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian///     objc-protocol-expression
16366c89eafc90f5c51a0bf185a993961170aee530c2Fariborz Jahanian///       @protocol ( protocol-name )
1637849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios KyrtzidisParser::OwningExprResult
16382fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios KyrtzidisParser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
16392fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis  SourceLocation ProtoLoc = ConsumeToken();
16402fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis
16412fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis  if (Tok.isNot(tok::l_paren))
16422fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
1643849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis
1644849639d8b548519cc5a00c0c9253f0c0d525060dArgyrios Kyrtzidis  SourceLocation LParenLoc = ConsumeParen();
16452fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis
16462fea2242fe7e7c37df1e96316616febeaf4e29ebArgyrios Kyrtzidis  if (Tok.isNot(tok::identifier))
1647e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian    return ExprError(Diag(Tok, diag::err_expected_ident));
1648e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1649e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian  IdentifierInfo *protocolId = Tok.getIdentifierInfo();
1650d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  ConsumeToken();
1651e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1652e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1653e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1654df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
1655e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian                                                   LParenLoc, RParenLoc));
1656d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
1657e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1658243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian///     objc-selector-expression
1659243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian///       @selector '(' objc-keyword-selector ')'
1660df19526177bc6d0a3ea4d1ae97497869f60563dbChris LattnerParser::OwningExprResult
1661e992af01d14e2e31037562c123af0a71ae1ed374Fariborz JahanianParser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
1662d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  SourceLocation SelectorLoc = ConsumeToken();
1663e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1664243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian  if (Tok.isNot(tok::l_paren))
1665243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
1666e6bf90aec0044342ffccd13201b8a3a31a985a4bDouglas Gregor
1667e6bf90aec0044342ffccd13201b8a3a31a985a4bDouglas Gregor  llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1668de01b7a6b4df27555ff7b25e51c0d3df29e3a0cfRichard Smith  SourceLocation LParenLoc = ConsumeParen();
1669de01b7a6b4df27555ff7b25e51c0d3df29e3a0cfRichard Smith  SourceLocation sLoc;
16705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo *SelIdent = ParseObjCSelector(sLoc);
16715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name.
1672ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    return ExprError(Diag(Tok, diag::err_expected_ident));
1673ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1674ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  KeyIdents.push_back(SelIdent);
1675ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  unsigned nColons = 0;
1676ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  if (Tok.isNot(tok::r_paren)) {
1677ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    while (1) {
1678ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      if (Tok.isNot(tok::colon))
1679ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        return ExprError(Diag(Tok, diag::err_expected_colon));
1680ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1681ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      nColons++;
1682ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      ConsumeToken(); // Eat the ':'.
1683d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      if (Tok.is(tok::r_paren))
1684ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        break;
1685df1fdfd093e4e8d07813b5d86c22bb50a82e6714Fariborz Jahanian      // Check for another keyword selector.
1686dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin      SourceLocation Loc;
16871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      SelIdent = ParseObjCSelector(Loc);
1688b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor      KeyIdents.push_back(SelIdent);
1689322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor      if (!SelIdent && Tok.isNot(tok::colon))
1690a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian        break;
16917d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    }
16927d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  }
1693322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1694322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
1695b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor  return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
1696b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor                                                   LParenLoc, RParenLoc));
1697b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor }
1698d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall