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