xref: /minix3/external/bsd/llvm/dist/clang/lib/Parse/ParseObjc.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
2*f4a2713aSLionel Sambuc //
3*f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*f4a2713aSLionel Sambuc //
5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7*f4a2713aSLionel Sambuc //
8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9*f4a2713aSLionel Sambuc //
10*f4a2713aSLionel Sambuc //  This file implements the Objective-C portions of the Parser interface.
11*f4a2713aSLionel Sambuc //
12*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13*f4a2713aSLionel Sambuc 
14*f4a2713aSLionel Sambuc #include "clang/Parse/Parser.h"
15*f4a2713aSLionel Sambuc #include "RAIIObjectsForParser.h"
16*f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
17*f4a2713aSLionel Sambuc #include "clang/Parse/ParseDiagnostic.h"
18*f4a2713aSLionel Sambuc #include "clang/Sema/DeclSpec.h"
19*f4a2713aSLionel Sambuc #include "clang/Sema/PrettyDeclStackTrace.h"
20*f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h"
21*f4a2713aSLionel Sambuc #include "llvm/ADT/SmallVector.h"
22*f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
23*f4a2713aSLionel Sambuc using namespace clang;
24*f4a2713aSLionel Sambuc 
25*f4a2713aSLionel Sambuc /// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
26*f4a2713aSLionel Sambuc void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
27*f4a2713aSLionel Sambuc   ParsedAttributes attrs(AttrFactory);
28*f4a2713aSLionel Sambuc   if (Tok.is(tok::kw___attribute)) {
29*f4a2713aSLionel Sambuc     if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
30*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_postfix_attribute_hint)
31*f4a2713aSLionel Sambuc           << (Kind == tok::objc_protocol);
32*f4a2713aSLionel Sambuc     else
33*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_postfix_attribute);
34*f4a2713aSLionel Sambuc     ParseGNUAttributes(attrs);
35*f4a2713aSLionel Sambuc   }
36*f4a2713aSLionel Sambuc }
37*f4a2713aSLionel Sambuc 
38*f4a2713aSLionel Sambuc /// ParseObjCAtDirectives - Handle parts of the external-declaration production:
39*f4a2713aSLionel Sambuc ///       external-declaration: [C99 6.9]
40*f4a2713aSLionel Sambuc /// [OBJC]  objc-class-definition
41*f4a2713aSLionel Sambuc /// [OBJC]  objc-class-declaration
42*f4a2713aSLionel Sambuc /// [OBJC]  objc-alias-declaration
43*f4a2713aSLionel Sambuc /// [OBJC]  objc-protocol-definition
44*f4a2713aSLionel Sambuc /// [OBJC]  objc-method-definition
45*f4a2713aSLionel Sambuc /// [OBJC]  '@' 'end'
46*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
47*f4a2713aSLionel Sambuc   SourceLocation AtLoc = ConsumeToken(); // the "@"
48*f4a2713aSLionel Sambuc 
49*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
50*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtDirective(getCurScope());
51*f4a2713aSLionel Sambuc     cutOffParsing();
52*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
53*f4a2713aSLionel Sambuc   }
54*f4a2713aSLionel Sambuc 
55*f4a2713aSLionel Sambuc   Decl *SingleDecl = 0;
56*f4a2713aSLionel Sambuc   switch (Tok.getObjCKeywordID()) {
57*f4a2713aSLionel Sambuc   case tok::objc_class:
58*f4a2713aSLionel Sambuc     return ParseObjCAtClassDeclaration(AtLoc);
59*f4a2713aSLionel Sambuc   case tok::objc_interface: {
60*f4a2713aSLionel Sambuc     ParsedAttributes attrs(AttrFactory);
61*f4a2713aSLionel Sambuc     SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
62*f4a2713aSLionel Sambuc     break;
63*f4a2713aSLionel Sambuc   }
64*f4a2713aSLionel Sambuc   case tok::objc_protocol: {
65*f4a2713aSLionel Sambuc     ParsedAttributes attrs(AttrFactory);
66*f4a2713aSLionel Sambuc     return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
67*f4a2713aSLionel Sambuc   }
68*f4a2713aSLionel Sambuc   case tok::objc_implementation:
69*f4a2713aSLionel Sambuc     return ParseObjCAtImplementationDeclaration(AtLoc);
70*f4a2713aSLionel Sambuc   case tok::objc_end:
71*f4a2713aSLionel Sambuc     return ParseObjCAtEndDeclaration(AtLoc);
72*f4a2713aSLionel Sambuc   case tok::objc_compatibility_alias:
73*f4a2713aSLionel Sambuc     SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
74*f4a2713aSLionel Sambuc     break;
75*f4a2713aSLionel Sambuc   case tok::objc_synthesize:
76*f4a2713aSLionel Sambuc     SingleDecl = ParseObjCPropertySynthesize(AtLoc);
77*f4a2713aSLionel Sambuc     break;
78*f4a2713aSLionel Sambuc   case tok::objc_dynamic:
79*f4a2713aSLionel Sambuc     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
80*f4a2713aSLionel Sambuc     break;
81*f4a2713aSLionel Sambuc   case tok::objc_import:
82*f4a2713aSLionel Sambuc     if (getLangOpts().Modules)
83*f4a2713aSLionel Sambuc       return ParseModuleImport(AtLoc);
84*f4a2713aSLionel Sambuc 
85*f4a2713aSLionel Sambuc     // Fall through
86*f4a2713aSLionel Sambuc 
87*f4a2713aSLionel Sambuc   default:
88*f4a2713aSLionel Sambuc     Diag(AtLoc, diag::err_unexpected_at);
89*f4a2713aSLionel Sambuc     SkipUntil(tok::semi);
90*f4a2713aSLionel Sambuc     SingleDecl = 0;
91*f4a2713aSLionel Sambuc     break;
92*f4a2713aSLionel Sambuc   }
93*f4a2713aSLionel Sambuc   return Actions.ConvertDeclToDeclGroup(SingleDecl);
94*f4a2713aSLionel Sambuc }
95*f4a2713aSLionel Sambuc 
96*f4a2713aSLionel Sambuc ///
97*f4a2713aSLionel Sambuc /// objc-class-declaration:
98*f4a2713aSLionel Sambuc ///    '@' 'class' identifier-list ';'
99*f4a2713aSLionel Sambuc ///
100*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
101*f4a2713aSLionel Sambuc Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
102*f4a2713aSLionel Sambuc   ConsumeToken(); // the identifier "class"
103*f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 8> ClassNames;
104*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ClassLocs;
105*f4a2713aSLionel Sambuc 
106*f4a2713aSLionel Sambuc 
107*f4a2713aSLionel Sambuc   while (1) {
108*f4a2713aSLionel Sambuc     MaybeSkipAttributes(tok::objc_class);
109*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
110*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident);
111*f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
112*f4a2713aSLionel Sambuc       return Actions.ConvertDeclToDeclGroup(0);
113*f4a2713aSLionel Sambuc     }
114*f4a2713aSLionel Sambuc     ClassNames.push_back(Tok.getIdentifierInfo());
115*f4a2713aSLionel Sambuc     ClassLocs.push_back(Tok.getLocation());
116*f4a2713aSLionel Sambuc     ConsumeToken();
117*f4a2713aSLionel Sambuc 
118*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
119*f4a2713aSLionel Sambuc       break;
120*f4a2713aSLionel Sambuc 
121*f4a2713aSLionel Sambuc     ConsumeToken();
122*f4a2713aSLionel Sambuc   }
123*f4a2713aSLionel Sambuc 
124*f4a2713aSLionel Sambuc   // Consume the ';'.
125*f4a2713aSLionel Sambuc   if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
126*f4a2713aSLionel Sambuc     return Actions.ConvertDeclToDeclGroup(0);
127*f4a2713aSLionel Sambuc 
128*f4a2713aSLionel Sambuc   return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
129*f4a2713aSLionel Sambuc                                               ClassLocs.data(),
130*f4a2713aSLionel Sambuc                                               ClassNames.size());
131*f4a2713aSLionel Sambuc }
132*f4a2713aSLionel Sambuc 
133*f4a2713aSLionel Sambuc void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
134*f4a2713aSLionel Sambuc {
135*f4a2713aSLionel Sambuc   Sema::ObjCContainerKind ock = Actions.getObjCContainerKind();
136*f4a2713aSLionel Sambuc   if (ock == Sema::OCK_None)
137*f4a2713aSLionel Sambuc     return;
138*f4a2713aSLionel Sambuc 
139*f4a2713aSLionel Sambuc   Decl *Decl = Actions.getObjCDeclContext();
140*f4a2713aSLionel Sambuc   if (CurParsedObjCImpl) {
141*f4a2713aSLionel Sambuc     CurParsedObjCImpl->finish(AtLoc);
142*f4a2713aSLionel Sambuc   } else {
143*f4a2713aSLionel Sambuc     Actions.ActOnAtEnd(getCurScope(), AtLoc);
144*f4a2713aSLionel Sambuc   }
145*f4a2713aSLionel Sambuc   Diag(AtLoc, diag::err_objc_missing_end)
146*f4a2713aSLionel Sambuc       << FixItHint::CreateInsertion(AtLoc, "@end\n");
147*f4a2713aSLionel Sambuc   if (Decl)
148*f4a2713aSLionel Sambuc     Diag(Decl->getLocStart(), diag::note_objc_container_start)
149*f4a2713aSLionel Sambuc         << (int) ock;
150*f4a2713aSLionel Sambuc }
151*f4a2713aSLionel Sambuc 
152*f4a2713aSLionel Sambuc ///
153*f4a2713aSLionel Sambuc ///   objc-interface:
154*f4a2713aSLionel Sambuc ///     objc-class-interface-attributes[opt] objc-class-interface
155*f4a2713aSLionel Sambuc ///     objc-category-interface
156*f4a2713aSLionel Sambuc ///
157*f4a2713aSLionel Sambuc ///   objc-class-interface:
158*f4a2713aSLionel Sambuc ///     '@' 'interface' identifier objc-superclass[opt]
159*f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
160*f4a2713aSLionel Sambuc ///       objc-class-instance-variables[opt]
161*f4a2713aSLionel Sambuc ///       objc-interface-decl-list
162*f4a2713aSLionel Sambuc ///     @end
163*f4a2713aSLionel Sambuc ///
164*f4a2713aSLionel Sambuc ///   objc-category-interface:
165*f4a2713aSLionel Sambuc ///     '@' 'interface' identifier '(' identifier[opt] ')'
166*f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
167*f4a2713aSLionel Sambuc ///       objc-interface-decl-list
168*f4a2713aSLionel Sambuc ///     @end
169*f4a2713aSLionel Sambuc ///
170*f4a2713aSLionel Sambuc ///   objc-superclass:
171*f4a2713aSLionel Sambuc ///     ':' identifier
172*f4a2713aSLionel Sambuc ///
173*f4a2713aSLionel Sambuc ///   objc-class-interface-attributes:
174*f4a2713aSLionel Sambuc ///     __attribute__((visibility("default")))
175*f4a2713aSLionel Sambuc ///     __attribute__((visibility("hidden")))
176*f4a2713aSLionel Sambuc ///     __attribute__((deprecated))
177*f4a2713aSLionel Sambuc ///     __attribute__((unavailable))
178*f4a2713aSLionel Sambuc ///     __attribute__((objc_exception)) - used by NSException on 64-bit
179*f4a2713aSLionel Sambuc ///     __attribute__((objc_root_class))
180*f4a2713aSLionel Sambuc ///
181*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
182*f4a2713aSLionel Sambuc                                               ParsedAttributes &attrs) {
183*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
184*f4a2713aSLionel Sambuc          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
185*f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
186*f4a2713aSLionel Sambuc   ConsumeToken(); // the "interface" identifier
187*f4a2713aSLionel Sambuc 
188*f4a2713aSLionel Sambuc   // Code completion after '@interface'.
189*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
190*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
191*f4a2713aSLionel Sambuc     cutOffParsing();
192*f4a2713aSLionel Sambuc     return 0;
193*f4a2713aSLionel Sambuc   }
194*f4a2713aSLionel Sambuc 
195*f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_interface);
196*f4a2713aSLionel Sambuc 
197*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
198*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident); // missing class or category name.
199*f4a2713aSLionel Sambuc     return 0;
200*f4a2713aSLionel Sambuc   }
201*f4a2713aSLionel Sambuc 
202*f4a2713aSLionel Sambuc   // We have a class or category name - consume it.
203*f4a2713aSLionel Sambuc   IdentifierInfo *nameId = Tok.getIdentifierInfo();
204*f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken();
205*f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren) &&
206*f4a2713aSLionel Sambuc       !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
207*f4a2713aSLionel Sambuc 
208*f4a2713aSLionel Sambuc     BalancedDelimiterTracker T(*this, tok::l_paren);
209*f4a2713aSLionel Sambuc     T.consumeOpen();
210*f4a2713aSLionel Sambuc 
211*f4a2713aSLionel Sambuc     SourceLocation categoryLoc;
212*f4a2713aSLionel Sambuc     IdentifierInfo *categoryId = 0;
213*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
214*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
215*f4a2713aSLionel Sambuc       cutOffParsing();
216*f4a2713aSLionel Sambuc       return 0;
217*f4a2713aSLionel Sambuc     }
218*f4a2713aSLionel Sambuc 
219*f4a2713aSLionel Sambuc     // For ObjC2, the category name is optional (not an error).
220*f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier)) {
221*f4a2713aSLionel Sambuc       categoryId = Tok.getIdentifierInfo();
222*f4a2713aSLionel Sambuc       categoryLoc = ConsumeToken();
223*f4a2713aSLionel Sambuc     }
224*f4a2713aSLionel Sambuc     else if (!getLangOpts().ObjC2) {
225*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident); // missing category name.
226*f4a2713aSLionel Sambuc       return 0;
227*f4a2713aSLionel Sambuc     }
228*f4a2713aSLionel Sambuc 
229*f4a2713aSLionel Sambuc     T.consumeClose();
230*f4a2713aSLionel Sambuc     if (T.getCloseLocation().isInvalid())
231*f4a2713aSLionel Sambuc       return 0;
232*f4a2713aSLionel Sambuc 
233*f4a2713aSLionel Sambuc     if (!attrs.empty()) { // categories don't support attributes.
234*f4a2713aSLionel Sambuc       Diag(nameLoc, diag::err_objc_no_attributes_on_category);
235*f4a2713aSLionel Sambuc       attrs.clear();
236*f4a2713aSLionel Sambuc     }
237*f4a2713aSLionel Sambuc 
238*f4a2713aSLionel Sambuc     // Next, we need to check for any protocol references.
239*f4a2713aSLionel Sambuc     SourceLocation LAngleLoc, EndProtoLoc;
240*f4a2713aSLionel Sambuc     SmallVector<Decl *, 8> ProtocolRefs;
241*f4a2713aSLionel Sambuc     SmallVector<SourceLocation, 8> ProtocolLocs;
242*f4a2713aSLionel Sambuc     if (Tok.is(tok::less) &&
243*f4a2713aSLionel Sambuc         ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
244*f4a2713aSLionel Sambuc                                     LAngleLoc, EndProtoLoc))
245*f4a2713aSLionel Sambuc       return 0;
246*f4a2713aSLionel Sambuc 
247*f4a2713aSLionel Sambuc     Decl *CategoryType =
248*f4a2713aSLionel Sambuc     Actions.ActOnStartCategoryInterface(AtLoc,
249*f4a2713aSLionel Sambuc                                         nameId, nameLoc,
250*f4a2713aSLionel Sambuc                                         categoryId, categoryLoc,
251*f4a2713aSLionel Sambuc                                         ProtocolRefs.data(),
252*f4a2713aSLionel Sambuc                                         ProtocolRefs.size(),
253*f4a2713aSLionel Sambuc                                         ProtocolLocs.data(),
254*f4a2713aSLionel Sambuc                                         EndProtoLoc);
255*f4a2713aSLionel Sambuc 
256*f4a2713aSLionel Sambuc     if (Tok.is(tok::l_brace))
257*f4a2713aSLionel Sambuc       ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
258*f4a2713aSLionel Sambuc 
259*f4a2713aSLionel Sambuc     ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
260*f4a2713aSLionel Sambuc     return CategoryType;
261*f4a2713aSLionel Sambuc   }
262*f4a2713aSLionel Sambuc   // Parse a class interface.
263*f4a2713aSLionel Sambuc   IdentifierInfo *superClassId = 0;
264*f4a2713aSLionel Sambuc   SourceLocation superClassLoc;
265*f4a2713aSLionel Sambuc 
266*f4a2713aSLionel Sambuc   if (Tok.is(tok::colon)) { // a super class is specified.
267*f4a2713aSLionel Sambuc     ConsumeToken();
268*f4a2713aSLionel Sambuc 
269*f4a2713aSLionel Sambuc     // Code completion of superclass names.
270*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
271*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
272*f4a2713aSLionel Sambuc       cutOffParsing();
273*f4a2713aSLionel Sambuc       return 0;
274*f4a2713aSLionel Sambuc     }
275*f4a2713aSLionel Sambuc 
276*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
277*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident); // missing super class name.
278*f4a2713aSLionel Sambuc       return 0;
279*f4a2713aSLionel Sambuc     }
280*f4a2713aSLionel Sambuc     superClassId = Tok.getIdentifierInfo();
281*f4a2713aSLionel Sambuc     superClassLoc = ConsumeToken();
282*f4a2713aSLionel Sambuc   }
283*f4a2713aSLionel Sambuc   // Next, we need to check for any protocol references.
284*f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolRefs;
285*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
286*f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
287*f4a2713aSLionel Sambuc   if (Tok.is(tok::less) &&
288*f4a2713aSLionel Sambuc       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
289*f4a2713aSLionel Sambuc                                   LAngleLoc, EndProtoLoc))
290*f4a2713aSLionel Sambuc     return 0;
291*f4a2713aSLionel Sambuc 
292*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::less))
293*f4a2713aSLionel Sambuc     Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
294*f4a2713aSLionel Sambuc 
295*f4a2713aSLionel Sambuc   Decl *ClsType =
296*f4a2713aSLionel Sambuc     Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc,
297*f4a2713aSLionel Sambuc                                      superClassId, superClassLoc,
298*f4a2713aSLionel Sambuc                                      ProtocolRefs.data(), ProtocolRefs.size(),
299*f4a2713aSLionel Sambuc                                      ProtocolLocs.data(),
300*f4a2713aSLionel Sambuc                                      EndProtoLoc, attrs.getList());
301*f4a2713aSLionel Sambuc 
302*f4a2713aSLionel Sambuc   if (Tok.is(tok::l_brace))
303*f4a2713aSLionel Sambuc     ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
304*f4a2713aSLionel Sambuc 
305*f4a2713aSLionel Sambuc   ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
306*f4a2713aSLionel Sambuc   return ClsType;
307*f4a2713aSLionel Sambuc }
308*f4a2713aSLionel Sambuc 
309*f4a2713aSLionel Sambuc /// The Objective-C property callback.  This should be defined where
310*f4a2713aSLionel Sambuc /// it's used, but instead it's been lifted to here to support VS2005.
311*f4a2713aSLionel Sambuc struct Parser::ObjCPropertyCallback : FieldCallback {
312*f4a2713aSLionel Sambuc private:
313*f4a2713aSLionel Sambuc   virtual void anchor();
314*f4a2713aSLionel Sambuc public:
315*f4a2713aSLionel Sambuc   Parser &P;
316*f4a2713aSLionel Sambuc   SmallVectorImpl<Decl *> &Props;
317*f4a2713aSLionel Sambuc   ObjCDeclSpec &OCDS;
318*f4a2713aSLionel Sambuc   SourceLocation AtLoc;
319*f4a2713aSLionel Sambuc   SourceLocation LParenLoc;
320*f4a2713aSLionel Sambuc   tok::ObjCKeywordKind MethodImplKind;
321*f4a2713aSLionel Sambuc 
322*f4a2713aSLionel Sambuc   ObjCPropertyCallback(Parser &P,
323*f4a2713aSLionel Sambuc                        SmallVectorImpl<Decl *> &Props,
324*f4a2713aSLionel Sambuc                        ObjCDeclSpec &OCDS, SourceLocation AtLoc,
325*f4a2713aSLionel Sambuc                        SourceLocation LParenLoc,
326*f4a2713aSLionel Sambuc                        tok::ObjCKeywordKind MethodImplKind) :
327*f4a2713aSLionel Sambuc     P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc), LParenLoc(LParenLoc),
328*f4a2713aSLionel Sambuc     MethodImplKind(MethodImplKind) {
329*f4a2713aSLionel Sambuc   }
330*f4a2713aSLionel Sambuc 
331*f4a2713aSLionel Sambuc   void invoke(ParsingFieldDeclarator &FD) {
332*f4a2713aSLionel Sambuc     if (FD.D.getIdentifier() == 0) {
333*f4a2713aSLionel Sambuc       P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
334*f4a2713aSLionel Sambuc         << FD.D.getSourceRange();
335*f4a2713aSLionel Sambuc       return;
336*f4a2713aSLionel Sambuc     }
337*f4a2713aSLionel Sambuc     if (FD.BitfieldSize) {
338*f4a2713aSLionel Sambuc       P.Diag(AtLoc, diag::err_objc_property_bitfield)
339*f4a2713aSLionel Sambuc         << FD.D.getSourceRange();
340*f4a2713aSLionel Sambuc       return;
341*f4a2713aSLionel Sambuc     }
342*f4a2713aSLionel Sambuc 
343*f4a2713aSLionel Sambuc     // Install the property declarator into interfaceDecl.
344*f4a2713aSLionel Sambuc     IdentifierInfo *SelName =
345*f4a2713aSLionel Sambuc       OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
346*f4a2713aSLionel Sambuc 
347*f4a2713aSLionel Sambuc     Selector GetterSel =
348*f4a2713aSLionel Sambuc       P.PP.getSelectorTable().getNullarySelector(SelName);
349*f4a2713aSLionel Sambuc     IdentifierInfo *SetterName = OCDS.getSetterName();
350*f4a2713aSLionel Sambuc     Selector SetterSel;
351*f4a2713aSLionel Sambuc     if (SetterName)
352*f4a2713aSLionel Sambuc       SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
353*f4a2713aSLionel Sambuc     else
354*f4a2713aSLionel Sambuc       SetterSel =
355*f4a2713aSLionel Sambuc         SelectorTable::constructSetterSelector(P.PP.getIdentifierTable(),
356*f4a2713aSLionel Sambuc                                                P.PP.getSelectorTable(),
357*f4a2713aSLionel Sambuc                                                FD.D.getIdentifier());
358*f4a2713aSLionel Sambuc     bool isOverridingProperty = false;
359*f4a2713aSLionel Sambuc     Decl *Property =
360*f4a2713aSLionel Sambuc       P.Actions.ActOnProperty(P.getCurScope(), AtLoc, LParenLoc,
361*f4a2713aSLionel Sambuc                               FD, OCDS,
362*f4a2713aSLionel Sambuc                               GetterSel, SetterSel,
363*f4a2713aSLionel Sambuc                               &isOverridingProperty,
364*f4a2713aSLionel Sambuc                               MethodImplKind);
365*f4a2713aSLionel Sambuc     if (!isOverridingProperty)
366*f4a2713aSLionel Sambuc       Props.push_back(Property);
367*f4a2713aSLionel Sambuc 
368*f4a2713aSLionel Sambuc     FD.complete(Property);
369*f4a2713aSLionel Sambuc   }
370*f4a2713aSLionel Sambuc };
371*f4a2713aSLionel Sambuc 
372*f4a2713aSLionel Sambuc void Parser::ObjCPropertyCallback::anchor() {
373*f4a2713aSLionel Sambuc }
374*f4a2713aSLionel Sambuc 
375*f4a2713aSLionel Sambuc ///   objc-interface-decl-list:
376*f4a2713aSLionel Sambuc ///     empty
377*f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-property-decl [OBJC2]
378*f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-method-requirement [OBJC2]
379*f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-method-proto ';'
380*f4a2713aSLionel Sambuc ///     objc-interface-decl-list declaration
381*f4a2713aSLionel Sambuc ///     objc-interface-decl-list ';'
382*f4a2713aSLionel Sambuc ///
383*f4a2713aSLionel Sambuc ///   objc-method-requirement: [OBJC2]
384*f4a2713aSLionel Sambuc ///     @required
385*f4a2713aSLionel Sambuc ///     @optional
386*f4a2713aSLionel Sambuc ///
387*f4a2713aSLionel Sambuc void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
388*f4a2713aSLionel Sambuc                                         Decl *CDecl) {
389*f4a2713aSLionel Sambuc   SmallVector<Decl *, 32> allMethods;
390*f4a2713aSLionel Sambuc   SmallVector<Decl *, 16> allProperties;
391*f4a2713aSLionel Sambuc   SmallVector<DeclGroupPtrTy, 8> allTUVariables;
392*f4a2713aSLionel Sambuc   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
393*f4a2713aSLionel Sambuc 
394*f4a2713aSLionel Sambuc   SourceRange AtEnd;
395*f4a2713aSLionel Sambuc 
396*f4a2713aSLionel Sambuc   while (1) {
397*f4a2713aSLionel Sambuc     // If this is a method prototype, parse it.
398*f4a2713aSLionel Sambuc     if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
399*f4a2713aSLionel Sambuc       if (Decl *methodPrototype =
400*f4a2713aSLionel Sambuc           ParseObjCMethodPrototype(MethodImplKind, false))
401*f4a2713aSLionel Sambuc         allMethods.push_back(methodPrototype);
402*f4a2713aSLionel Sambuc       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
403*f4a2713aSLionel Sambuc       // method definitions.
404*f4a2713aSLionel Sambuc       if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {
405*f4a2713aSLionel Sambuc         // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.
406*f4a2713aSLionel Sambuc         SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
407*f4a2713aSLionel Sambuc         if (Tok.is(tok::semi))
408*f4a2713aSLionel Sambuc           ConsumeToken();
409*f4a2713aSLionel Sambuc       }
410*f4a2713aSLionel Sambuc       continue;
411*f4a2713aSLionel Sambuc     }
412*f4a2713aSLionel Sambuc     if (Tok.is(tok::l_paren)) {
413*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_minus_or_plus);
414*f4a2713aSLionel Sambuc       ParseObjCMethodDecl(Tok.getLocation(),
415*f4a2713aSLionel Sambuc                           tok::minus,
416*f4a2713aSLionel Sambuc                           MethodImplKind, false);
417*f4a2713aSLionel Sambuc       continue;
418*f4a2713aSLionel Sambuc     }
419*f4a2713aSLionel Sambuc     // Ignore excess semicolons.
420*f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
421*f4a2713aSLionel Sambuc       ConsumeToken();
422*f4a2713aSLionel Sambuc       continue;
423*f4a2713aSLionel Sambuc     }
424*f4a2713aSLionel Sambuc 
425*f4a2713aSLionel Sambuc     // If we got to the end of the file, exit the loop.
426*f4a2713aSLionel Sambuc     if (Tok.is(tok::eof))
427*f4a2713aSLionel Sambuc       break;
428*f4a2713aSLionel Sambuc 
429*f4a2713aSLionel Sambuc     // Code completion within an Objective-C interface.
430*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
431*f4a2713aSLionel Sambuc       Actions.CodeCompleteOrdinaryName(getCurScope(),
432*f4a2713aSLionel Sambuc                             CurParsedObjCImpl? Sema::PCC_ObjCImplementation
433*f4a2713aSLionel Sambuc                                              : Sema::PCC_ObjCInterface);
434*f4a2713aSLionel Sambuc       return cutOffParsing();
435*f4a2713aSLionel Sambuc     }
436*f4a2713aSLionel Sambuc 
437*f4a2713aSLionel Sambuc     // If we don't have an @ directive, parse it as a function definition.
438*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::at)) {
439*f4a2713aSLionel Sambuc       // The code below does not consume '}'s because it is afraid of eating the
440*f4a2713aSLionel Sambuc       // end of a namespace.  Because of the way this code is structured, an
441*f4a2713aSLionel Sambuc       // erroneous r_brace would cause an infinite loop if not handled here.
442*f4a2713aSLionel Sambuc       if (Tok.is(tok::r_brace))
443*f4a2713aSLionel Sambuc         break;
444*f4a2713aSLionel Sambuc       ParsedAttributesWithRange attrs(AttrFactory);
445*f4a2713aSLionel Sambuc       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
446*f4a2713aSLionel Sambuc       continue;
447*f4a2713aSLionel Sambuc     }
448*f4a2713aSLionel Sambuc 
449*f4a2713aSLionel Sambuc     // Otherwise, we have an @ directive, eat the @.
450*f4a2713aSLionel Sambuc     SourceLocation AtLoc = ConsumeToken(); // the "@"
451*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
452*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCAtDirective(getCurScope());
453*f4a2713aSLionel Sambuc       return cutOffParsing();
454*f4a2713aSLionel Sambuc     }
455*f4a2713aSLionel Sambuc 
456*f4a2713aSLionel Sambuc     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
457*f4a2713aSLionel Sambuc 
458*f4a2713aSLionel Sambuc     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
459*f4a2713aSLionel Sambuc       AtEnd.setBegin(AtLoc);
460*f4a2713aSLionel Sambuc       AtEnd.setEnd(Tok.getLocation());
461*f4a2713aSLionel Sambuc       break;
462*f4a2713aSLionel Sambuc     } else if (DirectiveKind == tok::objc_not_keyword) {
463*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_unknown_at);
464*f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
465*f4a2713aSLionel Sambuc       continue;
466*f4a2713aSLionel Sambuc     }
467*f4a2713aSLionel Sambuc 
468*f4a2713aSLionel Sambuc     // Eat the identifier.
469*f4a2713aSLionel Sambuc     ConsumeToken();
470*f4a2713aSLionel Sambuc 
471*f4a2713aSLionel Sambuc     switch (DirectiveKind) {
472*f4a2713aSLionel Sambuc     default:
473*f4a2713aSLionel Sambuc       // FIXME: If someone forgets an @end on a protocol, this loop will
474*f4a2713aSLionel Sambuc       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
475*f4a2713aSLionel Sambuc       // would probably be better to bail out if we saw an @class or @interface
476*f4a2713aSLionel Sambuc       // or something like that.
477*f4a2713aSLionel Sambuc       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
478*f4a2713aSLionel Sambuc       // Skip until we see an '@' or '}' or ';'.
479*f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, tok::at, StopAtSemi);
480*f4a2713aSLionel Sambuc       break;
481*f4a2713aSLionel Sambuc 
482*f4a2713aSLionel Sambuc     case tok::objc_implementation:
483*f4a2713aSLionel Sambuc     case tok::objc_interface:
484*f4a2713aSLionel Sambuc       Diag(AtLoc, diag::err_objc_missing_end)
485*f4a2713aSLionel Sambuc           << FixItHint::CreateInsertion(AtLoc, "@end\n");
486*f4a2713aSLionel Sambuc       Diag(CDecl->getLocStart(), diag::note_objc_container_start)
487*f4a2713aSLionel Sambuc           << (int) Actions.getObjCContainerKind();
488*f4a2713aSLionel Sambuc       ConsumeToken();
489*f4a2713aSLionel Sambuc       break;
490*f4a2713aSLionel Sambuc 
491*f4a2713aSLionel Sambuc     case tok::objc_required:
492*f4a2713aSLionel Sambuc     case tok::objc_optional:
493*f4a2713aSLionel Sambuc       // This is only valid on protocols.
494*f4a2713aSLionel Sambuc       // FIXME: Should this check for ObjC2 being enabled?
495*f4a2713aSLionel Sambuc       if (contextKey != tok::objc_protocol)
496*f4a2713aSLionel Sambuc         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
497*f4a2713aSLionel Sambuc       else
498*f4a2713aSLionel Sambuc         MethodImplKind = DirectiveKind;
499*f4a2713aSLionel Sambuc       break;
500*f4a2713aSLionel Sambuc 
501*f4a2713aSLionel Sambuc     case tok::objc_property:
502*f4a2713aSLionel Sambuc       if (!getLangOpts().ObjC2)
503*f4a2713aSLionel Sambuc         Diag(AtLoc, diag::err_objc_properties_require_objc2);
504*f4a2713aSLionel Sambuc 
505*f4a2713aSLionel Sambuc       ObjCDeclSpec OCDS;
506*f4a2713aSLionel Sambuc       SourceLocation LParenLoc;
507*f4a2713aSLionel Sambuc       // Parse property attribute list, if any.
508*f4a2713aSLionel Sambuc       if (Tok.is(tok::l_paren)) {
509*f4a2713aSLionel Sambuc         LParenLoc = Tok.getLocation();
510*f4a2713aSLionel Sambuc         ParseObjCPropertyAttribute(OCDS);
511*f4a2713aSLionel Sambuc       }
512*f4a2713aSLionel Sambuc 
513*f4a2713aSLionel Sambuc       ObjCPropertyCallback Callback(*this, allProperties,
514*f4a2713aSLionel Sambuc                                     OCDS, AtLoc, LParenLoc, MethodImplKind);
515*f4a2713aSLionel Sambuc 
516*f4a2713aSLionel Sambuc       // Parse all the comma separated declarators.
517*f4a2713aSLionel Sambuc       ParsingDeclSpec DS(*this);
518*f4a2713aSLionel Sambuc       ParseStructDeclaration(DS, Callback);
519*f4a2713aSLionel Sambuc 
520*f4a2713aSLionel Sambuc       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
521*f4a2713aSLionel Sambuc       break;
522*f4a2713aSLionel Sambuc     }
523*f4a2713aSLionel Sambuc   }
524*f4a2713aSLionel Sambuc 
525*f4a2713aSLionel Sambuc   // We break out of the big loop in two cases: when we see @end or when we see
526*f4a2713aSLionel Sambuc   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
527*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
528*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtDirective(getCurScope());
529*f4a2713aSLionel Sambuc     return cutOffParsing();
530*f4a2713aSLionel Sambuc   } else if (Tok.isObjCAtKeyword(tok::objc_end)) {
531*f4a2713aSLionel Sambuc     ConsumeToken(); // the "end" identifier
532*f4a2713aSLionel Sambuc   } else {
533*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_objc_missing_end)
534*f4a2713aSLionel Sambuc         << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
535*f4a2713aSLionel Sambuc     Diag(CDecl->getLocStart(), diag::note_objc_container_start)
536*f4a2713aSLionel Sambuc         << (int) Actions.getObjCContainerKind();
537*f4a2713aSLionel Sambuc     AtEnd.setBegin(Tok.getLocation());
538*f4a2713aSLionel Sambuc     AtEnd.setEnd(Tok.getLocation());
539*f4a2713aSLionel Sambuc   }
540*f4a2713aSLionel Sambuc 
541*f4a2713aSLionel Sambuc   // Insert collected methods declarations into the @interface object.
542*f4a2713aSLionel Sambuc   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
543*f4a2713aSLionel Sambuc   Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
544*f4a2713aSLionel Sambuc }
545*f4a2713aSLionel Sambuc 
546*f4a2713aSLionel Sambuc ///   Parse property attribute declarations.
547*f4a2713aSLionel Sambuc ///
548*f4a2713aSLionel Sambuc ///   property-attr-decl: '(' property-attrlist ')'
549*f4a2713aSLionel Sambuc ///   property-attrlist:
550*f4a2713aSLionel Sambuc ///     property-attribute
551*f4a2713aSLionel Sambuc ///     property-attrlist ',' property-attribute
552*f4a2713aSLionel Sambuc ///   property-attribute:
553*f4a2713aSLionel Sambuc ///     getter '=' identifier
554*f4a2713aSLionel Sambuc ///     setter '=' identifier ':'
555*f4a2713aSLionel Sambuc ///     readonly
556*f4a2713aSLionel Sambuc ///     readwrite
557*f4a2713aSLionel Sambuc ///     assign
558*f4a2713aSLionel Sambuc ///     retain
559*f4a2713aSLionel Sambuc ///     copy
560*f4a2713aSLionel Sambuc ///     nonatomic
561*f4a2713aSLionel Sambuc ///     atomic
562*f4a2713aSLionel Sambuc ///     strong
563*f4a2713aSLionel Sambuc ///     weak
564*f4a2713aSLionel Sambuc ///     unsafe_unretained
565*f4a2713aSLionel Sambuc ///
566*f4a2713aSLionel Sambuc void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
567*f4a2713aSLionel Sambuc   assert(Tok.getKind() == tok::l_paren);
568*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
569*f4a2713aSLionel Sambuc   T.consumeOpen();
570*f4a2713aSLionel Sambuc 
571*f4a2713aSLionel Sambuc   while (1) {
572*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
573*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
574*f4a2713aSLionel Sambuc       return cutOffParsing();
575*f4a2713aSLionel Sambuc     }
576*f4a2713aSLionel Sambuc     const IdentifierInfo *II = Tok.getIdentifierInfo();
577*f4a2713aSLionel Sambuc 
578*f4a2713aSLionel Sambuc     // If this is not an identifier at all, bail out early.
579*f4a2713aSLionel Sambuc     if (II == 0) {
580*f4a2713aSLionel Sambuc       T.consumeClose();
581*f4a2713aSLionel Sambuc       return;
582*f4a2713aSLionel Sambuc     }
583*f4a2713aSLionel Sambuc 
584*f4a2713aSLionel Sambuc     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
585*f4a2713aSLionel Sambuc 
586*f4a2713aSLionel Sambuc     if (II->isStr("readonly"))
587*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
588*f4a2713aSLionel Sambuc     else if (II->isStr("assign"))
589*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
590*f4a2713aSLionel Sambuc     else if (II->isStr("unsafe_unretained"))
591*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained);
592*f4a2713aSLionel Sambuc     else if (II->isStr("readwrite"))
593*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
594*f4a2713aSLionel Sambuc     else if (II->isStr("retain"))
595*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
596*f4a2713aSLionel Sambuc     else if (II->isStr("strong"))
597*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong);
598*f4a2713aSLionel Sambuc     else if (II->isStr("copy"))
599*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
600*f4a2713aSLionel Sambuc     else if (II->isStr("nonatomic"))
601*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
602*f4a2713aSLionel Sambuc     else if (II->isStr("atomic"))
603*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);
604*f4a2713aSLionel Sambuc     else if (II->isStr("weak"))
605*f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak);
606*f4a2713aSLionel Sambuc     else if (II->isStr("getter") || II->isStr("setter")) {
607*f4a2713aSLionel Sambuc       bool IsSetter = II->getNameStart()[0] == 's';
608*f4a2713aSLionel Sambuc 
609*f4a2713aSLionel Sambuc       // getter/setter require extra treatment.
610*f4a2713aSLionel Sambuc       unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
611*f4a2713aSLionel Sambuc         diag::err_objc_expected_equal_for_getter;
612*f4a2713aSLionel Sambuc 
613*f4a2713aSLionel Sambuc       if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren))
614*f4a2713aSLionel Sambuc         return;
615*f4a2713aSLionel Sambuc 
616*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
617*f4a2713aSLionel Sambuc         if (IsSetter)
618*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCPropertySetter(getCurScope());
619*f4a2713aSLionel Sambuc         else
620*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCPropertyGetter(getCurScope());
621*f4a2713aSLionel Sambuc         return cutOffParsing();
622*f4a2713aSLionel Sambuc       }
623*f4a2713aSLionel Sambuc 
624*f4a2713aSLionel Sambuc 
625*f4a2713aSLionel Sambuc       SourceLocation SelLoc;
626*f4a2713aSLionel Sambuc       IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
627*f4a2713aSLionel Sambuc 
628*f4a2713aSLionel Sambuc       if (!SelIdent) {
629*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
630*f4a2713aSLionel Sambuc           << IsSetter;
631*f4a2713aSLionel Sambuc         SkipUntil(tok::r_paren, StopAtSemi);
632*f4a2713aSLionel Sambuc         return;
633*f4a2713aSLionel Sambuc       }
634*f4a2713aSLionel Sambuc 
635*f4a2713aSLionel Sambuc       if (IsSetter) {
636*f4a2713aSLionel Sambuc         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
637*f4a2713aSLionel Sambuc         DS.setSetterName(SelIdent);
638*f4a2713aSLionel Sambuc 
639*f4a2713aSLionel Sambuc         if (ExpectAndConsume(tok::colon,
640*f4a2713aSLionel Sambuc                              diag::err_expected_colon_after_setter_name, "",
641*f4a2713aSLionel Sambuc                              tok::r_paren))
642*f4a2713aSLionel Sambuc           return;
643*f4a2713aSLionel Sambuc       } else {
644*f4a2713aSLionel Sambuc         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
645*f4a2713aSLionel Sambuc         DS.setGetterName(SelIdent);
646*f4a2713aSLionel Sambuc       }
647*f4a2713aSLionel Sambuc     } else {
648*f4a2713aSLionel Sambuc       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
649*f4a2713aSLionel Sambuc       SkipUntil(tok::r_paren, StopAtSemi);
650*f4a2713aSLionel Sambuc       return;
651*f4a2713aSLionel Sambuc     }
652*f4a2713aSLionel Sambuc 
653*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
654*f4a2713aSLionel Sambuc       break;
655*f4a2713aSLionel Sambuc 
656*f4a2713aSLionel Sambuc     ConsumeToken();
657*f4a2713aSLionel Sambuc   }
658*f4a2713aSLionel Sambuc 
659*f4a2713aSLionel Sambuc   T.consumeClose();
660*f4a2713aSLionel Sambuc }
661*f4a2713aSLionel Sambuc 
662*f4a2713aSLionel Sambuc ///   objc-method-proto:
663*f4a2713aSLionel Sambuc ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
664*f4a2713aSLionel Sambuc ///     objc-class-method objc-method-decl objc-method-attributes[opt]
665*f4a2713aSLionel Sambuc ///
666*f4a2713aSLionel Sambuc ///   objc-instance-method: '-'
667*f4a2713aSLionel Sambuc ///   objc-class-method: '+'
668*f4a2713aSLionel Sambuc ///
669*f4a2713aSLionel Sambuc ///   objc-method-attributes:         [OBJC2]
670*f4a2713aSLionel Sambuc ///     __attribute__((deprecated))
671*f4a2713aSLionel Sambuc ///
672*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
673*f4a2713aSLionel Sambuc                                        bool MethodDefinition) {
674*f4a2713aSLionel Sambuc   assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
675*f4a2713aSLionel Sambuc 
676*f4a2713aSLionel Sambuc   tok::TokenKind methodType = Tok.getKind();
677*f4a2713aSLionel Sambuc   SourceLocation mLoc = ConsumeToken();
678*f4a2713aSLionel Sambuc   Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
679*f4a2713aSLionel Sambuc                                     MethodDefinition);
680*f4a2713aSLionel Sambuc   // Since this rule is used for both method declarations and definitions,
681*f4a2713aSLionel Sambuc   // the caller is (optionally) responsible for consuming the ';'.
682*f4a2713aSLionel Sambuc   return MDecl;
683*f4a2713aSLionel Sambuc }
684*f4a2713aSLionel Sambuc 
685*f4a2713aSLionel Sambuc ///   objc-selector:
686*f4a2713aSLionel Sambuc ///     identifier
687*f4a2713aSLionel Sambuc ///     one of
688*f4a2713aSLionel Sambuc ///       enum struct union if else while do for switch case default
689*f4a2713aSLionel Sambuc ///       break continue return goto asm sizeof typeof __alignof
690*f4a2713aSLionel Sambuc ///       unsigned long const short volatile signed restrict _Complex
691*f4a2713aSLionel Sambuc ///       in out inout bycopy byref oneway int char float double void _Bool
692*f4a2713aSLionel Sambuc ///
693*f4a2713aSLionel Sambuc IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
694*f4a2713aSLionel Sambuc 
695*f4a2713aSLionel Sambuc   switch (Tok.getKind()) {
696*f4a2713aSLionel Sambuc   default:
697*f4a2713aSLionel Sambuc     return 0;
698*f4a2713aSLionel Sambuc   case tok::ampamp:
699*f4a2713aSLionel Sambuc   case tok::ampequal:
700*f4a2713aSLionel Sambuc   case tok::amp:
701*f4a2713aSLionel Sambuc   case tok::pipe:
702*f4a2713aSLionel Sambuc   case tok::tilde:
703*f4a2713aSLionel Sambuc   case tok::exclaim:
704*f4a2713aSLionel Sambuc   case tok::exclaimequal:
705*f4a2713aSLionel Sambuc   case tok::pipepipe:
706*f4a2713aSLionel Sambuc   case tok::pipeequal:
707*f4a2713aSLionel Sambuc   case tok::caret:
708*f4a2713aSLionel Sambuc   case tok::caretequal: {
709*f4a2713aSLionel Sambuc     std::string ThisTok(PP.getSpelling(Tok));
710*f4a2713aSLionel Sambuc     if (isLetter(ThisTok[0])) {
711*f4a2713aSLionel Sambuc       IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data());
712*f4a2713aSLionel Sambuc       Tok.setKind(tok::identifier);
713*f4a2713aSLionel Sambuc       SelectorLoc = ConsumeToken();
714*f4a2713aSLionel Sambuc       return II;
715*f4a2713aSLionel Sambuc     }
716*f4a2713aSLionel Sambuc     return 0;
717*f4a2713aSLionel Sambuc   }
718*f4a2713aSLionel Sambuc 
719*f4a2713aSLionel Sambuc   case tok::identifier:
720*f4a2713aSLionel Sambuc   case tok::kw_asm:
721*f4a2713aSLionel Sambuc   case tok::kw_auto:
722*f4a2713aSLionel Sambuc   case tok::kw_bool:
723*f4a2713aSLionel Sambuc   case tok::kw_break:
724*f4a2713aSLionel Sambuc   case tok::kw_case:
725*f4a2713aSLionel Sambuc   case tok::kw_catch:
726*f4a2713aSLionel Sambuc   case tok::kw_char:
727*f4a2713aSLionel Sambuc   case tok::kw_class:
728*f4a2713aSLionel Sambuc   case tok::kw_const:
729*f4a2713aSLionel Sambuc   case tok::kw_const_cast:
730*f4a2713aSLionel Sambuc   case tok::kw_continue:
731*f4a2713aSLionel Sambuc   case tok::kw_default:
732*f4a2713aSLionel Sambuc   case tok::kw_delete:
733*f4a2713aSLionel Sambuc   case tok::kw_do:
734*f4a2713aSLionel Sambuc   case tok::kw_double:
735*f4a2713aSLionel Sambuc   case tok::kw_dynamic_cast:
736*f4a2713aSLionel Sambuc   case tok::kw_else:
737*f4a2713aSLionel Sambuc   case tok::kw_enum:
738*f4a2713aSLionel Sambuc   case tok::kw_explicit:
739*f4a2713aSLionel Sambuc   case tok::kw_export:
740*f4a2713aSLionel Sambuc   case tok::kw_extern:
741*f4a2713aSLionel Sambuc   case tok::kw_false:
742*f4a2713aSLionel Sambuc   case tok::kw_float:
743*f4a2713aSLionel Sambuc   case tok::kw_for:
744*f4a2713aSLionel Sambuc   case tok::kw_friend:
745*f4a2713aSLionel Sambuc   case tok::kw_goto:
746*f4a2713aSLionel Sambuc   case tok::kw_if:
747*f4a2713aSLionel Sambuc   case tok::kw_inline:
748*f4a2713aSLionel Sambuc   case tok::kw_int:
749*f4a2713aSLionel Sambuc   case tok::kw_long:
750*f4a2713aSLionel Sambuc   case tok::kw_mutable:
751*f4a2713aSLionel Sambuc   case tok::kw_namespace:
752*f4a2713aSLionel Sambuc   case tok::kw_new:
753*f4a2713aSLionel Sambuc   case tok::kw_operator:
754*f4a2713aSLionel Sambuc   case tok::kw_private:
755*f4a2713aSLionel Sambuc   case tok::kw_protected:
756*f4a2713aSLionel Sambuc   case tok::kw_public:
757*f4a2713aSLionel Sambuc   case tok::kw_register:
758*f4a2713aSLionel Sambuc   case tok::kw_reinterpret_cast:
759*f4a2713aSLionel Sambuc   case tok::kw_restrict:
760*f4a2713aSLionel Sambuc   case tok::kw_return:
761*f4a2713aSLionel Sambuc   case tok::kw_short:
762*f4a2713aSLionel Sambuc   case tok::kw_signed:
763*f4a2713aSLionel Sambuc   case tok::kw_sizeof:
764*f4a2713aSLionel Sambuc   case tok::kw_static:
765*f4a2713aSLionel Sambuc   case tok::kw_static_cast:
766*f4a2713aSLionel Sambuc   case tok::kw_struct:
767*f4a2713aSLionel Sambuc   case tok::kw_switch:
768*f4a2713aSLionel Sambuc   case tok::kw_template:
769*f4a2713aSLionel Sambuc   case tok::kw_this:
770*f4a2713aSLionel Sambuc   case tok::kw_throw:
771*f4a2713aSLionel Sambuc   case tok::kw_true:
772*f4a2713aSLionel Sambuc   case tok::kw_try:
773*f4a2713aSLionel Sambuc   case tok::kw_typedef:
774*f4a2713aSLionel Sambuc   case tok::kw_typeid:
775*f4a2713aSLionel Sambuc   case tok::kw_typename:
776*f4a2713aSLionel Sambuc   case tok::kw_typeof:
777*f4a2713aSLionel Sambuc   case tok::kw_union:
778*f4a2713aSLionel Sambuc   case tok::kw_unsigned:
779*f4a2713aSLionel Sambuc   case tok::kw_using:
780*f4a2713aSLionel Sambuc   case tok::kw_virtual:
781*f4a2713aSLionel Sambuc   case tok::kw_void:
782*f4a2713aSLionel Sambuc   case tok::kw_volatile:
783*f4a2713aSLionel Sambuc   case tok::kw_wchar_t:
784*f4a2713aSLionel Sambuc   case tok::kw_while:
785*f4a2713aSLionel Sambuc   case tok::kw__Bool:
786*f4a2713aSLionel Sambuc   case tok::kw__Complex:
787*f4a2713aSLionel Sambuc   case tok::kw___alignof:
788*f4a2713aSLionel Sambuc     IdentifierInfo *II = Tok.getIdentifierInfo();
789*f4a2713aSLionel Sambuc     SelectorLoc = ConsumeToken();
790*f4a2713aSLionel Sambuc     return II;
791*f4a2713aSLionel Sambuc   }
792*f4a2713aSLionel Sambuc }
793*f4a2713aSLionel Sambuc 
794*f4a2713aSLionel Sambuc ///  objc-for-collection-in: 'in'
795*f4a2713aSLionel Sambuc ///
796*f4a2713aSLionel Sambuc bool Parser::isTokIdentifier_in() const {
797*f4a2713aSLionel Sambuc   // FIXME: May have to do additional look-ahead to only allow for
798*f4a2713aSLionel Sambuc   // valid tokens following an 'in'; such as an identifier, unary operators,
799*f4a2713aSLionel Sambuc   // '[' etc.
800*f4a2713aSLionel Sambuc   return (getLangOpts().ObjC2 && Tok.is(tok::identifier) &&
801*f4a2713aSLionel Sambuc           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
802*f4a2713aSLionel Sambuc }
803*f4a2713aSLionel Sambuc 
804*f4a2713aSLionel Sambuc /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
805*f4a2713aSLionel Sambuc /// qualifier list and builds their bitmask representation in the input
806*f4a2713aSLionel Sambuc /// argument.
807*f4a2713aSLionel Sambuc ///
808*f4a2713aSLionel Sambuc ///   objc-type-qualifiers:
809*f4a2713aSLionel Sambuc ///     objc-type-qualifier
810*f4a2713aSLionel Sambuc ///     objc-type-qualifiers objc-type-qualifier
811*f4a2713aSLionel Sambuc ///
812*f4a2713aSLionel Sambuc void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
813*f4a2713aSLionel Sambuc                                         Declarator::TheContext Context) {
814*f4a2713aSLionel Sambuc   assert(Context == Declarator::ObjCParameterContext ||
815*f4a2713aSLionel Sambuc          Context == Declarator::ObjCResultContext);
816*f4a2713aSLionel Sambuc 
817*f4a2713aSLionel Sambuc   while (1) {
818*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
819*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
820*f4a2713aSLionel Sambuc                           Context == Declarator::ObjCParameterContext);
821*f4a2713aSLionel Sambuc       return cutOffParsing();
822*f4a2713aSLionel Sambuc     }
823*f4a2713aSLionel Sambuc 
824*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier))
825*f4a2713aSLionel Sambuc       return;
826*f4a2713aSLionel Sambuc 
827*f4a2713aSLionel Sambuc     const IdentifierInfo *II = Tok.getIdentifierInfo();
828*f4a2713aSLionel Sambuc     for (unsigned i = 0; i != objc_NumQuals; ++i) {
829*f4a2713aSLionel Sambuc       if (II != ObjCTypeQuals[i])
830*f4a2713aSLionel Sambuc         continue;
831*f4a2713aSLionel Sambuc 
832*f4a2713aSLionel Sambuc       ObjCDeclSpec::ObjCDeclQualifier Qual;
833*f4a2713aSLionel Sambuc       switch (i) {
834*f4a2713aSLionel Sambuc       default: llvm_unreachable("Unknown decl qualifier");
835*f4a2713aSLionel Sambuc       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
836*f4a2713aSLionel Sambuc       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
837*f4a2713aSLionel Sambuc       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
838*f4a2713aSLionel Sambuc       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
839*f4a2713aSLionel Sambuc       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
840*f4a2713aSLionel Sambuc       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
841*f4a2713aSLionel Sambuc       }
842*f4a2713aSLionel Sambuc       DS.setObjCDeclQualifier(Qual);
843*f4a2713aSLionel Sambuc       ConsumeToken();
844*f4a2713aSLionel Sambuc       II = 0;
845*f4a2713aSLionel Sambuc       break;
846*f4a2713aSLionel Sambuc     }
847*f4a2713aSLionel Sambuc 
848*f4a2713aSLionel Sambuc     // If this wasn't a recognized qualifier, bail out.
849*f4a2713aSLionel Sambuc     if (II) return;
850*f4a2713aSLionel Sambuc   }
851*f4a2713aSLionel Sambuc }
852*f4a2713aSLionel Sambuc 
853*f4a2713aSLionel Sambuc /// Take all the decl attributes out of the given list and add
854*f4a2713aSLionel Sambuc /// them to the given attribute set.
855*f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs,
856*f4a2713aSLionel Sambuc                                AttributeList *list) {
857*f4a2713aSLionel Sambuc   while (list) {
858*f4a2713aSLionel Sambuc     AttributeList *cur = list;
859*f4a2713aSLionel Sambuc     list = cur->getNext();
860*f4a2713aSLionel Sambuc 
861*f4a2713aSLionel Sambuc     if (!cur->isUsedAsTypeAttr()) {
862*f4a2713aSLionel Sambuc       // Clear out the next pointer.  We're really completely
863*f4a2713aSLionel Sambuc       // destroying the internal invariants of the declarator here,
864*f4a2713aSLionel Sambuc       // but it doesn't matter because we're done with it.
865*f4a2713aSLionel Sambuc       cur->setNext(0);
866*f4a2713aSLionel Sambuc       attrs.add(cur);
867*f4a2713aSLionel Sambuc     }
868*f4a2713aSLionel Sambuc   }
869*f4a2713aSLionel Sambuc }
870*f4a2713aSLionel Sambuc 
871*f4a2713aSLionel Sambuc /// takeDeclAttributes - Take all the decl attributes from the given
872*f4a2713aSLionel Sambuc /// declarator and add them to the given list.
873*f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs,
874*f4a2713aSLionel Sambuc                                Declarator &D) {
875*f4a2713aSLionel Sambuc   // First, take ownership of all attributes.
876*f4a2713aSLionel Sambuc   attrs.getPool().takeAllFrom(D.getAttributePool());
877*f4a2713aSLionel Sambuc   attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
878*f4a2713aSLionel Sambuc 
879*f4a2713aSLionel Sambuc   // Now actually move the attributes over.
880*f4a2713aSLionel Sambuc   takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList());
881*f4a2713aSLionel Sambuc   takeDeclAttributes(attrs, D.getAttributes());
882*f4a2713aSLionel Sambuc   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
883*f4a2713aSLionel Sambuc     takeDeclAttributes(attrs,
884*f4a2713aSLionel Sambuc                   const_cast<AttributeList*>(D.getTypeObject(i).getAttrs()));
885*f4a2713aSLionel Sambuc }
886*f4a2713aSLionel Sambuc 
887*f4a2713aSLionel Sambuc ///   objc-type-name:
888*f4a2713aSLionel Sambuc ///     '(' objc-type-qualifiers[opt] type-name ')'
889*f4a2713aSLionel Sambuc ///     '(' objc-type-qualifiers[opt] ')'
890*f4a2713aSLionel Sambuc ///
891*f4a2713aSLionel Sambuc ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
892*f4a2713aSLionel Sambuc                                      Declarator::TheContext context,
893*f4a2713aSLionel Sambuc                                      ParsedAttributes *paramAttrs) {
894*f4a2713aSLionel Sambuc   assert(context == Declarator::ObjCParameterContext ||
895*f4a2713aSLionel Sambuc          context == Declarator::ObjCResultContext);
896*f4a2713aSLionel Sambuc   assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext));
897*f4a2713aSLionel Sambuc 
898*f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_paren) && "expected (");
899*f4a2713aSLionel Sambuc 
900*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
901*f4a2713aSLionel Sambuc   T.consumeOpen();
902*f4a2713aSLionel Sambuc 
903*f4a2713aSLionel Sambuc   SourceLocation TypeStartLoc = Tok.getLocation();
904*f4a2713aSLionel Sambuc   ObjCDeclContextSwitch ObjCDC(*this);
905*f4a2713aSLionel Sambuc 
906*f4a2713aSLionel Sambuc   // Parse type qualifiers, in, inout, etc.
907*f4a2713aSLionel Sambuc   ParseObjCTypeQualifierList(DS, context);
908*f4a2713aSLionel Sambuc 
909*f4a2713aSLionel Sambuc   ParsedType Ty;
910*f4a2713aSLionel Sambuc   if (isTypeSpecifierQualifier()) {
911*f4a2713aSLionel Sambuc     // Parse an abstract declarator.
912*f4a2713aSLionel Sambuc     DeclSpec declSpec(AttrFactory);
913*f4a2713aSLionel Sambuc     declSpec.setObjCQualifiers(&DS);
914*f4a2713aSLionel Sambuc     ParseSpecifierQualifierList(declSpec);
915*f4a2713aSLionel Sambuc     declSpec.SetRangeEnd(Tok.getLocation());
916*f4a2713aSLionel Sambuc     Declarator declarator(declSpec, context);
917*f4a2713aSLionel Sambuc     ParseDeclarator(declarator);
918*f4a2713aSLionel Sambuc 
919*f4a2713aSLionel Sambuc     // If that's not invalid, extract a type.
920*f4a2713aSLionel Sambuc     if (!declarator.isInvalidType()) {
921*f4a2713aSLionel Sambuc       TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
922*f4a2713aSLionel Sambuc       if (!type.isInvalid())
923*f4a2713aSLionel Sambuc         Ty = type.get();
924*f4a2713aSLionel Sambuc 
925*f4a2713aSLionel Sambuc       // If we're parsing a parameter, steal all the decl attributes
926*f4a2713aSLionel Sambuc       // and add them to the decl spec.
927*f4a2713aSLionel Sambuc       if (context == Declarator::ObjCParameterContext)
928*f4a2713aSLionel Sambuc         takeDeclAttributes(*paramAttrs, declarator);
929*f4a2713aSLionel Sambuc     }
930*f4a2713aSLionel Sambuc   } else if (context == Declarator::ObjCResultContext &&
931*f4a2713aSLionel Sambuc              Tok.is(tok::identifier)) {
932*f4a2713aSLionel Sambuc     if (!Ident_instancetype)
933*f4a2713aSLionel Sambuc       Ident_instancetype = PP.getIdentifierInfo("instancetype");
934*f4a2713aSLionel Sambuc 
935*f4a2713aSLionel Sambuc     if (Tok.getIdentifierInfo() == Ident_instancetype) {
936*f4a2713aSLionel Sambuc       Ty = Actions.ActOnObjCInstanceType(Tok.getLocation());
937*f4a2713aSLionel Sambuc       ConsumeToken();
938*f4a2713aSLionel Sambuc     }
939*f4a2713aSLionel Sambuc   }
940*f4a2713aSLionel Sambuc 
941*f4a2713aSLionel Sambuc   if (Tok.is(tok::r_paren))
942*f4a2713aSLionel Sambuc     T.consumeClose();
943*f4a2713aSLionel Sambuc   else if (Tok.getLocation() == TypeStartLoc) {
944*f4a2713aSLionel Sambuc     // If we didn't eat any tokens, then this isn't a type.
945*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_type);
946*f4a2713aSLionel Sambuc     SkipUntil(tok::r_paren, StopAtSemi);
947*f4a2713aSLionel Sambuc   } else {
948*f4a2713aSLionel Sambuc     // Otherwise, we found *something*, but didn't get a ')' in the right
949*f4a2713aSLionel Sambuc     // place.  Emit an error then return what we have as the type.
950*f4a2713aSLionel Sambuc     T.consumeClose();
951*f4a2713aSLionel Sambuc   }
952*f4a2713aSLionel Sambuc   return Ty;
953*f4a2713aSLionel Sambuc }
954*f4a2713aSLionel Sambuc 
955*f4a2713aSLionel Sambuc ///   objc-method-decl:
956*f4a2713aSLionel Sambuc ///     objc-selector
957*f4a2713aSLionel Sambuc ///     objc-keyword-selector objc-parmlist[opt]
958*f4a2713aSLionel Sambuc ///     objc-type-name objc-selector
959*f4a2713aSLionel Sambuc ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
960*f4a2713aSLionel Sambuc ///
961*f4a2713aSLionel Sambuc ///   objc-keyword-selector:
962*f4a2713aSLionel Sambuc ///     objc-keyword-decl
963*f4a2713aSLionel Sambuc ///     objc-keyword-selector objc-keyword-decl
964*f4a2713aSLionel Sambuc ///
965*f4a2713aSLionel Sambuc ///   objc-keyword-decl:
966*f4a2713aSLionel Sambuc ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
967*f4a2713aSLionel Sambuc ///     objc-selector ':' objc-keyword-attributes[opt] identifier
968*f4a2713aSLionel Sambuc ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
969*f4a2713aSLionel Sambuc ///     ':' objc-keyword-attributes[opt] identifier
970*f4a2713aSLionel Sambuc ///
971*f4a2713aSLionel Sambuc ///   objc-parmlist:
972*f4a2713aSLionel Sambuc ///     objc-parms objc-ellipsis[opt]
973*f4a2713aSLionel Sambuc ///
974*f4a2713aSLionel Sambuc ///   objc-parms:
975*f4a2713aSLionel Sambuc ///     objc-parms , parameter-declaration
976*f4a2713aSLionel Sambuc ///
977*f4a2713aSLionel Sambuc ///   objc-ellipsis:
978*f4a2713aSLionel Sambuc ///     , ...
979*f4a2713aSLionel Sambuc ///
980*f4a2713aSLionel Sambuc ///   objc-keyword-attributes:         [OBJC2]
981*f4a2713aSLionel Sambuc ///     __attribute__((unused))
982*f4a2713aSLionel Sambuc ///
983*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
984*f4a2713aSLionel Sambuc                                   tok::TokenKind mType,
985*f4a2713aSLionel Sambuc                                   tok::ObjCKeywordKind MethodImplKind,
986*f4a2713aSLionel Sambuc                                   bool MethodDefinition) {
987*f4a2713aSLionel Sambuc   ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
988*f4a2713aSLionel Sambuc 
989*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
990*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
991*f4a2713aSLionel Sambuc                                        /*ReturnType=*/ ParsedType());
992*f4a2713aSLionel Sambuc     cutOffParsing();
993*f4a2713aSLionel Sambuc     return 0;
994*f4a2713aSLionel Sambuc   }
995*f4a2713aSLionel Sambuc 
996*f4a2713aSLionel Sambuc   // Parse the return type if present.
997*f4a2713aSLionel Sambuc   ParsedType ReturnType;
998*f4a2713aSLionel Sambuc   ObjCDeclSpec DSRet;
999*f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren))
1000*f4a2713aSLionel Sambuc     ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0);
1001*f4a2713aSLionel Sambuc 
1002*f4a2713aSLionel Sambuc   // If attributes exist before the method, parse them.
1003*f4a2713aSLionel Sambuc   ParsedAttributes methodAttrs(AttrFactory);
1004*f4a2713aSLionel Sambuc   if (getLangOpts().ObjC2)
1005*f4a2713aSLionel Sambuc     MaybeParseGNUAttributes(methodAttrs);
1006*f4a2713aSLionel Sambuc 
1007*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
1008*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
1009*f4a2713aSLionel Sambuc                                        ReturnType);
1010*f4a2713aSLionel Sambuc     cutOffParsing();
1011*f4a2713aSLionel Sambuc     return 0;
1012*f4a2713aSLionel Sambuc   }
1013*f4a2713aSLionel Sambuc 
1014*f4a2713aSLionel Sambuc   // Now parse the selector.
1015*f4a2713aSLionel Sambuc   SourceLocation selLoc;
1016*f4a2713aSLionel Sambuc   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
1017*f4a2713aSLionel Sambuc 
1018*f4a2713aSLionel Sambuc   // An unnamed colon is valid.
1019*f4a2713aSLionel Sambuc   if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
1020*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_selector_for_method)
1021*f4a2713aSLionel Sambuc       << SourceRange(mLoc, Tok.getLocation());
1022*f4a2713aSLionel Sambuc     // Skip until we get a ; or @.
1023*f4a2713aSLionel Sambuc     SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
1024*f4a2713aSLionel Sambuc     return 0;
1025*f4a2713aSLionel Sambuc   }
1026*f4a2713aSLionel Sambuc 
1027*f4a2713aSLionel Sambuc   SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
1028*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::colon)) {
1029*f4a2713aSLionel Sambuc     // If attributes exist after the method, parse them.
1030*f4a2713aSLionel Sambuc     if (getLangOpts().ObjC2)
1031*f4a2713aSLionel Sambuc       MaybeParseGNUAttributes(methodAttrs);
1032*f4a2713aSLionel Sambuc 
1033*f4a2713aSLionel Sambuc     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
1034*f4a2713aSLionel Sambuc     Decl *Result
1035*f4a2713aSLionel Sambuc          = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
1036*f4a2713aSLionel Sambuc                                           mType, DSRet, ReturnType,
1037*f4a2713aSLionel Sambuc                                           selLoc, Sel, 0,
1038*f4a2713aSLionel Sambuc                                           CParamInfo.data(), CParamInfo.size(),
1039*f4a2713aSLionel Sambuc                                           methodAttrs.getList(), MethodImplKind,
1040*f4a2713aSLionel Sambuc                                           false, MethodDefinition);
1041*f4a2713aSLionel Sambuc     PD.complete(Result);
1042*f4a2713aSLionel Sambuc     return Result;
1043*f4a2713aSLionel Sambuc   }
1044*f4a2713aSLionel Sambuc 
1045*f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
1046*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 12> KeyLocs;
1047*f4a2713aSLionel Sambuc   SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
1048*f4a2713aSLionel Sambuc   ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
1049*f4a2713aSLionel Sambuc                             Scope::FunctionDeclarationScope | Scope::DeclScope);
1050*f4a2713aSLionel Sambuc 
1051*f4a2713aSLionel Sambuc   AttributePool allParamAttrs(AttrFactory);
1052*f4a2713aSLionel Sambuc   while (1) {
1053*f4a2713aSLionel Sambuc     ParsedAttributes paramAttrs(AttrFactory);
1054*f4a2713aSLionel Sambuc     Sema::ObjCArgInfo ArgInfo;
1055*f4a2713aSLionel Sambuc 
1056*f4a2713aSLionel Sambuc     // Each iteration parses a single keyword argument.
1057*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::colon)) {
1058*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_colon);
1059*f4a2713aSLionel Sambuc       break;
1060*f4a2713aSLionel Sambuc     }
1061*f4a2713aSLionel Sambuc     ConsumeToken(); // Eat the ':'.
1062*f4a2713aSLionel Sambuc 
1063*f4a2713aSLionel Sambuc     ArgInfo.Type = ParsedType();
1064*f4a2713aSLionel Sambuc     if (Tok.is(tok::l_paren)) // Parse the argument type if present.
1065*f4a2713aSLionel Sambuc       ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
1066*f4a2713aSLionel Sambuc                                        Declarator::ObjCParameterContext,
1067*f4a2713aSLionel Sambuc                                        &paramAttrs);
1068*f4a2713aSLionel Sambuc 
1069*f4a2713aSLionel Sambuc     // If attributes exist before the argument name, parse them.
1070*f4a2713aSLionel Sambuc     // Regardless, collect all the attributes we've parsed so far.
1071*f4a2713aSLionel Sambuc     ArgInfo.ArgAttrs = 0;
1072*f4a2713aSLionel Sambuc     if (getLangOpts().ObjC2) {
1073*f4a2713aSLionel Sambuc       MaybeParseGNUAttributes(paramAttrs);
1074*f4a2713aSLionel Sambuc       ArgInfo.ArgAttrs = paramAttrs.getList();
1075*f4a2713aSLionel Sambuc     }
1076*f4a2713aSLionel Sambuc 
1077*f4a2713aSLionel Sambuc     // Code completion for the next piece of the selector.
1078*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1079*f4a2713aSLionel Sambuc       KeyIdents.push_back(SelIdent);
1080*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
1081*f4a2713aSLionel Sambuc                                                  mType == tok::minus,
1082*f4a2713aSLionel Sambuc                                                  /*AtParameterName=*/true,
1083*f4a2713aSLionel Sambuc                                                  ReturnType, KeyIdents);
1084*f4a2713aSLionel Sambuc       cutOffParsing();
1085*f4a2713aSLionel Sambuc       return 0;
1086*f4a2713aSLionel Sambuc     }
1087*f4a2713aSLionel Sambuc 
1088*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1089*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident); // missing argument name.
1090*f4a2713aSLionel Sambuc       break;
1091*f4a2713aSLionel Sambuc     }
1092*f4a2713aSLionel Sambuc 
1093*f4a2713aSLionel Sambuc     ArgInfo.Name = Tok.getIdentifierInfo();
1094*f4a2713aSLionel Sambuc     ArgInfo.NameLoc = Tok.getLocation();
1095*f4a2713aSLionel Sambuc     ConsumeToken(); // Eat the identifier.
1096*f4a2713aSLionel Sambuc 
1097*f4a2713aSLionel Sambuc     ArgInfos.push_back(ArgInfo);
1098*f4a2713aSLionel Sambuc     KeyIdents.push_back(SelIdent);
1099*f4a2713aSLionel Sambuc     KeyLocs.push_back(selLoc);
1100*f4a2713aSLionel Sambuc 
1101*f4a2713aSLionel Sambuc     // Make sure the attributes persist.
1102*f4a2713aSLionel Sambuc     allParamAttrs.takeAllFrom(paramAttrs.getPool());
1103*f4a2713aSLionel Sambuc 
1104*f4a2713aSLionel Sambuc     // Code completion for the next piece of the selector.
1105*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1106*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
1107*f4a2713aSLionel Sambuc                                                  mType == tok::minus,
1108*f4a2713aSLionel Sambuc                                                  /*AtParameterName=*/false,
1109*f4a2713aSLionel Sambuc                                                  ReturnType, KeyIdents);
1110*f4a2713aSLionel Sambuc       cutOffParsing();
1111*f4a2713aSLionel Sambuc       return 0;
1112*f4a2713aSLionel Sambuc     }
1113*f4a2713aSLionel Sambuc 
1114*f4a2713aSLionel Sambuc     // Check for another keyword selector.
1115*f4a2713aSLionel Sambuc     SelIdent = ParseObjCSelectorPiece(selLoc);
1116*f4a2713aSLionel Sambuc     if (!SelIdent && Tok.isNot(tok::colon))
1117*f4a2713aSLionel Sambuc       break;
1118*f4a2713aSLionel Sambuc     if (!SelIdent) {
1119*f4a2713aSLionel Sambuc       SourceLocation ColonLoc = Tok.getLocation();
1120*f4a2713aSLionel Sambuc       if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {
1121*f4a2713aSLionel Sambuc         Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;
1122*f4a2713aSLionel Sambuc         Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;
1123*f4a2713aSLionel Sambuc         Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;
1124*f4a2713aSLionel Sambuc       }
1125*f4a2713aSLionel Sambuc     }
1126*f4a2713aSLionel Sambuc     // We have a selector or a colon, continue parsing.
1127*f4a2713aSLionel Sambuc   }
1128*f4a2713aSLionel Sambuc 
1129*f4a2713aSLionel Sambuc   bool isVariadic = false;
1130*f4a2713aSLionel Sambuc   bool cStyleParamWarned = false;
1131*f4a2713aSLionel Sambuc   // Parse the (optional) parameter list.
1132*f4a2713aSLionel Sambuc   while (Tok.is(tok::comma)) {
1133*f4a2713aSLionel Sambuc     ConsumeToken();
1134*f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis)) {
1135*f4a2713aSLionel Sambuc       isVariadic = true;
1136*f4a2713aSLionel Sambuc       ConsumeToken();
1137*f4a2713aSLionel Sambuc       break;
1138*f4a2713aSLionel Sambuc     }
1139*f4a2713aSLionel Sambuc     if (!cStyleParamWarned) {
1140*f4a2713aSLionel Sambuc       Diag(Tok, diag::warn_cstyle_param);
1141*f4a2713aSLionel Sambuc       cStyleParamWarned = true;
1142*f4a2713aSLionel Sambuc     }
1143*f4a2713aSLionel Sambuc     DeclSpec DS(AttrFactory);
1144*f4a2713aSLionel Sambuc     ParseDeclarationSpecifiers(DS);
1145*f4a2713aSLionel Sambuc     // Parse the declarator.
1146*f4a2713aSLionel Sambuc     Declarator ParmDecl(DS, Declarator::PrototypeContext);
1147*f4a2713aSLionel Sambuc     ParseDeclarator(ParmDecl);
1148*f4a2713aSLionel Sambuc     IdentifierInfo *ParmII = ParmDecl.getIdentifier();
1149*f4a2713aSLionel Sambuc     Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
1150*f4a2713aSLionel Sambuc     CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
1151*f4a2713aSLionel Sambuc                                                     ParmDecl.getIdentifierLoc(),
1152*f4a2713aSLionel Sambuc                                                     Param,
1153*f4a2713aSLionel Sambuc                                                    0));
1154*f4a2713aSLionel Sambuc   }
1155*f4a2713aSLionel Sambuc 
1156*f4a2713aSLionel Sambuc   // FIXME: Add support for optional parameter list...
1157*f4a2713aSLionel Sambuc   // If attributes exist after the method, parse them.
1158*f4a2713aSLionel Sambuc   if (getLangOpts().ObjC2)
1159*f4a2713aSLionel Sambuc     MaybeParseGNUAttributes(methodAttrs);
1160*f4a2713aSLionel Sambuc 
1161*f4a2713aSLionel Sambuc   if (KeyIdents.size() == 0)
1162*f4a2713aSLionel Sambuc     return 0;
1163*f4a2713aSLionel Sambuc 
1164*f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
1165*f4a2713aSLionel Sambuc                                                    &KeyIdents[0]);
1166*f4a2713aSLionel Sambuc   Decl *Result
1167*f4a2713aSLionel Sambuc        = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
1168*f4a2713aSLionel Sambuc                                         mType, DSRet, ReturnType,
1169*f4a2713aSLionel Sambuc                                         KeyLocs, Sel, &ArgInfos[0],
1170*f4a2713aSLionel Sambuc                                         CParamInfo.data(), CParamInfo.size(),
1171*f4a2713aSLionel Sambuc                                         methodAttrs.getList(),
1172*f4a2713aSLionel Sambuc                                         MethodImplKind, isVariadic, MethodDefinition);
1173*f4a2713aSLionel Sambuc 
1174*f4a2713aSLionel Sambuc   PD.complete(Result);
1175*f4a2713aSLionel Sambuc   return Result;
1176*f4a2713aSLionel Sambuc }
1177*f4a2713aSLionel Sambuc 
1178*f4a2713aSLionel Sambuc ///   objc-protocol-refs:
1179*f4a2713aSLionel Sambuc ///     '<' identifier-list '>'
1180*f4a2713aSLionel Sambuc ///
1181*f4a2713aSLionel Sambuc bool Parser::
1182*f4a2713aSLionel Sambuc ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
1183*f4a2713aSLionel Sambuc                             SmallVectorImpl<SourceLocation> &ProtocolLocs,
1184*f4a2713aSLionel Sambuc                             bool WarnOnDeclarations,
1185*f4a2713aSLionel Sambuc                             SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
1186*f4a2713aSLionel Sambuc   assert(Tok.is(tok::less) && "expected <");
1187*f4a2713aSLionel Sambuc 
1188*f4a2713aSLionel Sambuc   LAngleLoc = ConsumeToken(); // the "<"
1189*f4a2713aSLionel Sambuc 
1190*f4a2713aSLionel Sambuc   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
1191*f4a2713aSLionel Sambuc 
1192*f4a2713aSLionel Sambuc   while (1) {
1193*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1194*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
1195*f4a2713aSLionel Sambuc                                                  ProtocolIdents.size());
1196*f4a2713aSLionel Sambuc       cutOffParsing();
1197*f4a2713aSLionel Sambuc       return true;
1198*f4a2713aSLionel Sambuc     }
1199*f4a2713aSLionel Sambuc 
1200*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1201*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident);
1202*f4a2713aSLionel Sambuc       SkipUntil(tok::greater, StopAtSemi);
1203*f4a2713aSLionel Sambuc       return true;
1204*f4a2713aSLionel Sambuc     }
1205*f4a2713aSLionel Sambuc     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
1206*f4a2713aSLionel Sambuc                                        Tok.getLocation()));
1207*f4a2713aSLionel Sambuc     ProtocolLocs.push_back(Tok.getLocation());
1208*f4a2713aSLionel Sambuc     ConsumeToken();
1209*f4a2713aSLionel Sambuc 
1210*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
1211*f4a2713aSLionel Sambuc       break;
1212*f4a2713aSLionel Sambuc     ConsumeToken();
1213*f4a2713aSLionel Sambuc   }
1214*f4a2713aSLionel Sambuc 
1215*f4a2713aSLionel Sambuc   // Consume the '>'.
1216*f4a2713aSLionel Sambuc   if (ParseGreaterThanInTemplateList(EndLoc, /*ConsumeLastToken=*/true))
1217*f4a2713aSLionel Sambuc     return true;
1218*f4a2713aSLionel Sambuc 
1219*f4a2713aSLionel Sambuc   // Convert the list of protocols identifiers into a list of protocol decls.
1220*f4a2713aSLionel Sambuc   Actions.FindProtocolDeclaration(WarnOnDeclarations,
1221*f4a2713aSLionel Sambuc                                   &ProtocolIdents[0], ProtocolIdents.size(),
1222*f4a2713aSLionel Sambuc                                   Protocols);
1223*f4a2713aSLionel Sambuc   return false;
1224*f4a2713aSLionel Sambuc }
1225*f4a2713aSLionel Sambuc 
1226*f4a2713aSLionel Sambuc /// \brief Parse the Objective-C protocol qualifiers that follow a typename
1227*f4a2713aSLionel Sambuc /// in a decl-specifier-seq, starting at the '<'.
1228*f4a2713aSLionel Sambuc bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
1229*f4a2713aSLionel Sambuc   assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
1230*f4a2713aSLionel Sambuc   assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C");
1231*f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
1232*f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolDecl;
1233*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
1234*f4a2713aSLionel Sambuc   bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1235*f4a2713aSLionel Sambuc                                             LAngleLoc, EndProtoLoc);
1236*f4a2713aSLionel Sambuc   DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1237*f4a2713aSLionel Sambuc                            ProtocolLocs.data(), LAngleLoc);
1238*f4a2713aSLionel Sambuc   if (EndProtoLoc.isValid())
1239*f4a2713aSLionel Sambuc     DS.SetRangeEnd(EndProtoLoc);
1240*f4a2713aSLionel Sambuc   return Result;
1241*f4a2713aSLionel Sambuc }
1242*f4a2713aSLionel Sambuc 
1243*f4a2713aSLionel Sambuc void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
1244*f4a2713aSLionel Sambuc                                  BalancedDelimiterTracker &T,
1245*f4a2713aSLionel Sambuc                                  SmallVectorImpl<Decl *> &AllIvarDecls,
1246*f4a2713aSLionel Sambuc                                  bool RBraceMissing) {
1247*f4a2713aSLionel Sambuc   if (!RBraceMissing)
1248*f4a2713aSLionel Sambuc     T.consumeClose();
1249*f4a2713aSLionel Sambuc 
1250*f4a2713aSLionel Sambuc   Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
1251*f4a2713aSLionel Sambuc   Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
1252*f4a2713aSLionel Sambuc   Actions.ActOnObjCContainerFinishDefinition();
1253*f4a2713aSLionel Sambuc   // Call ActOnFields() even if we don't have any decls. This is useful
1254*f4a2713aSLionel Sambuc   // for code rewriting tools that need to be aware of the empty list.
1255*f4a2713aSLionel Sambuc   Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
1256*f4a2713aSLionel Sambuc                       AllIvarDecls,
1257*f4a2713aSLionel Sambuc                       T.getOpenLocation(), T.getCloseLocation(), 0);
1258*f4a2713aSLionel Sambuc }
1259*f4a2713aSLionel Sambuc 
1260*f4a2713aSLionel Sambuc ///   objc-class-instance-variables:
1261*f4a2713aSLionel Sambuc ///     '{' objc-instance-variable-decl-list[opt] '}'
1262*f4a2713aSLionel Sambuc ///
1263*f4a2713aSLionel Sambuc ///   objc-instance-variable-decl-list:
1264*f4a2713aSLionel Sambuc ///     objc-visibility-spec
1265*f4a2713aSLionel Sambuc ///     objc-instance-variable-decl ';'
1266*f4a2713aSLionel Sambuc ///     ';'
1267*f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list objc-visibility-spec
1268*f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
1269*f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list ';'
1270*f4a2713aSLionel Sambuc ///
1271*f4a2713aSLionel Sambuc ///   objc-visibility-spec:
1272*f4a2713aSLionel Sambuc ///     @private
1273*f4a2713aSLionel Sambuc ///     @protected
1274*f4a2713aSLionel Sambuc ///     @public
1275*f4a2713aSLionel Sambuc ///     @package [OBJC2]
1276*f4a2713aSLionel Sambuc ///
1277*f4a2713aSLionel Sambuc ///   objc-instance-variable-decl:
1278*f4a2713aSLionel Sambuc ///     struct-declaration
1279*f4a2713aSLionel Sambuc ///
1280*f4a2713aSLionel Sambuc void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
1281*f4a2713aSLionel Sambuc                                              tok::ObjCKeywordKind visibility,
1282*f4a2713aSLionel Sambuc                                              SourceLocation atLoc) {
1283*f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_brace) && "expected {");
1284*f4a2713aSLionel Sambuc   SmallVector<Decl *, 32> AllIvarDecls;
1285*f4a2713aSLionel Sambuc 
1286*f4a2713aSLionel Sambuc   ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
1287*f4a2713aSLionel Sambuc   ObjCDeclContextSwitch ObjCDC(*this);
1288*f4a2713aSLionel Sambuc 
1289*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_brace);
1290*f4a2713aSLionel Sambuc   T.consumeOpen();
1291*f4a2713aSLionel Sambuc   // While we still have something to read, read the instance variables.
1292*f4a2713aSLionel Sambuc   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
1293*f4a2713aSLionel Sambuc     // Each iteration of this loop reads one objc-instance-variable-decl.
1294*f4a2713aSLionel Sambuc 
1295*f4a2713aSLionel Sambuc     // Check for extraneous top-level semicolon.
1296*f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
1297*f4a2713aSLionel Sambuc       ConsumeExtraSemi(InstanceVariableList);
1298*f4a2713aSLionel Sambuc       continue;
1299*f4a2713aSLionel Sambuc     }
1300*f4a2713aSLionel Sambuc 
1301*f4a2713aSLionel Sambuc     // Set the default visibility to private.
1302*f4a2713aSLionel Sambuc     if (Tok.is(tok::at)) { // parse objc-visibility-spec
1303*f4a2713aSLionel Sambuc       ConsumeToken(); // eat the @ sign
1304*f4a2713aSLionel Sambuc 
1305*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
1306*f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCAtVisibility(getCurScope());
1307*f4a2713aSLionel Sambuc         return cutOffParsing();
1308*f4a2713aSLionel Sambuc       }
1309*f4a2713aSLionel Sambuc 
1310*f4a2713aSLionel Sambuc       switch (Tok.getObjCKeywordID()) {
1311*f4a2713aSLionel Sambuc       case tok::objc_private:
1312*f4a2713aSLionel Sambuc       case tok::objc_public:
1313*f4a2713aSLionel Sambuc       case tok::objc_protected:
1314*f4a2713aSLionel Sambuc       case tok::objc_package:
1315*f4a2713aSLionel Sambuc         visibility = Tok.getObjCKeywordID();
1316*f4a2713aSLionel Sambuc         ConsumeToken();
1317*f4a2713aSLionel Sambuc         continue;
1318*f4a2713aSLionel Sambuc 
1319*f4a2713aSLionel Sambuc       case tok::objc_end:
1320*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_unexpected_atend);
1321*f4a2713aSLionel Sambuc         Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
1322*f4a2713aSLionel Sambuc         Tok.setKind(tok::at);
1323*f4a2713aSLionel Sambuc         Tok.setLength(1);
1324*f4a2713aSLionel Sambuc         PP.EnterToken(Tok);
1325*f4a2713aSLionel Sambuc         HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
1326*f4a2713aSLionel Sambuc                                          T, AllIvarDecls, true);
1327*f4a2713aSLionel Sambuc         return;
1328*f4a2713aSLionel Sambuc 
1329*f4a2713aSLionel Sambuc       default:
1330*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_illegal_visibility_spec);
1331*f4a2713aSLionel Sambuc         continue;
1332*f4a2713aSLionel Sambuc       }
1333*f4a2713aSLionel Sambuc     }
1334*f4a2713aSLionel Sambuc 
1335*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1336*f4a2713aSLionel Sambuc       Actions.CodeCompleteOrdinaryName(getCurScope(),
1337*f4a2713aSLionel Sambuc                                        Sema::PCC_ObjCInstanceVariableList);
1338*f4a2713aSLionel Sambuc       return cutOffParsing();
1339*f4a2713aSLionel Sambuc     }
1340*f4a2713aSLionel Sambuc 
1341*f4a2713aSLionel Sambuc     struct ObjCIvarCallback : FieldCallback {
1342*f4a2713aSLionel Sambuc       Parser &P;
1343*f4a2713aSLionel Sambuc       Decl *IDecl;
1344*f4a2713aSLionel Sambuc       tok::ObjCKeywordKind visibility;
1345*f4a2713aSLionel Sambuc       SmallVectorImpl<Decl *> &AllIvarDecls;
1346*f4a2713aSLionel Sambuc 
1347*f4a2713aSLionel Sambuc       ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V,
1348*f4a2713aSLionel Sambuc                        SmallVectorImpl<Decl *> &AllIvarDecls) :
1349*f4a2713aSLionel Sambuc         P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
1350*f4a2713aSLionel Sambuc       }
1351*f4a2713aSLionel Sambuc 
1352*f4a2713aSLionel Sambuc       void invoke(ParsingFieldDeclarator &FD) {
1353*f4a2713aSLionel Sambuc         P.Actions.ActOnObjCContainerStartDefinition(IDecl);
1354*f4a2713aSLionel Sambuc         // Install the declarator into the interface decl.
1355*f4a2713aSLionel Sambuc         Decl *Field
1356*f4a2713aSLionel Sambuc           = P.Actions.ActOnIvar(P.getCurScope(),
1357*f4a2713aSLionel Sambuc                                 FD.D.getDeclSpec().getSourceRange().getBegin(),
1358*f4a2713aSLionel Sambuc                                 FD.D, FD.BitfieldSize, visibility);
1359*f4a2713aSLionel Sambuc         P.Actions.ActOnObjCContainerFinishDefinition();
1360*f4a2713aSLionel Sambuc         if (Field)
1361*f4a2713aSLionel Sambuc           AllIvarDecls.push_back(Field);
1362*f4a2713aSLionel Sambuc         FD.complete(Field);
1363*f4a2713aSLionel Sambuc       }
1364*f4a2713aSLionel Sambuc     } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
1365*f4a2713aSLionel Sambuc 
1366*f4a2713aSLionel Sambuc     // Parse all the comma separated declarators.
1367*f4a2713aSLionel Sambuc     ParsingDeclSpec DS(*this);
1368*f4a2713aSLionel Sambuc     ParseStructDeclaration(DS, Callback);
1369*f4a2713aSLionel Sambuc 
1370*f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
1371*f4a2713aSLionel Sambuc       ConsumeToken();
1372*f4a2713aSLionel Sambuc     } else {
1373*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_semi_decl_list);
1374*f4a2713aSLionel Sambuc       // Skip to end of block or statement
1375*f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
1376*f4a2713aSLionel Sambuc     }
1377*f4a2713aSLionel Sambuc   }
1378*f4a2713aSLionel Sambuc   HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
1379*f4a2713aSLionel Sambuc                                    T, AllIvarDecls, false);
1380*f4a2713aSLionel Sambuc   return;
1381*f4a2713aSLionel Sambuc }
1382*f4a2713aSLionel Sambuc 
1383*f4a2713aSLionel Sambuc ///   objc-protocol-declaration:
1384*f4a2713aSLionel Sambuc ///     objc-protocol-definition
1385*f4a2713aSLionel Sambuc ///     objc-protocol-forward-reference
1386*f4a2713aSLionel Sambuc ///
1387*f4a2713aSLionel Sambuc ///   objc-protocol-definition:
1388*f4a2713aSLionel Sambuc ///     \@protocol identifier
1389*f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
1390*f4a2713aSLionel Sambuc ///       objc-interface-decl-list
1391*f4a2713aSLionel Sambuc ///     \@end
1392*f4a2713aSLionel Sambuc ///
1393*f4a2713aSLionel Sambuc ///   objc-protocol-forward-reference:
1394*f4a2713aSLionel Sambuc ///     \@protocol identifier-list ';'
1395*f4a2713aSLionel Sambuc ///
1396*f4a2713aSLionel Sambuc ///   "\@protocol identifier ;" should be resolved as "\@protocol
1397*f4a2713aSLionel Sambuc ///   identifier-list ;": objc-interface-decl-list may not start with a
1398*f4a2713aSLionel Sambuc ///   semicolon in the first alternative if objc-protocol-refs are omitted.
1399*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
1400*f4a2713aSLionel Sambuc Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
1401*f4a2713aSLionel Sambuc                                        ParsedAttributes &attrs) {
1402*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
1403*f4a2713aSLionel Sambuc          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
1404*f4a2713aSLionel Sambuc   ConsumeToken(); // the "protocol" identifier
1405*f4a2713aSLionel Sambuc 
1406*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
1407*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCProtocolDecl(getCurScope());
1408*f4a2713aSLionel Sambuc     cutOffParsing();
1409*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1410*f4a2713aSLionel Sambuc   }
1411*f4a2713aSLionel Sambuc 
1412*f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_protocol);
1413*f4a2713aSLionel Sambuc 
1414*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1415*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident); // missing protocol name.
1416*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1417*f4a2713aSLionel Sambuc   }
1418*f4a2713aSLionel Sambuc   // Save the protocol name, then consume it.
1419*f4a2713aSLionel Sambuc   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
1420*f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken();
1421*f4a2713aSLionel Sambuc 
1422*f4a2713aSLionel Sambuc   if (Tok.is(tok::semi)) { // forward declaration of one protocol.
1423*f4a2713aSLionel Sambuc     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
1424*f4a2713aSLionel Sambuc     ConsumeToken();
1425*f4a2713aSLionel Sambuc     return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
1426*f4a2713aSLionel Sambuc                                                    attrs.getList());
1427*f4a2713aSLionel Sambuc   }
1428*f4a2713aSLionel Sambuc 
1429*f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
1430*f4a2713aSLionel Sambuc 
1431*f4a2713aSLionel Sambuc   if (Tok.is(tok::comma)) { // list of forward declarations.
1432*f4a2713aSLionel Sambuc     SmallVector<IdentifierLocPair, 8> ProtocolRefs;
1433*f4a2713aSLionel Sambuc     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
1434*f4a2713aSLionel Sambuc 
1435*f4a2713aSLionel Sambuc     // Parse the list of forward declarations.
1436*f4a2713aSLionel Sambuc     while (1) {
1437*f4a2713aSLionel Sambuc       ConsumeToken(); // the ','
1438*f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1439*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_expected_ident);
1440*f4a2713aSLionel Sambuc         SkipUntil(tok::semi);
1441*f4a2713aSLionel Sambuc         return DeclGroupPtrTy();
1442*f4a2713aSLionel Sambuc       }
1443*f4a2713aSLionel Sambuc       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
1444*f4a2713aSLionel Sambuc                                                Tok.getLocation()));
1445*f4a2713aSLionel Sambuc       ConsumeToken(); // the identifier
1446*f4a2713aSLionel Sambuc 
1447*f4a2713aSLionel Sambuc       if (Tok.isNot(tok::comma))
1448*f4a2713aSLionel Sambuc         break;
1449*f4a2713aSLionel Sambuc     }
1450*f4a2713aSLionel Sambuc     // Consume the ';'.
1451*f4a2713aSLionel Sambuc     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
1452*f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1453*f4a2713aSLionel Sambuc 
1454*f4a2713aSLionel Sambuc     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
1455*f4a2713aSLionel Sambuc                                                    &ProtocolRefs[0],
1456*f4a2713aSLionel Sambuc                                                    ProtocolRefs.size(),
1457*f4a2713aSLionel Sambuc                                                    attrs.getList());
1458*f4a2713aSLionel Sambuc   }
1459*f4a2713aSLionel Sambuc 
1460*f4a2713aSLionel Sambuc   // Last, and definitely not least, parse a protocol declaration.
1461*f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
1462*f4a2713aSLionel Sambuc 
1463*f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolRefs;
1464*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
1465*f4a2713aSLionel Sambuc   if (Tok.is(tok::less) &&
1466*f4a2713aSLionel Sambuc       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
1467*f4a2713aSLionel Sambuc                                   LAngleLoc, EndProtoLoc))
1468*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1469*f4a2713aSLionel Sambuc 
1470*f4a2713aSLionel Sambuc   Decl *ProtoType =
1471*f4a2713aSLionel Sambuc     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
1472*f4a2713aSLionel Sambuc                                         ProtocolRefs.data(),
1473*f4a2713aSLionel Sambuc                                         ProtocolRefs.size(),
1474*f4a2713aSLionel Sambuc                                         ProtocolLocs.data(),
1475*f4a2713aSLionel Sambuc                                         EndProtoLoc, attrs.getList());
1476*f4a2713aSLionel Sambuc 
1477*f4a2713aSLionel Sambuc   ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
1478*f4a2713aSLionel Sambuc   return Actions.ConvertDeclToDeclGroup(ProtoType);
1479*f4a2713aSLionel Sambuc }
1480*f4a2713aSLionel Sambuc 
1481*f4a2713aSLionel Sambuc ///   objc-implementation:
1482*f4a2713aSLionel Sambuc ///     objc-class-implementation-prologue
1483*f4a2713aSLionel Sambuc ///     objc-category-implementation-prologue
1484*f4a2713aSLionel Sambuc ///
1485*f4a2713aSLionel Sambuc ///   objc-class-implementation-prologue:
1486*f4a2713aSLionel Sambuc ///     @implementation identifier objc-superclass[opt]
1487*f4a2713aSLionel Sambuc ///       objc-class-instance-variables[opt]
1488*f4a2713aSLionel Sambuc ///
1489*f4a2713aSLionel Sambuc ///   objc-category-implementation-prologue:
1490*f4a2713aSLionel Sambuc ///     @implementation identifier ( identifier )
1491*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
1492*f4a2713aSLionel Sambuc Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
1493*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
1494*f4a2713aSLionel Sambuc          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
1495*f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
1496*f4a2713aSLionel Sambuc   ConsumeToken(); // the "implementation" identifier
1497*f4a2713aSLionel Sambuc 
1498*f4a2713aSLionel Sambuc   // Code completion after '@implementation'.
1499*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
1500*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCImplementationDecl(getCurScope());
1501*f4a2713aSLionel Sambuc     cutOffParsing();
1502*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1503*f4a2713aSLionel Sambuc   }
1504*f4a2713aSLionel Sambuc 
1505*f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_implementation);
1506*f4a2713aSLionel Sambuc 
1507*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1508*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident); // missing class or category name.
1509*f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1510*f4a2713aSLionel Sambuc   }
1511*f4a2713aSLionel Sambuc   // We have a class or category name - consume it.
1512*f4a2713aSLionel Sambuc   IdentifierInfo *nameId = Tok.getIdentifierInfo();
1513*f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
1514*f4a2713aSLionel Sambuc   Decl *ObjCImpDecl = 0;
1515*f4a2713aSLionel Sambuc 
1516*f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren)) {
1517*f4a2713aSLionel Sambuc     // we have a category implementation.
1518*f4a2713aSLionel Sambuc     ConsumeParen();
1519*f4a2713aSLionel Sambuc     SourceLocation categoryLoc, rparenLoc;
1520*f4a2713aSLionel Sambuc     IdentifierInfo *categoryId = 0;
1521*f4a2713aSLionel Sambuc 
1522*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1523*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
1524*f4a2713aSLionel Sambuc       cutOffParsing();
1525*f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1526*f4a2713aSLionel Sambuc     }
1527*f4a2713aSLionel Sambuc 
1528*f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier)) {
1529*f4a2713aSLionel Sambuc       categoryId = Tok.getIdentifierInfo();
1530*f4a2713aSLionel Sambuc       categoryLoc = ConsumeToken();
1531*f4a2713aSLionel Sambuc     } else {
1532*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident); // missing category name.
1533*f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1534*f4a2713aSLionel Sambuc     }
1535*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::r_paren)) {
1536*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_rparen);
1537*f4a2713aSLionel Sambuc       SkipUntil(tok::r_paren); // don't stop at ';'
1538*f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1539*f4a2713aSLionel Sambuc     }
1540*f4a2713aSLionel Sambuc     rparenLoc = ConsumeParen();
1541*f4a2713aSLionel Sambuc     if (Tok.is(tok::less)) { // we have illegal '<' try to recover
1542*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_unexpected_protocol_qualifier);
1543*f4a2713aSLionel Sambuc       AttributeFactory attr;
1544*f4a2713aSLionel Sambuc       DeclSpec DS(attr);
1545*f4a2713aSLionel Sambuc       (void)ParseObjCProtocolQualifiers(DS);
1546*f4a2713aSLionel Sambuc     }
1547*f4a2713aSLionel Sambuc     ObjCImpDecl = Actions.ActOnStartCategoryImplementation(
1548*f4a2713aSLionel Sambuc                                     AtLoc, nameId, nameLoc, categoryId,
1549*f4a2713aSLionel Sambuc                                     categoryLoc);
1550*f4a2713aSLionel Sambuc 
1551*f4a2713aSLionel Sambuc   } else {
1552*f4a2713aSLionel Sambuc     // We have a class implementation
1553*f4a2713aSLionel Sambuc     SourceLocation superClassLoc;
1554*f4a2713aSLionel Sambuc     IdentifierInfo *superClassId = 0;
1555*f4a2713aSLionel Sambuc     if (Tok.is(tok::colon)) {
1556*f4a2713aSLionel Sambuc       // We have a super class
1557*f4a2713aSLionel Sambuc       ConsumeToken();
1558*f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1559*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_expected_ident); // missing super class name.
1560*f4a2713aSLionel Sambuc         return DeclGroupPtrTy();
1561*f4a2713aSLionel Sambuc       }
1562*f4a2713aSLionel Sambuc       superClassId = Tok.getIdentifierInfo();
1563*f4a2713aSLionel Sambuc       superClassLoc = ConsumeToken(); // Consume super class name
1564*f4a2713aSLionel Sambuc     }
1565*f4a2713aSLionel Sambuc     ObjCImpDecl = Actions.ActOnStartClassImplementation(
1566*f4a2713aSLionel Sambuc                                     AtLoc, nameId, nameLoc,
1567*f4a2713aSLionel Sambuc                                     superClassId, superClassLoc);
1568*f4a2713aSLionel Sambuc 
1569*f4a2713aSLionel Sambuc     if (Tok.is(tok::l_brace)) // we have ivars
1570*f4a2713aSLionel Sambuc       ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
1571*f4a2713aSLionel Sambuc     else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
1572*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_unexpected_protocol_qualifier);
1573*f4a2713aSLionel Sambuc       // try to recover.
1574*f4a2713aSLionel Sambuc       AttributeFactory attr;
1575*f4a2713aSLionel Sambuc       DeclSpec DS(attr);
1576*f4a2713aSLionel Sambuc       (void)ParseObjCProtocolQualifiers(DS);
1577*f4a2713aSLionel Sambuc     }
1578*f4a2713aSLionel Sambuc   }
1579*f4a2713aSLionel Sambuc   assert(ObjCImpDecl);
1580*f4a2713aSLionel Sambuc 
1581*f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> DeclsInGroup;
1582*f4a2713aSLionel Sambuc 
1583*f4a2713aSLionel Sambuc   {
1584*f4a2713aSLionel Sambuc     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
1585*f4a2713aSLionel Sambuc     while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) {
1586*f4a2713aSLionel Sambuc       ParsedAttributesWithRange attrs(AttrFactory);
1587*f4a2713aSLionel Sambuc       MaybeParseCXX11Attributes(attrs);
1588*f4a2713aSLionel Sambuc       MaybeParseMicrosoftAttributes(attrs);
1589*f4a2713aSLionel Sambuc       if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
1590*f4a2713aSLionel Sambuc         DeclGroupRef DG = DGP.get();
1591*f4a2713aSLionel Sambuc         DeclsInGroup.append(DG.begin(), DG.end());
1592*f4a2713aSLionel Sambuc       }
1593*f4a2713aSLionel Sambuc     }
1594*f4a2713aSLionel Sambuc   }
1595*f4a2713aSLionel Sambuc 
1596*f4a2713aSLionel Sambuc   return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup);
1597*f4a2713aSLionel Sambuc }
1598*f4a2713aSLionel Sambuc 
1599*f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
1600*f4a2713aSLionel Sambuc Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
1601*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
1602*f4a2713aSLionel Sambuc          "ParseObjCAtEndDeclaration(): Expected @end");
1603*f4a2713aSLionel Sambuc   ConsumeToken(); // the "end" identifier
1604*f4a2713aSLionel Sambuc   if (CurParsedObjCImpl)
1605*f4a2713aSLionel Sambuc     CurParsedObjCImpl->finish(atEnd);
1606*f4a2713aSLionel Sambuc   else
1607*f4a2713aSLionel Sambuc     // missing @implementation
1608*f4a2713aSLionel Sambuc     Diag(atEnd.getBegin(), diag::err_expected_objc_container);
1609*f4a2713aSLionel Sambuc   return DeclGroupPtrTy();
1610*f4a2713aSLionel Sambuc }
1611*f4a2713aSLionel Sambuc 
1612*f4a2713aSLionel Sambuc Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
1613*f4a2713aSLionel Sambuc   if (!Finished) {
1614*f4a2713aSLionel Sambuc     finish(P.Tok.getLocation());
1615*f4a2713aSLionel Sambuc     if (P.Tok.is(tok::eof)) {
1616*f4a2713aSLionel Sambuc       P.Diag(P.Tok, diag::err_objc_missing_end)
1617*f4a2713aSLionel Sambuc           << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
1618*f4a2713aSLionel Sambuc       P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
1619*f4a2713aSLionel Sambuc           << Sema::OCK_Implementation;
1620*f4a2713aSLionel Sambuc     }
1621*f4a2713aSLionel Sambuc   }
1622*f4a2713aSLionel Sambuc   P.CurParsedObjCImpl = 0;
1623*f4a2713aSLionel Sambuc   assert(LateParsedObjCMethods.empty());
1624*f4a2713aSLionel Sambuc }
1625*f4a2713aSLionel Sambuc 
1626*f4a2713aSLionel Sambuc void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
1627*f4a2713aSLionel Sambuc   assert(!Finished);
1628*f4a2713aSLionel Sambuc   P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl);
1629*f4a2713aSLionel Sambuc   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
1630*f4a2713aSLionel Sambuc     P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
1631*f4a2713aSLionel Sambuc                                true/*Methods*/);
1632*f4a2713aSLionel Sambuc 
1633*f4a2713aSLionel Sambuc   P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);
1634*f4a2713aSLionel Sambuc 
1635*f4a2713aSLionel Sambuc   if (HasCFunction)
1636*f4a2713aSLionel Sambuc     for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
1637*f4a2713aSLionel Sambuc       P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
1638*f4a2713aSLionel Sambuc                                  false/*c-functions*/);
1639*f4a2713aSLionel Sambuc 
1640*f4a2713aSLionel Sambuc   /// \brief Clear and free the cached objc methods.
1641*f4a2713aSLionel Sambuc   for (LateParsedObjCMethodContainer::iterator
1642*f4a2713aSLionel Sambuc          I = LateParsedObjCMethods.begin(),
1643*f4a2713aSLionel Sambuc          E = LateParsedObjCMethods.end(); I != E; ++I)
1644*f4a2713aSLionel Sambuc     delete *I;
1645*f4a2713aSLionel Sambuc   LateParsedObjCMethods.clear();
1646*f4a2713aSLionel Sambuc 
1647*f4a2713aSLionel Sambuc   Finished = true;
1648*f4a2713aSLionel Sambuc }
1649*f4a2713aSLionel Sambuc 
1650*f4a2713aSLionel Sambuc ///   compatibility-alias-decl:
1651*f4a2713aSLionel Sambuc ///     @compatibility_alias alias-name  class-name ';'
1652*f4a2713aSLionel Sambuc ///
1653*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
1654*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
1655*f4a2713aSLionel Sambuc          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
1656*f4a2713aSLionel Sambuc   ConsumeToken(); // consume compatibility_alias
1657*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1658*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident);
1659*f4a2713aSLionel Sambuc     return 0;
1660*f4a2713aSLionel Sambuc   }
1661*f4a2713aSLionel Sambuc   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
1662*f4a2713aSLionel Sambuc   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
1663*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1664*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident);
1665*f4a2713aSLionel Sambuc     return 0;
1666*f4a2713aSLionel Sambuc   }
1667*f4a2713aSLionel Sambuc   IdentifierInfo *classId = Tok.getIdentifierInfo();
1668*f4a2713aSLionel Sambuc   SourceLocation classLoc = ConsumeToken(); // consume class-name;
1669*f4a2713aSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
1670*f4a2713aSLionel Sambuc                    "@compatibility_alias");
1671*f4a2713aSLionel Sambuc   return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
1672*f4a2713aSLionel Sambuc                                          classId, classLoc);
1673*f4a2713aSLionel Sambuc }
1674*f4a2713aSLionel Sambuc 
1675*f4a2713aSLionel Sambuc ///   property-synthesis:
1676*f4a2713aSLionel Sambuc ///     @synthesize property-ivar-list ';'
1677*f4a2713aSLionel Sambuc ///
1678*f4a2713aSLionel Sambuc ///   property-ivar-list:
1679*f4a2713aSLionel Sambuc ///     property-ivar
1680*f4a2713aSLionel Sambuc ///     property-ivar-list ',' property-ivar
1681*f4a2713aSLionel Sambuc ///
1682*f4a2713aSLionel Sambuc ///   property-ivar:
1683*f4a2713aSLionel Sambuc ///     identifier
1684*f4a2713aSLionel Sambuc ///     identifier '=' identifier
1685*f4a2713aSLionel Sambuc ///
1686*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1687*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1688*f4a2713aSLionel Sambuc          "ParseObjCPropertySynthesize(): Expected '@synthesize'");
1689*f4a2713aSLionel Sambuc   ConsumeToken(); // consume synthesize
1690*f4a2713aSLionel Sambuc 
1691*f4a2713aSLionel Sambuc   while (true) {
1692*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1693*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
1694*f4a2713aSLionel Sambuc       cutOffParsing();
1695*f4a2713aSLionel Sambuc       return 0;
1696*f4a2713aSLionel Sambuc     }
1697*f4a2713aSLionel Sambuc 
1698*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1699*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_synthesized_property_name);
1700*f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1701*f4a2713aSLionel Sambuc       return 0;
1702*f4a2713aSLionel Sambuc     }
1703*f4a2713aSLionel Sambuc 
1704*f4a2713aSLionel Sambuc     IdentifierInfo *propertyIvar = 0;
1705*f4a2713aSLionel Sambuc     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1706*f4a2713aSLionel Sambuc     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1707*f4a2713aSLionel Sambuc     SourceLocation propertyIvarLoc;
1708*f4a2713aSLionel Sambuc     if (Tok.is(tok::equal)) {
1709*f4a2713aSLionel Sambuc       // property '=' ivar-name
1710*f4a2713aSLionel Sambuc       ConsumeToken(); // consume '='
1711*f4a2713aSLionel Sambuc 
1712*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
1713*f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
1714*f4a2713aSLionel Sambuc         cutOffParsing();
1715*f4a2713aSLionel Sambuc         return 0;
1716*f4a2713aSLionel Sambuc       }
1717*f4a2713aSLionel Sambuc 
1718*f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1719*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_expected_ident);
1720*f4a2713aSLionel Sambuc         break;
1721*f4a2713aSLionel Sambuc       }
1722*f4a2713aSLionel Sambuc       propertyIvar = Tok.getIdentifierInfo();
1723*f4a2713aSLionel Sambuc       propertyIvarLoc = ConsumeToken(); // consume ivar-name
1724*f4a2713aSLionel Sambuc     }
1725*f4a2713aSLionel Sambuc     Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true,
1726*f4a2713aSLionel Sambuc                                   propertyId, propertyIvar, propertyIvarLoc);
1727*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
1728*f4a2713aSLionel Sambuc       break;
1729*f4a2713aSLionel Sambuc     ConsumeToken(); // consume ','
1730*f4a2713aSLionel Sambuc   }
1731*f4a2713aSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize");
1732*f4a2713aSLionel Sambuc   return 0;
1733*f4a2713aSLionel Sambuc }
1734*f4a2713aSLionel Sambuc 
1735*f4a2713aSLionel Sambuc ///   property-dynamic:
1736*f4a2713aSLionel Sambuc ///     @dynamic  property-list
1737*f4a2713aSLionel Sambuc ///
1738*f4a2713aSLionel Sambuc ///   property-list:
1739*f4a2713aSLionel Sambuc ///     identifier
1740*f4a2713aSLionel Sambuc ///     property-list ',' identifier
1741*f4a2713aSLionel Sambuc ///
1742*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1743*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1744*f4a2713aSLionel Sambuc          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1745*f4a2713aSLionel Sambuc   ConsumeToken(); // consume dynamic
1746*f4a2713aSLionel Sambuc   while (true) {
1747*f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1748*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
1749*f4a2713aSLionel Sambuc       cutOffParsing();
1750*f4a2713aSLionel Sambuc       return 0;
1751*f4a2713aSLionel Sambuc     }
1752*f4a2713aSLionel Sambuc 
1753*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1754*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_ident);
1755*f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1756*f4a2713aSLionel Sambuc       return 0;
1757*f4a2713aSLionel Sambuc     }
1758*f4a2713aSLionel Sambuc 
1759*f4a2713aSLionel Sambuc     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1760*f4a2713aSLionel Sambuc     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1761*f4a2713aSLionel Sambuc     Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false,
1762*f4a2713aSLionel Sambuc                                   propertyId, 0, SourceLocation());
1763*f4a2713aSLionel Sambuc 
1764*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
1765*f4a2713aSLionel Sambuc       break;
1766*f4a2713aSLionel Sambuc     ConsumeToken(); // consume ','
1767*f4a2713aSLionel Sambuc   }
1768*f4a2713aSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic");
1769*f4a2713aSLionel Sambuc   return 0;
1770*f4a2713aSLionel Sambuc }
1771*f4a2713aSLionel Sambuc 
1772*f4a2713aSLionel Sambuc ///  objc-throw-statement:
1773*f4a2713aSLionel Sambuc ///    throw expression[opt];
1774*f4a2713aSLionel Sambuc ///
1775*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
1776*f4a2713aSLionel Sambuc   ExprResult Res;
1777*f4a2713aSLionel Sambuc   ConsumeToken(); // consume throw
1778*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::semi)) {
1779*f4a2713aSLionel Sambuc     Res = ParseExpression();
1780*f4a2713aSLionel Sambuc     if (Res.isInvalid()) {
1781*f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1782*f4a2713aSLionel Sambuc       return StmtError();
1783*f4a2713aSLionel Sambuc     }
1784*f4a2713aSLionel Sambuc   }
1785*f4a2713aSLionel Sambuc   // consume ';'
1786*f4a2713aSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
1787*f4a2713aSLionel Sambuc   return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
1788*f4a2713aSLionel Sambuc }
1789*f4a2713aSLionel Sambuc 
1790*f4a2713aSLionel Sambuc /// objc-synchronized-statement:
1791*f4a2713aSLionel Sambuc ///   @synchronized '(' expression ')' compound-statement
1792*f4a2713aSLionel Sambuc ///
1793*f4a2713aSLionel Sambuc StmtResult
1794*f4a2713aSLionel Sambuc Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
1795*f4a2713aSLionel Sambuc   ConsumeToken(); // consume synchronized
1796*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren)) {
1797*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
1798*f4a2713aSLionel Sambuc     return StmtError();
1799*f4a2713aSLionel Sambuc   }
1800*f4a2713aSLionel Sambuc 
1801*f4a2713aSLionel Sambuc   // The operand is surrounded with parentheses.
1802*f4a2713aSLionel Sambuc   ConsumeParen();  // '('
1803*f4a2713aSLionel Sambuc   ExprResult operand(ParseExpression());
1804*f4a2713aSLionel Sambuc 
1805*f4a2713aSLionel Sambuc   if (Tok.is(tok::r_paren)) {
1806*f4a2713aSLionel Sambuc     ConsumeParen();  // ')'
1807*f4a2713aSLionel Sambuc   } else {
1808*f4a2713aSLionel Sambuc     if (!operand.isInvalid())
1809*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_rparen);
1810*f4a2713aSLionel Sambuc 
1811*f4a2713aSLionel Sambuc     // Skip forward until we see a left brace, but don't consume it.
1812*f4a2713aSLionel Sambuc     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
1813*f4a2713aSLionel Sambuc   }
1814*f4a2713aSLionel Sambuc 
1815*f4a2713aSLionel Sambuc   // Require a compound statement.
1816*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1817*f4a2713aSLionel Sambuc     if (!operand.isInvalid())
1818*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_lbrace);
1819*f4a2713aSLionel Sambuc     return StmtError();
1820*f4a2713aSLionel Sambuc   }
1821*f4a2713aSLionel Sambuc 
1822*f4a2713aSLionel Sambuc   // Check the @synchronized operand now.
1823*f4a2713aSLionel Sambuc   if (!operand.isInvalid())
1824*f4a2713aSLionel Sambuc     operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take());
1825*f4a2713aSLionel Sambuc 
1826*f4a2713aSLionel Sambuc   // Parse the compound statement within a new scope.
1827*f4a2713aSLionel Sambuc   ParseScope bodyScope(this, Scope::DeclScope);
1828*f4a2713aSLionel Sambuc   StmtResult body(ParseCompoundStatementBody());
1829*f4a2713aSLionel Sambuc   bodyScope.Exit();
1830*f4a2713aSLionel Sambuc 
1831*f4a2713aSLionel Sambuc   // If there was a semantic or parse error earlier with the
1832*f4a2713aSLionel Sambuc   // operand, fail now.
1833*f4a2713aSLionel Sambuc   if (operand.isInvalid())
1834*f4a2713aSLionel Sambuc     return StmtError();
1835*f4a2713aSLionel Sambuc 
1836*f4a2713aSLionel Sambuc   if (body.isInvalid())
1837*f4a2713aSLionel Sambuc     body = Actions.ActOnNullStmt(Tok.getLocation());
1838*f4a2713aSLionel Sambuc 
1839*f4a2713aSLionel Sambuc   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get());
1840*f4a2713aSLionel Sambuc }
1841*f4a2713aSLionel Sambuc 
1842*f4a2713aSLionel Sambuc ///  objc-try-catch-statement:
1843*f4a2713aSLionel Sambuc ///    @try compound-statement objc-catch-list[opt]
1844*f4a2713aSLionel Sambuc ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
1845*f4a2713aSLionel Sambuc ///
1846*f4a2713aSLionel Sambuc ///  objc-catch-list:
1847*f4a2713aSLionel Sambuc ///    @catch ( parameter-declaration ) compound-statement
1848*f4a2713aSLionel Sambuc ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1849*f4a2713aSLionel Sambuc ///  catch-parameter-declaration:
1850*f4a2713aSLionel Sambuc ///     parameter-declaration
1851*f4a2713aSLionel Sambuc ///     '...' [OBJC2]
1852*f4a2713aSLionel Sambuc ///
1853*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
1854*f4a2713aSLionel Sambuc   bool catch_or_finally_seen = false;
1855*f4a2713aSLionel Sambuc 
1856*f4a2713aSLionel Sambuc   ConsumeToken(); // consume try
1857*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1858*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_lbrace);
1859*f4a2713aSLionel Sambuc     return StmtError();
1860*f4a2713aSLionel Sambuc   }
1861*f4a2713aSLionel Sambuc   StmtVector CatchStmts;
1862*f4a2713aSLionel Sambuc   StmtResult FinallyStmt;
1863*f4a2713aSLionel Sambuc   ParseScope TryScope(this, Scope::DeclScope);
1864*f4a2713aSLionel Sambuc   StmtResult TryBody(ParseCompoundStatementBody());
1865*f4a2713aSLionel Sambuc   TryScope.Exit();
1866*f4a2713aSLionel Sambuc   if (TryBody.isInvalid())
1867*f4a2713aSLionel Sambuc     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
1868*f4a2713aSLionel Sambuc 
1869*f4a2713aSLionel Sambuc   while (Tok.is(tok::at)) {
1870*f4a2713aSLionel Sambuc     // At this point, we need to lookahead to determine if this @ is the start
1871*f4a2713aSLionel Sambuc     // of an @catch or @finally.  We don't want to consume the @ token if this
1872*f4a2713aSLionel Sambuc     // is an @try or @encode or something else.
1873*f4a2713aSLionel Sambuc     Token AfterAt = GetLookAheadToken(1);
1874*f4a2713aSLionel Sambuc     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
1875*f4a2713aSLionel Sambuc         !AfterAt.isObjCAtKeyword(tok::objc_finally))
1876*f4a2713aSLionel Sambuc       break;
1877*f4a2713aSLionel Sambuc 
1878*f4a2713aSLionel Sambuc     SourceLocation AtCatchFinallyLoc = ConsumeToken();
1879*f4a2713aSLionel Sambuc     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
1880*f4a2713aSLionel Sambuc       Decl *FirstPart = 0;
1881*f4a2713aSLionel Sambuc       ConsumeToken(); // consume catch
1882*f4a2713aSLionel Sambuc       if (Tok.is(tok::l_paren)) {
1883*f4a2713aSLionel Sambuc         ConsumeParen();
1884*f4a2713aSLionel Sambuc         ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
1885*f4a2713aSLionel Sambuc         if (Tok.isNot(tok::ellipsis)) {
1886*f4a2713aSLionel Sambuc           DeclSpec DS(AttrFactory);
1887*f4a2713aSLionel Sambuc           ParseDeclarationSpecifiers(DS);
1888*f4a2713aSLionel Sambuc           Declarator ParmDecl(DS, Declarator::ObjCCatchContext);
1889*f4a2713aSLionel Sambuc           ParseDeclarator(ParmDecl);
1890*f4a2713aSLionel Sambuc 
1891*f4a2713aSLionel Sambuc           // Inform the actions module about the declarator, so it
1892*f4a2713aSLionel Sambuc           // gets added to the current scope.
1893*f4a2713aSLionel Sambuc           FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
1894*f4a2713aSLionel Sambuc         } else
1895*f4a2713aSLionel Sambuc           ConsumeToken(); // consume '...'
1896*f4a2713aSLionel Sambuc 
1897*f4a2713aSLionel Sambuc         SourceLocation RParenLoc;
1898*f4a2713aSLionel Sambuc 
1899*f4a2713aSLionel Sambuc         if (Tok.is(tok::r_paren))
1900*f4a2713aSLionel Sambuc           RParenLoc = ConsumeParen();
1901*f4a2713aSLionel Sambuc         else // Skip over garbage, until we get to ')'.  Eat the ')'.
1902*f4a2713aSLionel Sambuc           SkipUntil(tok::r_paren, StopAtSemi);
1903*f4a2713aSLionel Sambuc 
1904*f4a2713aSLionel Sambuc         StmtResult CatchBody(true);
1905*f4a2713aSLionel Sambuc         if (Tok.is(tok::l_brace))
1906*f4a2713aSLionel Sambuc           CatchBody = ParseCompoundStatementBody();
1907*f4a2713aSLionel Sambuc         else
1908*f4a2713aSLionel Sambuc           Diag(Tok, diag::err_expected_lbrace);
1909*f4a2713aSLionel Sambuc         if (CatchBody.isInvalid())
1910*f4a2713aSLionel Sambuc           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
1911*f4a2713aSLionel Sambuc 
1912*f4a2713aSLionel Sambuc         StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
1913*f4a2713aSLionel Sambuc                                                               RParenLoc,
1914*f4a2713aSLionel Sambuc                                                               FirstPart,
1915*f4a2713aSLionel Sambuc                                                               CatchBody.take());
1916*f4a2713aSLionel Sambuc         if (!Catch.isInvalid())
1917*f4a2713aSLionel Sambuc           CatchStmts.push_back(Catch.release());
1918*f4a2713aSLionel Sambuc 
1919*f4a2713aSLionel Sambuc       } else {
1920*f4a2713aSLionel Sambuc         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
1921*f4a2713aSLionel Sambuc           << "@catch clause";
1922*f4a2713aSLionel Sambuc         return StmtError();
1923*f4a2713aSLionel Sambuc       }
1924*f4a2713aSLionel Sambuc       catch_or_finally_seen = true;
1925*f4a2713aSLionel Sambuc     } else {
1926*f4a2713aSLionel Sambuc       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
1927*f4a2713aSLionel Sambuc       ConsumeToken(); // consume finally
1928*f4a2713aSLionel Sambuc       ParseScope FinallyScope(this, Scope::DeclScope);
1929*f4a2713aSLionel Sambuc 
1930*f4a2713aSLionel Sambuc       StmtResult FinallyBody(true);
1931*f4a2713aSLionel Sambuc       if (Tok.is(tok::l_brace))
1932*f4a2713aSLionel Sambuc         FinallyBody = ParseCompoundStatementBody();
1933*f4a2713aSLionel Sambuc       else
1934*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_expected_lbrace);
1935*f4a2713aSLionel Sambuc       if (FinallyBody.isInvalid())
1936*f4a2713aSLionel Sambuc         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
1937*f4a2713aSLionel Sambuc       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
1938*f4a2713aSLionel Sambuc                                                    FinallyBody.take());
1939*f4a2713aSLionel Sambuc       catch_or_finally_seen = true;
1940*f4a2713aSLionel Sambuc       break;
1941*f4a2713aSLionel Sambuc     }
1942*f4a2713aSLionel Sambuc   }
1943*f4a2713aSLionel Sambuc   if (!catch_or_finally_seen) {
1944*f4a2713aSLionel Sambuc     Diag(atLoc, diag::err_missing_catch_finally);
1945*f4a2713aSLionel Sambuc     return StmtError();
1946*f4a2713aSLionel Sambuc   }
1947*f4a2713aSLionel Sambuc 
1948*f4a2713aSLionel Sambuc   return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(),
1949*f4a2713aSLionel Sambuc                                     CatchStmts,
1950*f4a2713aSLionel Sambuc                                     FinallyStmt.take());
1951*f4a2713aSLionel Sambuc }
1952*f4a2713aSLionel Sambuc 
1953*f4a2713aSLionel Sambuc /// objc-autoreleasepool-statement:
1954*f4a2713aSLionel Sambuc ///   @autoreleasepool compound-statement
1955*f4a2713aSLionel Sambuc ///
1956*f4a2713aSLionel Sambuc StmtResult
1957*f4a2713aSLionel Sambuc Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
1958*f4a2713aSLionel Sambuc   ConsumeToken(); // consume autoreleasepool
1959*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1960*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_lbrace);
1961*f4a2713aSLionel Sambuc     return StmtError();
1962*f4a2713aSLionel Sambuc   }
1963*f4a2713aSLionel Sambuc   // Enter a scope to hold everything within the compound stmt.  Compound
1964*f4a2713aSLionel Sambuc   // statements can always hold declarations.
1965*f4a2713aSLionel Sambuc   ParseScope BodyScope(this, Scope::DeclScope);
1966*f4a2713aSLionel Sambuc 
1967*f4a2713aSLionel Sambuc   StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
1968*f4a2713aSLionel Sambuc 
1969*f4a2713aSLionel Sambuc   BodyScope.Exit();
1970*f4a2713aSLionel Sambuc   if (AutoreleasePoolBody.isInvalid())
1971*f4a2713aSLionel Sambuc     AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
1972*f4a2713aSLionel Sambuc   return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
1973*f4a2713aSLionel Sambuc                                                 AutoreleasePoolBody.take());
1974*f4a2713aSLionel Sambuc }
1975*f4a2713aSLionel Sambuc 
1976*f4a2713aSLionel Sambuc /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them
1977*f4a2713aSLionel Sambuc /// for later parsing.
1978*f4a2713aSLionel Sambuc void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
1979*f4a2713aSLionel Sambuc   LexedMethod* LM = new LexedMethod(this, MDecl);
1980*f4a2713aSLionel Sambuc   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
1981*f4a2713aSLionel Sambuc   CachedTokens &Toks = LM->Toks;
1982*f4a2713aSLionel Sambuc   // Begin by storing the '{' or 'try' or ':' token.
1983*f4a2713aSLionel Sambuc   Toks.push_back(Tok);
1984*f4a2713aSLionel Sambuc   if (Tok.is(tok::kw_try)) {
1985*f4a2713aSLionel Sambuc     ConsumeToken();
1986*f4a2713aSLionel Sambuc     if (Tok.is(tok::colon)) {
1987*f4a2713aSLionel Sambuc       Toks.push_back(Tok);
1988*f4a2713aSLionel Sambuc       ConsumeToken();
1989*f4a2713aSLionel Sambuc       while (Tok.isNot(tok::l_brace)) {
1990*f4a2713aSLionel Sambuc         ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
1991*f4a2713aSLionel Sambuc         ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
1992*f4a2713aSLionel Sambuc       }
1993*f4a2713aSLionel Sambuc     }
1994*f4a2713aSLionel Sambuc     Toks.push_back(Tok); // also store '{'
1995*f4a2713aSLionel Sambuc   }
1996*f4a2713aSLionel Sambuc   else if (Tok.is(tok::colon)) {
1997*f4a2713aSLionel Sambuc     ConsumeToken();
1998*f4a2713aSLionel Sambuc     while (Tok.isNot(tok::l_brace)) {
1999*f4a2713aSLionel Sambuc       ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
2000*f4a2713aSLionel Sambuc       ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
2001*f4a2713aSLionel Sambuc     }
2002*f4a2713aSLionel Sambuc     Toks.push_back(Tok); // also store '{'
2003*f4a2713aSLionel Sambuc   }
2004*f4a2713aSLionel Sambuc   ConsumeBrace();
2005*f4a2713aSLionel Sambuc   // Consume everything up to (and including) the matching right brace.
2006*f4a2713aSLionel Sambuc   ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
2007*f4a2713aSLionel Sambuc   while (Tok.is(tok::kw_catch)) {
2008*f4a2713aSLionel Sambuc     ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
2009*f4a2713aSLionel Sambuc     ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
2010*f4a2713aSLionel Sambuc   }
2011*f4a2713aSLionel Sambuc }
2012*f4a2713aSLionel Sambuc 
2013*f4a2713aSLionel Sambuc ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
2014*f4a2713aSLionel Sambuc ///
2015*f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDefinition() {
2016*f4a2713aSLionel Sambuc   Decl *MDecl = ParseObjCMethodPrototype();
2017*f4a2713aSLionel Sambuc 
2018*f4a2713aSLionel Sambuc   PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
2019*f4a2713aSLionel Sambuc                                       "parsing Objective-C method");
2020*f4a2713aSLionel Sambuc 
2021*f4a2713aSLionel Sambuc   // parse optional ';'
2022*f4a2713aSLionel Sambuc   if (Tok.is(tok::semi)) {
2023*f4a2713aSLionel Sambuc     if (CurParsedObjCImpl) {
2024*f4a2713aSLionel Sambuc       Diag(Tok, diag::warn_semicolon_before_method_body)
2025*f4a2713aSLionel Sambuc         << FixItHint::CreateRemoval(Tok.getLocation());
2026*f4a2713aSLionel Sambuc     }
2027*f4a2713aSLionel Sambuc     ConsumeToken();
2028*f4a2713aSLionel Sambuc   }
2029*f4a2713aSLionel Sambuc 
2030*f4a2713aSLionel Sambuc   // We should have an opening brace now.
2031*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
2032*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_method_body);
2033*f4a2713aSLionel Sambuc 
2034*f4a2713aSLionel Sambuc     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
2035*f4a2713aSLionel Sambuc     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
2036*f4a2713aSLionel Sambuc 
2037*f4a2713aSLionel Sambuc     // If we didn't find the '{', bail out.
2038*f4a2713aSLionel Sambuc     if (Tok.isNot(tok::l_brace))
2039*f4a2713aSLionel Sambuc       return 0;
2040*f4a2713aSLionel Sambuc   }
2041*f4a2713aSLionel Sambuc 
2042*f4a2713aSLionel Sambuc   if (!MDecl) {
2043*f4a2713aSLionel Sambuc     ConsumeBrace();
2044*f4a2713aSLionel Sambuc     SkipUntil(tok::r_brace);
2045*f4a2713aSLionel Sambuc     return 0;
2046*f4a2713aSLionel Sambuc   }
2047*f4a2713aSLionel Sambuc 
2048*f4a2713aSLionel Sambuc   // Allow the rest of sema to find private method decl implementations.
2049*f4a2713aSLionel Sambuc   Actions.AddAnyMethodToGlobalPool(MDecl);
2050*f4a2713aSLionel Sambuc   assert (CurParsedObjCImpl
2051*f4a2713aSLionel Sambuc           && "ParseObjCMethodDefinition - Method out of @implementation");
2052*f4a2713aSLionel Sambuc   // Consume the tokens and store them for later parsing.
2053*f4a2713aSLionel Sambuc   StashAwayMethodOrFunctionBodyTokens(MDecl);
2054*f4a2713aSLionel Sambuc   return MDecl;
2055*f4a2713aSLionel Sambuc }
2056*f4a2713aSLionel Sambuc 
2057*f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
2058*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2059*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtStatement(getCurScope());
2060*f4a2713aSLionel Sambuc     cutOffParsing();
2061*f4a2713aSLionel Sambuc     return StmtError();
2062*f4a2713aSLionel Sambuc   }
2063*f4a2713aSLionel Sambuc 
2064*f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_try))
2065*f4a2713aSLionel Sambuc     return ParseObjCTryStmt(AtLoc);
2066*f4a2713aSLionel Sambuc 
2067*f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_throw))
2068*f4a2713aSLionel Sambuc     return ParseObjCThrowStmt(AtLoc);
2069*f4a2713aSLionel Sambuc 
2070*f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
2071*f4a2713aSLionel Sambuc     return ParseObjCSynchronizedStmt(AtLoc);
2072*f4a2713aSLionel Sambuc 
2073*f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
2074*f4a2713aSLionel Sambuc     return ParseObjCAutoreleasePoolStmt(AtLoc);
2075*f4a2713aSLionel Sambuc 
2076*f4a2713aSLionel Sambuc   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
2077*f4a2713aSLionel Sambuc   if (Res.isInvalid()) {
2078*f4a2713aSLionel Sambuc     // If the expression is invalid, skip ahead to the next semicolon. Not
2079*f4a2713aSLionel Sambuc     // doing this opens us up to the possibility of infinite loops if
2080*f4a2713aSLionel Sambuc     // ParseExpression does not consume any tokens.
2081*f4a2713aSLionel Sambuc     SkipUntil(tok::semi);
2082*f4a2713aSLionel Sambuc     return StmtError();
2083*f4a2713aSLionel Sambuc   }
2084*f4a2713aSLionel Sambuc 
2085*f4a2713aSLionel Sambuc   // Otherwise, eat the semicolon.
2086*f4a2713aSLionel Sambuc   ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
2087*f4a2713aSLionel Sambuc   return Actions.ActOnExprStmt(Res);
2088*f4a2713aSLionel Sambuc }
2089*f4a2713aSLionel Sambuc 
2090*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
2091*f4a2713aSLionel Sambuc   switch (Tok.getKind()) {
2092*f4a2713aSLionel Sambuc   case tok::code_completion:
2093*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtExpression(getCurScope());
2094*f4a2713aSLionel Sambuc     cutOffParsing();
2095*f4a2713aSLionel Sambuc     return ExprError();
2096*f4a2713aSLionel Sambuc 
2097*f4a2713aSLionel Sambuc   case tok::minus:
2098*f4a2713aSLionel Sambuc   case tok::plus: {
2099*f4a2713aSLionel Sambuc     tok::TokenKind Kind = Tok.getKind();
2100*f4a2713aSLionel Sambuc     SourceLocation OpLoc = ConsumeToken();
2101*f4a2713aSLionel Sambuc 
2102*f4a2713aSLionel Sambuc     if (!Tok.is(tok::numeric_constant)) {
2103*f4a2713aSLionel Sambuc       const char *Symbol = 0;
2104*f4a2713aSLionel Sambuc       switch (Kind) {
2105*f4a2713aSLionel Sambuc       case tok::minus: Symbol = "-"; break;
2106*f4a2713aSLionel Sambuc       case tok::plus: Symbol = "+"; break;
2107*f4a2713aSLionel Sambuc       default: llvm_unreachable("missing unary operator case");
2108*f4a2713aSLionel Sambuc       }
2109*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_nsnumber_nonliteral_unary)
2110*f4a2713aSLionel Sambuc         << Symbol;
2111*f4a2713aSLionel Sambuc       return ExprError();
2112*f4a2713aSLionel Sambuc     }
2113*f4a2713aSLionel Sambuc 
2114*f4a2713aSLionel Sambuc     ExprResult Lit(Actions.ActOnNumericConstant(Tok));
2115*f4a2713aSLionel Sambuc     if (Lit.isInvalid()) {
2116*f4a2713aSLionel Sambuc       return Lit;
2117*f4a2713aSLionel Sambuc     }
2118*f4a2713aSLionel Sambuc     ConsumeToken(); // Consume the literal token.
2119*f4a2713aSLionel Sambuc 
2120*f4a2713aSLionel Sambuc     Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take());
2121*f4a2713aSLionel Sambuc     if (Lit.isInvalid())
2122*f4a2713aSLionel Sambuc       return Lit;
2123*f4a2713aSLionel Sambuc 
2124*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(
2125*f4a2713aSLionel Sambuc              Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
2126*f4a2713aSLionel Sambuc   }
2127*f4a2713aSLionel Sambuc 
2128*f4a2713aSLionel Sambuc   case tok::string_literal:    // primary-expression: string-literal
2129*f4a2713aSLionel Sambuc   case tok::wide_string_literal:
2130*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
2131*f4a2713aSLionel Sambuc 
2132*f4a2713aSLionel Sambuc   case tok::char_constant:
2133*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
2134*f4a2713aSLionel Sambuc 
2135*f4a2713aSLionel Sambuc   case tok::numeric_constant:
2136*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
2137*f4a2713aSLionel Sambuc 
2138*f4a2713aSLionel Sambuc   case tok::kw_true:  // Objective-C++, etc.
2139*f4a2713aSLionel Sambuc   case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
2140*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
2141*f4a2713aSLionel Sambuc   case tok::kw_false: // Objective-C++, etc.
2142*f4a2713aSLionel Sambuc   case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
2143*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
2144*f4a2713aSLionel Sambuc 
2145*f4a2713aSLionel Sambuc   case tok::l_square:
2146*f4a2713aSLionel Sambuc     // Objective-C array literal
2147*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
2148*f4a2713aSLionel Sambuc 
2149*f4a2713aSLionel Sambuc   case tok::l_brace:
2150*f4a2713aSLionel Sambuc     // Objective-C dictionary literal
2151*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
2152*f4a2713aSLionel Sambuc 
2153*f4a2713aSLionel Sambuc   case tok::l_paren:
2154*f4a2713aSLionel Sambuc     // Objective-C boxed expression
2155*f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
2156*f4a2713aSLionel Sambuc 
2157*f4a2713aSLionel Sambuc   default:
2158*f4a2713aSLionel Sambuc     if (Tok.getIdentifierInfo() == 0)
2159*f4a2713aSLionel Sambuc       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
2160*f4a2713aSLionel Sambuc 
2161*f4a2713aSLionel Sambuc     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
2162*f4a2713aSLionel Sambuc     case tok::objc_encode:
2163*f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
2164*f4a2713aSLionel Sambuc     case tok::objc_protocol:
2165*f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
2166*f4a2713aSLionel Sambuc     case tok::objc_selector:
2167*f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
2168*f4a2713aSLionel Sambuc       default: {
2169*f4a2713aSLionel Sambuc         const char *str = 0;
2170*f4a2713aSLionel Sambuc         if (GetLookAheadToken(1).is(tok::l_brace)) {
2171*f4a2713aSLionel Sambuc           char ch = Tok.getIdentifierInfo()->getNameStart()[0];
2172*f4a2713aSLionel Sambuc           str =
2173*f4a2713aSLionel Sambuc             ch == 't' ? "try"
2174*f4a2713aSLionel Sambuc                       : (ch == 'f' ? "finally"
2175*f4a2713aSLionel Sambuc                                    : (ch == 'a' ? "autoreleasepool" : 0));
2176*f4a2713aSLionel Sambuc         }
2177*f4a2713aSLionel Sambuc         if (str) {
2178*f4a2713aSLionel Sambuc           SourceLocation kwLoc = Tok.getLocation();
2179*f4a2713aSLionel Sambuc           return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
2180*f4a2713aSLionel Sambuc                              FixItHint::CreateReplacement(kwLoc, str));
2181*f4a2713aSLionel Sambuc         }
2182*f4a2713aSLionel Sambuc         else
2183*f4a2713aSLionel Sambuc           return ExprError(Diag(AtLoc, diag::err_unexpected_at));
2184*f4a2713aSLionel Sambuc       }
2185*f4a2713aSLionel Sambuc     }
2186*f4a2713aSLionel Sambuc   }
2187*f4a2713aSLionel Sambuc }
2188*f4a2713aSLionel Sambuc 
2189*f4a2713aSLionel Sambuc /// \brief Parse the receiver of an Objective-C++ message send.
2190*f4a2713aSLionel Sambuc ///
2191*f4a2713aSLionel Sambuc /// This routine parses the receiver of a message send in
2192*f4a2713aSLionel Sambuc /// Objective-C++ either as a type or as an expression. Note that this
2193*f4a2713aSLionel Sambuc /// routine must not be called to parse a send to 'super', since it
2194*f4a2713aSLionel Sambuc /// has no way to return such a result.
2195*f4a2713aSLionel Sambuc ///
2196*f4a2713aSLionel Sambuc /// \param IsExpr Whether the receiver was parsed as an expression.
2197*f4a2713aSLionel Sambuc ///
2198*f4a2713aSLionel Sambuc /// \param TypeOrExpr If the receiver was parsed as an expression (\c
2199*f4a2713aSLionel Sambuc /// IsExpr is true), the parsed expression. If the receiver was parsed
2200*f4a2713aSLionel Sambuc /// as a type (\c IsExpr is false), the parsed type.
2201*f4a2713aSLionel Sambuc ///
2202*f4a2713aSLionel Sambuc /// \returns True if an error occurred during parsing or semantic
2203*f4a2713aSLionel Sambuc /// analysis, in which case the arguments do not have valid
2204*f4a2713aSLionel Sambuc /// values. Otherwise, returns false for a successful parse.
2205*f4a2713aSLionel Sambuc ///
2206*f4a2713aSLionel Sambuc ///   objc-receiver: [C++]
2207*f4a2713aSLionel Sambuc ///     'super' [not parsed here]
2208*f4a2713aSLionel Sambuc ///     expression
2209*f4a2713aSLionel Sambuc ///     simple-type-specifier
2210*f4a2713aSLionel Sambuc ///     typename-specifier
2211*f4a2713aSLionel Sambuc bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
2212*f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2213*f4a2713aSLionel Sambuc 
2214*f4a2713aSLionel Sambuc   if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
2215*f4a2713aSLionel Sambuc       Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
2216*f4a2713aSLionel Sambuc     TryAnnotateTypeOrScopeToken();
2217*f4a2713aSLionel Sambuc 
2218*f4a2713aSLionel Sambuc   if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
2219*f4a2713aSLionel Sambuc     //   objc-receiver:
2220*f4a2713aSLionel Sambuc     //     expression
2221*f4a2713aSLionel Sambuc     ExprResult Receiver = ParseExpression();
2222*f4a2713aSLionel Sambuc     if (Receiver.isInvalid())
2223*f4a2713aSLionel Sambuc       return true;
2224*f4a2713aSLionel Sambuc 
2225*f4a2713aSLionel Sambuc     IsExpr = true;
2226*f4a2713aSLionel Sambuc     TypeOrExpr = Receiver.take();
2227*f4a2713aSLionel Sambuc     return false;
2228*f4a2713aSLionel Sambuc   }
2229*f4a2713aSLionel Sambuc 
2230*f4a2713aSLionel Sambuc   // objc-receiver:
2231*f4a2713aSLionel Sambuc   //   typename-specifier
2232*f4a2713aSLionel Sambuc   //   simple-type-specifier
2233*f4a2713aSLionel Sambuc   //   expression (that starts with one of the above)
2234*f4a2713aSLionel Sambuc   DeclSpec DS(AttrFactory);
2235*f4a2713aSLionel Sambuc   ParseCXXSimpleTypeSpecifier(DS);
2236*f4a2713aSLionel Sambuc 
2237*f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren)) {
2238*f4a2713aSLionel Sambuc     // If we see an opening parentheses at this point, we are
2239*f4a2713aSLionel Sambuc     // actually parsing an expression that starts with a
2240*f4a2713aSLionel Sambuc     // function-style cast, e.g.,
2241*f4a2713aSLionel Sambuc     //
2242*f4a2713aSLionel Sambuc     //   postfix-expression:
2243*f4a2713aSLionel Sambuc     //     simple-type-specifier ( expression-list [opt] )
2244*f4a2713aSLionel Sambuc     //     typename-specifier ( expression-list [opt] )
2245*f4a2713aSLionel Sambuc     //
2246*f4a2713aSLionel Sambuc     // Parse the remainder of this case, then the (optional)
2247*f4a2713aSLionel Sambuc     // postfix-expression suffix, followed by the (optional)
2248*f4a2713aSLionel Sambuc     // right-hand side of the binary expression. We have an
2249*f4a2713aSLionel Sambuc     // instance method.
2250*f4a2713aSLionel Sambuc     ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
2251*f4a2713aSLionel Sambuc     if (!Receiver.isInvalid())
2252*f4a2713aSLionel Sambuc       Receiver = ParsePostfixExpressionSuffix(Receiver.take());
2253*f4a2713aSLionel Sambuc     if (!Receiver.isInvalid())
2254*f4a2713aSLionel Sambuc       Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma);
2255*f4a2713aSLionel Sambuc     if (Receiver.isInvalid())
2256*f4a2713aSLionel Sambuc       return true;
2257*f4a2713aSLionel Sambuc 
2258*f4a2713aSLionel Sambuc     IsExpr = true;
2259*f4a2713aSLionel Sambuc     TypeOrExpr = Receiver.take();
2260*f4a2713aSLionel Sambuc     return false;
2261*f4a2713aSLionel Sambuc   }
2262*f4a2713aSLionel Sambuc 
2263*f4a2713aSLionel Sambuc   // We have a class message. Turn the simple-type-specifier or
2264*f4a2713aSLionel Sambuc   // typename-specifier we parsed into a type and parse the
2265*f4a2713aSLionel Sambuc   // remainder of the class message.
2266*f4a2713aSLionel Sambuc   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
2267*f4a2713aSLionel Sambuc   TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
2268*f4a2713aSLionel Sambuc   if (Type.isInvalid())
2269*f4a2713aSLionel Sambuc     return true;
2270*f4a2713aSLionel Sambuc 
2271*f4a2713aSLionel Sambuc   IsExpr = false;
2272*f4a2713aSLionel Sambuc   TypeOrExpr = Type.get().getAsOpaquePtr();
2273*f4a2713aSLionel Sambuc   return false;
2274*f4a2713aSLionel Sambuc }
2275*f4a2713aSLionel Sambuc 
2276*f4a2713aSLionel Sambuc /// \brief Determine whether the parser is currently referring to a an
2277*f4a2713aSLionel Sambuc /// Objective-C message send, using a simplified heuristic to avoid overhead.
2278*f4a2713aSLionel Sambuc ///
2279*f4a2713aSLionel Sambuc /// This routine will only return true for a subset of valid message-send
2280*f4a2713aSLionel Sambuc /// expressions.
2281*f4a2713aSLionel Sambuc bool Parser::isSimpleObjCMessageExpression() {
2282*f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_square) && getLangOpts().ObjC1 &&
2283*f4a2713aSLionel Sambuc          "Incorrect start for isSimpleObjCMessageExpression");
2284*f4a2713aSLionel Sambuc   return GetLookAheadToken(1).is(tok::identifier) &&
2285*f4a2713aSLionel Sambuc          GetLookAheadToken(2).is(tok::identifier);
2286*f4a2713aSLionel Sambuc }
2287*f4a2713aSLionel Sambuc 
2288*f4a2713aSLionel Sambuc bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
2289*f4a2713aSLionel Sambuc   if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) ||
2290*f4a2713aSLionel Sambuc       InMessageExpression)
2291*f4a2713aSLionel Sambuc     return false;
2292*f4a2713aSLionel Sambuc 
2293*f4a2713aSLionel Sambuc 
2294*f4a2713aSLionel Sambuc   ParsedType Type;
2295*f4a2713aSLionel Sambuc 
2296*f4a2713aSLionel Sambuc   if (Tok.is(tok::annot_typename))
2297*f4a2713aSLionel Sambuc     Type = getTypeAnnotation(Tok);
2298*f4a2713aSLionel Sambuc   else if (Tok.is(tok::identifier))
2299*f4a2713aSLionel Sambuc     Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
2300*f4a2713aSLionel Sambuc                                getCurScope());
2301*f4a2713aSLionel Sambuc   else
2302*f4a2713aSLionel Sambuc     return false;
2303*f4a2713aSLionel Sambuc 
2304*f4a2713aSLionel Sambuc   if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
2305*f4a2713aSLionel Sambuc     const Token &AfterNext = GetLookAheadToken(2);
2306*f4a2713aSLionel Sambuc     if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) {
2307*f4a2713aSLionel Sambuc       if (Tok.is(tok::identifier))
2308*f4a2713aSLionel Sambuc         TryAnnotateTypeOrScopeToken();
2309*f4a2713aSLionel Sambuc 
2310*f4a2713aSLionel Sambuc       return Tok.is(tok::annot_typename);
2311*f4a2713aSLionel Sambuc     }
2312*f4a2713aSLionel Sambuc   }
2313*f4a2713aSLionel Sambuc 
2314*f4a2713aSLionel Sambuc   return false;
2315*f4a2713aSLionel Sambuc }
2316*f4a2713aSLionel Sambuc 
2317*f4a2713aSLionel Sambuc ///   objc-message-expr:
2318*f4a2713aSLionel Sambuc ///     '[' objc-receiver objc-message-args ']'
2319*f4a2713aSLionel Sambuc ///
2320*f4a2713aSLionel Sambuc ///   objc-receiver: [C]
2321*f4a2713aSLionel Sambuc ///     'super'
2322*f4a2713aSLionel Sambuc ///     expression
2323*f4a2713aSLionel Sambuc ///     class-name
2324*f4a2713aSLionel Sambuc ///     type-name
2325*f4a2713aSLionel Sambuc ///
2326*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCMessageExpression() {
2327*f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_square) && "'[' expected");
2328*f4a2713aSLionel Sambuc   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
2329*f4a2713aSLionel Sambuc 
2330*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2331*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMessageReceiver(getCurScope());
2332*f4a2713aSLionel Sambuc     cutOffParsing();
2333*f4a2713aSLionel Sambuc     return ExprError();
2334*f4a2713aSLionel Sambuc   }
2335*f4a2713aSLionel Sambuc 
2336*f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2337*f4a2713aSLionel Sambuc 
2338*f4a2713aSLionel Sambuc   if (getLangOpts().CPlusPlus) {
2339*f4a2713aSLionel Sambuc     // We completely separate the C and C++ cases because C++ requires
2340*f4a2713aSLionel Sambuc     // more complicated (read: slower) parsing.
2341*f4a2713aSLionel Sambuc 
2342*f4a2713aSLionel Sambuc     // Handle send to super.
2343*f4a2713aSLionel Sambuc     // FIXME: This doesn't benefit from the same typo-correction we
2344*f4a2713aSLionel Sambuc     // get in Objective-C.
2345*f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
2346*f4a2713aSLionel Sambuc         NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
2347*f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
2348*f4a2713aSLionel Sambuc                                             ParsedType(), 0);
2349*f4a2713aSLionel Sambuc 
2350*f4a2713aSLionel Sambuc     // Parse the receiver, which is either a type or an expression.
2351*f4a2713aSLionel Sambuc     bool IsExpr;
2352*f4a2713aSLionel Sambuc     void *TypeOrExpr = NULL;
2353*f4a2713aSLionel Sambuc     if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
2354*f4a2713aSLionel Sambuc       SkipUntil(tok::r_square, StopAtSemi);
2355*f4a2713aSLionel Sambuc       return ExprError();
2356*f4a2713aSLionel Sambuc     }
2357*f4a2713aSLionel Sambuc 
2358*f4a2713aSLionel Sambuc     if (IsExpr)
2359*f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2360*f4a2713aSLionel Sambuc                                             ParsedType(),
2361*f4a2713aSLionel Sambuc                                             static_cast<Expr*>(TypeOrExpr));
2362*f4a2713aSLionel Sambuc 
2363*f4a2713aSLionel Sambuc     return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2364*f4a2713aSLionel Sambuc                               ParsedType::getFromOpaquePtr(TypeOrExpr),
2365*f4a2713aSLionel Sambuc                                           0);
2366*f4a2713aSLionel Sambuc   }
2367*f4a2713aSLionel Sambuc 
2368*f4a2713aSLionel Sambuc   if (Tok.is(tok::identifier)) {
2369*f4a2713aSLionel Sambuc     IdentifierInfo *Name = Tok.getIdentifierInfo();
2370*f4a2713aSLionel Sambuc     SourceLocation NameLoc = Tok.getLocation();
2371*f4a2713aSLionel Sambuc     ParsedType ReceiverType;
2372*f4a2713aSLionel Sambuc     switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
2373*f4a2713aSLionel Sambuc                                        Name == Ident_super,
2374*f4a2713aSLionel Sambuc                                        NextToken().is(tok::period),
2375*f4a2713aSLionel Sambuc                                        ReceiverType)) {
2376*f4a2713aSLionel Sambuc     case Sema::ObjCSuperMessage:
2377*f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
2378*f4a2713aSLionel Sambuc                                             ParsedType(), 0);
2379*f4a2713aSLionel Sambuc 
2380*f4a2713aSLionel Sambuc     case Sema::ObjCClassMessage:
2381*f4a2713aSLionel Sambuc       if (!ReceiverType) {
2382*f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2383*f4a2713aSLionel Sambuc         return ExprError();
2384*f4a2713aSLionel Sambuc       }
2385*f4a2713aSLionel Sambuc 
2386*f4a2713aSLionel Sambuc       ConsumeToken(); // the type name
2387*f4a2713aSLionel Sambuc 
2388*f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2389*f4a2713aSLionel Sambuc                                             ReceiverType, 0);
2390*f4a2713aSLionel Sambuc 
2391*f4a2713aSLionel Sambuc     case Sema::ObjCInstanceMessage:
2392*f4a2713aSLionel Sambuc       // Fall through to parse an expression.
2393*f4a2713aSLionel Sambuc       break;
2394*f4a2713aSLionel Sambuc     }
2395*f4a2713aSLionel Sambuc   }
2396*f4a2713aSLionel Sambuc 
2397*f4a2713aSLionel Sambuc   // Otherwise, an arbitrary expression can be the receiver of a send.
2398*f4a2713aSLionel Sambuc   ExprResult Res(ParseExpression());
2399*f4a2713aSLionel Sambuc   if (Res.isInvalid()) {
2400*f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2401*f4a2713aSLionel Sambuc     return Res;
2402*f4a2713aSLionel Sambuc   }
2403*f4a2713aSLionel Sambuc 
2404*f4a2713aSLionel Sambuc   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2405*f4a2713aSLionel Sambuc                                         ParsedType(), Res.take());
2406*f4a2713aSLionel Sambuc }
2407*f4a2713aSLionel Sambuc 
2408*f4a2713aSLionel Sambuc /// \brief Parse the remainder of an Objective-C message following the
2409*f4a2713aSLionel Sambuc /// '[' objc-receiver.
2410*f4a2713aSLionel Sambuc ///
2411*f4a2713aSLionel Sambuc /// This routine handles sends to super, class messages (sent to a
2412*f4a2713aSLionel Sambuc /// class name), and instance messages (sent to an object), and the
2413*f4a2713aSLionel Sambuc /// target is represented by \p SuperLoc, \p ReceiverType, or \p
2414*f4a2713aSLionel Sambuc /// ReceiverExpr, respectively. Only one of these parameters may have
2415*f4a2713aSLionel Sambuc /// a valid value.
2416*f4a2713aSLionel Sambuc ///
2417*f4a2713aSLionel Sambuc /// \param LBracLoc The location of the opening '['.
2418*f4a2713aSLionel Sambuc ///
2419*f4a2713aSLionel Sambuc /// \param SuperLoc If this is a send to 'super', the location of the
2420*f4a2713aSLionel Sambuc /// 'super' keyword that indicates a send to the superclass.
2421*f4a2713aSLionel Sambuc ///
2422*f4a2713aSLionel Sambuc /// \param ReceiverType If this is a class message, the type of the
2423*f4a2713aSLionel Sambuc /// class we are sending a message to.
2424*f4a2713aSLionel Sambuc ///
2425*f4a2713aSLionel Sambuc /// \param ReceiverExpr If this is an instance message, the expression
2426*f4a2713aSLionel Sambuc /// used to compute the receiver object.
2427*f4a2713aSLionel Sambuc ///
2428*f4a2713aSLionel Sambuc ///   objc-message-args:
2429*f4a2713aSLionel Sambuc ///     objc-selector
2430*f4a2713aSLionel Sambuc ///     objc-keywordarg-list
2431*f4a2713aSLionel Sambuc ///
2432*f4a2713aSLionel Sambuc ///   objc-keywordarg-list:
2433*f4a2713aSLionel Sambuc ///     objc-keywordarg
2434*f4a2713aSLionel Sambuc ///     objc-keywordarg-list objc-keywordarg
2435*f4a2713aSLionel Sambuc ///
2436*f4a2713aSLionel Sambuc ///   objc-keywordarg:
2437*f4a2713aSLionel Sambuc ///     selector-name[opt] ':' objc-keywordexpr
2438*f4a2713aSLionel Sambuc ///
2439*f4a2713aSLionel Sambuc ///   objc-keywordexpr:
2440*f4a2713aSLionel Sambuc ///     nonempty-expr-list
2441*f4a2713aSLionel Sambuc ///
2442*f4a2713aSLionel Sambuc ///   nonempty-expr-list:
2443*f4a2713aSLionel Sambuc ///     assignment-expression
2444*f4a2713aSLionel Sambuc ///     nonempty-expr-list , assignment-expression
2445*f4a2713aSLionel Sambuc ///
2446*f4a2713aSLionel Sambuc ExprResult
2447*f4a2713aSLionel Sambuc Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
2448*f4a2713aSLionel Sambuc                                        SourceLocation SuperLoc,
2449*f4a2713aSLionel Sambuc                                        ParsedType ReceiverType,
2450*f4a2713aSLionel Sambuc                                        ExprArg ReceiverExpr) {
2451*f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2452*f4a2713aSLionel Sambuc 
2453*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2454*f4a2713aSLionel Sambuc     if (SuperLoc.isValid())
2455*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
2456*f4a2713aSLionel Sambuc                                            false);
2457*f4a2713aSLionel Sambuc     else if (ReceiverType)
2458*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
2459*f4a2713aSLionel Sambuc                                            false);
2460*f4a2713aSLionel Sambuc     else
2461*f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2462*f4a2713aSLionel Sambuc                                               None, false);
2463*f4a2713aSLionel Sambuc     cutOffParsing();
2464*f4a2713aSLionel Sambuc     return ExprError();
2465*f4a2713aSLionel Sambuc   }
2466*f4a2713aSLionel Sambuc 
2467*f4a2713aSLionel Sambuc   // Parse objc-selector
2468*f4a2713aSLionel Sambuc   SourceLocation Loc;
2469*f4a2713aSLionel Sambuc   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
2470*f4a2713aSLionel Sambuc 
2471*f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
2472*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 12> KeyLocs;
2473*f4a2713aSLionel Sambuc   ExprVector KeyExprs;
2474*f4a2713aSLionel Sambuc 
2475*f4a2713aSLionel Sambuc   if (Tok.is(tok::colon)) {
2476*f4a2713aSLionel Sambuc     while (1) {
2477*f4a2713aSLionel Sambuc       // Each iteration parses a single keyword argument.
2478*f4a2713aSLionel Sambuc       KeyIdents.push_back(selIdent);
2479*f4a2713aSLionel Sambuc       KeyLocs.push_back(Loc);
2480*f4a2713aSLionel Sambuc 
2481*f4a2713aSLionel Sambuc       if (Tok.isNot(tok::colon)) {
2482*f4a2713aSLionel Sambuc         Diag(Tok, diag::err_expected_colon);
2483*f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2484*f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2485*f4a2713aSLionel Sambuc         // the enclosing expression.
2486*f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2487*f4a2713aSLionel Sambuc         return ExprError();
2488*f4a2713aSLionel Sambuc       }
2489*f4a2713aSLionel Sambuc 
2490*f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the ':'.
2491*f4a2713aSLionel Sambuc       ///  Parse the expression after ':'
2492*f4a2713aSLionel Sambuc 
2493*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2494*f4a2713aSLionel Sambuc         if (SuperLoc.isValid())
2495*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
2496*f4a2713aSLionel Sambuc                                                KeyIdents,
2497*f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/true);
2498*f4a2713aSLionel Sambuc         else if (ReceiverType)
2499*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
2500*f4a2713aSLionel Sambuc                                                KeyIdents,
2501*f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/true);
2502*f4a2713aSLionel Sambuc         else
2503*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2504*f4a2713aSLionel Sambuc                                                   KeyIdents,
2505*f4a2713aSLionel Sambuc                                                   /*AtArgumentEpression=*/true);
2506*f4a2713aSLionel Sambuc 
2507*f4a2713aSLionel Sambuc         cutOffParsing();
2508*f4a2713aSLionel Sambuc         return ExprError();
2509*f4a2713aSLionel Sambuc       }
2510*f4a2713aSLionel Sambuc 
2511*f4a2713aSLionel Sambuc       ExprResult Expr;
2512*f4a2713aSLionel Sambuc       if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
2513*f4a2713aSLionel Sambuc         Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
2514*f4a2713aSLionel Sambuc         Expr = ParseBraceInitializer();
2515*f4a2713aSLionel Sambuc       } else
2516*f4a2713aSLionel Sambuc         Expr = ParseAssignmentExpression();
2517*f4a2713aSLionel Sambuc 
2518*f4a2713aSLionel Sambuc       ExprResult Res(Expr);
2519*f4a2713aSLionel Sambuc       if (Res.isInvalid()) {
2520*f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2521*f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2522*f4a2713aSLionel Sambuc         // the enclosing expression.
2523*f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2524*f4a2713aSLionel Sambuc         return Res;
2525*f4a2713aSLionel Sambuc       }
2526*f4a2713aSLionel Sambuc 
2527*f4a2713aSLionel Sambuc       // We have a valid expression.
2528*f4a2713aSLionel Sambuc       KeyExprs.push_back(Res.release());
2529*f4a2713aSLionel Sambuc 
2530*f4a2713aSLionel Sambuc       // Code completion after each argument.
2531*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2532*f4a2713aSLionel Sambuc         if (SuperLoc.isValid())
2533*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
2534*f4a2713aSLionel Sambuc                                                KeyIdents,
2535*f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/false);
2536*f4a2713aSLionel Sambuc         else if (ReceiverType)
2537*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
2538*f4a2713aSLionel Sambuc                                                KeyIdents,
2539*f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/false);
2540*f4a2713aSLionel Sambuc         else
2541*f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2542*f4a2713aSLionel Sambuc                                                   KeyIdents,
2543*f4a2713aSLionel Sambuc                                                 /*AtArgumentEpression=*/false);
2544*f4a2713aSLionel Sambuc         cutOffParsing();
2545*f4a2713aSLionel Sambuc         return ExprError();
2546*f4a2713aSLionel Sambuc       }
2547*f4a2713aSLionel Sambuc 
2548*f4a2713aSLionel Sambuc       // Check for another keyword selector.
2549*f4a2713aSLionel Sambuc       selIdent = ParseObjCSelectorPiece(Loc);
2550*f4a2713aSLionel Sambuc       if (!selIdent && Tok.isNot(tok::colon))
2551*f4a2713aSLionel Sambuc         break;
2552*f4a2713aSLionel Sambuc       // We have a selector or a colon, continue parsing.
2553*f4a2713aSLionel Sambuc     }
2554*f4a2713aSLionel Sambuc     // Parse the, optional, argument list, comma separated.
2555*f4a2713aSLionel Sambuc     while (Tok.is(tok::comma)) {
2556*f4a2713aSLionel Sambuc       SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
2557*f4a2713aSLionel Sambuc       ///  Parse the expression after ','
2558*f4a2713aSLionel Sambuc       ExprResult Res(ParseAssignmentExpression());
2559*f4a2713aSLionel Sambuc       if (Res.isInvalid()) {
2560*f4a2713aSLionel Sambuc         if (Tok.is(tok::colon)) {
2561*f4a2713aSLionel Sambuc           Diag(commaLoc, diag::note_extra_comma_message_arg) <<
2562*f4a2713aSLionel Sambuc             FixItHint::CreateRemoval(commaLoc);
2563*f4a2713aSLionel Sambuc         }
2564*f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2565*f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2566*f4a2713aSLionel Sambuc         // the enclosing expression.
2567*f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2568*f4a2713aSLionel Sambuc         return Res;
2569*f4a2713aSLionel Sambuc       }
2570*f4a2713aSLionel Sambuc 
2571*f4a2713aSLionel Sambuc       // We have a valid expression.
2572*f4a2713aSLionel Sambuc       KeyExprs.push_back(Res.release());
2573*f4a2713aSLionel Sambuc     }
2574*f4a2713aSLionel Sambuc   } else if (!selIdent) {
2575*f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_ident); // missing selector name.
2576*f4a2713aSLionel Sambuc 
2577*f4a2713aSLionel Sambuc     // We must manually skip to a ']', otherwise the expression skipper will
2578*f4a2713aSLionel Sambuc     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2579*f4a2713aSLionel Sambuc     // the enclosing expression.
2580*f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2581*f4a2713aSLionel Sambuc     return ExprError();
2582*f4a2713aSLionel Sambuc   }
2583*f4a2713aSLionel Sambuc 
2584*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::r_square)) {
2585*f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier))
2586*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_colon);
2587*f4a2713aSLionel Sambuc     else
2588*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_rsquare);
2589*f4a2713aSLionel Sambuc     // We must manually skip to a ']', otherwise the expression skipper will
2590*f4a2713aSLionel Sambuc     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2591*f4a2713aSLionel Sambuc     // the enclosing expression.
2592*f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2593*f4a2713aSLionel Sambuc     return ExprError();
2594*f4a2713aSLionel Sambuc   }
2595*f4a2713aSLionel Sambuc 
2596*f4a2713aSLionel Sambuc   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
2597*f4a2713aSLionel Sambuc 
2598*f4a2713aSLionel Sambuc   unsigned nKeys = KeyIdents.size();
2599*f4a2713aSLionel Sambuc   if (nKeys == 0) {
2600*f4a2713aSLionel Sambuc     KeyIdents.push_back(selIdent);
2601*f4a2713aSLionel Sambuc     KeyLocs.push_back(Loc);
2602*f4a2713aSLionel Sambuc   }
2603*f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
2604*f4a2713aSLionel Sambuc 
2605*f4a2713aSLionel Sambuc   if (SuperLoc.isValid())
2606*f4a2713aSLionel Sambuc     return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
2607*f4a2713aSLionel Sambuc                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2608*f4a2713aSLionel Sambuc   else if (ReceiverType)
2609*f4a2713aSLionel Sambuc     return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
2610*f4a2713aSLionel Sambuc                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2611*f4a2713aSLionel Sambuc   return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
2612*f4a2713aSLionel Sambuc                                       LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2613*f4a2713aSLionel Sambuc }
2614*f4a2713aSLionel Sambuc 
2615*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
2616*f4a2713aSLionel Sambuc   ExprResult Res(ParseStringLiteralExpression());
2617*f4a2713aSLionel Sambuc   if (Res.isInvalid()) return Res;
2618*f4a2713aSLionel Sambuc 
2619*f4a2713aSLionel Sambuc   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
2620*f4a2713aSLionel Sambuc   // expressions.  At this point, we know that the only valid thing that starts
2621*f4a2713aSLionel Sambuc   // with '@' is an @"".
2622*f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 4> AtLocs;
2623*f4a2713aSLionel Sambuc   ExprVector AtStrings;
2624*f4a2713aSLionel Sambuc   AtLocs.push_back(AtLoc);
2625*f4a2713aSLionel Sambuc   AtStrings.push_back(Res.release());
2626*f4a2713aSLionel Sambuc 
2627*f4a2713aSLionel Sambuc   while (Tok.is(tok::at)) {
2628*f4a2713aSLionel Sambuc     AtLocs.push_back(ConsumeToken()); // eat the @.
2629*f4a2713aSLionel Sambuc 
2630*f4a2713aSLionel Sambuc     // Invalid unless there is a string literal.
2631*f4a2713aSLionel Sambuc     if (!isTokenStringLiteral())
2632*f4a2713aSLionel Sambuc       return ExprError(Diag(Tok, diag::err_objc_concat_string));
2633*f4a2713aSLionel Sambuc 
2634*f4a2713aSLionel Sambuc     ExprResult Lit(ParseStringLiteralExpression());
2635*f4a2713aSLionel Sambuc     if (Lit.isInvalid())
2636*f4a2713aSLionel Sambuc       return Lit;
2637*f4a2713aSLionel Sambuc 
2638*f4a2713aSLionel Sambuc     AtStrings.push_back(Lit.release());
2639*f4a2713aSLionel Sambuc   }
2640*f4a2713aSLionel Sambuc 
2641*f4a2713aSLionel Sambuc   return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(),
2642*f4a2713aSLionel Sambuc                                         AtStrings.size());
2643*f4a2713aSLionel Sambuc }
2644*f4a2713aSLionel Sambuc 
2645*f4a2713aSLionel Sambuc /// ParseObjCBooleanLiteral -
2646*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' boolean-keyword
2647*f4a2713aSLionel Sambuc ///                        ;
2648*f4a2713aSLionel Sambuc /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
2649*f4a2713aSLionel Sambuc ///                        ;
2650*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
2651*f4a2713aSLionel Sambuc                                            bool ArgValue) {
2652*f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeToken();             // consume the keyword.
2653*f4a2713aSLionel Sambuc   return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
2654*f4a2713aSLionel Sambuc }
2655*f4a2713aSLionel Sambuc 
2656*f4a2713aSLionel Sambuc /// ParseObjCCharacterLiteral -
2657*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' character-literal
2658*f4a2713aSLionel Sambuc ///                        ;
2659*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
2660*f4a2713aSLionel Sambuc   ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
2661*f4a2713aSLionel Sambuc   if (Lit.isInvalid()) {
2662*f4a2713aSLionel Sambuc     return Lit;
2663*f4a2713aSLionel Sambuc   }
2664*f4a2713aSLionel Sambuc   ConsumeToken(); // Consume the literal token.
2665*f4a2713aSLionel Sambuc   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take());
2666*f4a2713aSLionel Sambuc }
2667*f4a2713aSLionel Sambuc 
2668*f4a2713aSLionel Sambuc /// ParseObjCNumericLiteral -
2669*f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' scalar-literal
2670*f4a2713aSLionel Sambuc ///                        ;
2671*f4a2713aSLionel Sambuc /// scalar-literal : | numeric-constant			/* any numeric constant. */
2672*f4a2713aSLionel Sambuc ///                    ;
2673*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
2674*f4a2713aSLionel Sambuc   ExprResult Lit(Actions.ActOnNumericConstant(Tok));
2675*f4a2713aSLionel Sambuc   if (Lit.isInvalid()) {
2676*f4a2713aSLionel Sambuc     return Lit;
2677*f4a2713aSLionel Sambuc   }
2678*f4a2713aSLionel Sambuc   ConsumeToken(); // Consume the literal token.
2679*f4a2713aSLionel Sambuc   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take());
2680*f4a2713aSLionel Sambuc }
2681*f4a2713aSLionel Sambuc 
2682*f4a2713aSLionel Sambuc /// ParseObjCBoxedExpr -
2683*f4a2713aSLionel Sambuc /// objc-box-expression:
2684*f4a2713aSLionel Sambuc ///       @( assignment-expression )
2685*f4a2713aSLionel Sambuc ExprResult
2686*f4a2713aSLionel Sambuc Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
2687*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2688*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");
2689*f4a2713aSLionel Sambuc 
2690*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2691*f4a2713aSLionel Sambuc   T.consumeOpen();
2692*f4a2713aSLionel Sambuc   ExprResult ValueExpr(ParseAssignmentExpression());
2693*f4a2713aSLionel Sambuc   if (T.consumeClose())
2694*f4a2713aSLionel Sambuc     return ExprError();
2695*f4a2713aSLionel Sambuc 
2696*f4a2713aSLionel Sambuc   if (ValueExpr.isInvalid())
2697*f4a2713aSLionel Sambuc     return ExprError();
2698*f4a2713aSLionel Sambuc 
2699*f4a2713aSLionel Sambuc   // Wrap the sub-expression in a parenthesized expression, to distinguish
2700*f4a2713aSLionel Sambuc   // a boxed expression from a literal.
2701*f4a2713aSLionel Sambuc   SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
2702*f4a2713aSLionel Sambuc   ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take());
2703*f4a2713aSLionel Sambuc   return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
2704*f4a2713aSLionel Sambuc                                     ValueExpr.take());
2705*f4a2713aSLionel Sambuc }
2706*f4a2713aSLionel Sambuc 
2707*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
2708*f4a2713aSLionel Sambuc   ExprVector ElementExprs;                   // array elements.
2709*f4a2713aSLionel Sambuc   ConsumeBracket(); // consume the l_square.
2710*f4a2713aSLionel Sambuc 
2711*f4a2713aSLionel Sambuc   while (Tok.isNot(tok::r_square)) {
2712*f4a2713aSLionel Sambuc     // Parse list of array element expressions (all must be id types).
2713*f4a2713aSLionel Sambuc     ExprResult Res(ParseAssignmentExpression());
2714*f4a2713aSLionel Sambuc     if (Res.isInvalid()) {
2715*f4a2713aSLionel Sambuc       // We must manually skip to a ']', otherwise the expression skipper will
2716*f4a2713aSLionel Sambuc       // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2717*f4a2713aSLionel Sambuc       // the enclosing expression.
2718*f4a2713aSLionel Sambuc       SkipUntil(tok::r_square, StopAtSemi);
2719*f4a2713aSLionel Sambuc       return Res;
2720*f4a2713aSLionel Sambuc     }
2721*f4a2713aSLionel Sambuc 
2722*f4a2713aSLionel Sambuc     // Parse the ellipsis that indicates a pack expansion.
2723*f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis))
2724*f4a2713aSLionel Sambuc       Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
2725*f4a2713aSLionel Sambuc     if (Res.isInvalid())
2726*f4a2713aSLionel Sambuc       return true;
2727*f4a2713aSLionel Sambuc 
2728*f4a2713aSLionel Sambuc     ElementExprs.push_back(Res.release());
2729*f4a2713aSLionel Sambuc 
2730*f4a2713aSLionel Sambuc     if (Tok.is(tok::comma))
2731*f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the ','.
2732*f4a2713aSLionel Sambuc     else if (Tok.isNot(tok::r_square))
2733*f4a2713aSLionel Sambuc      return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma));
2734*f4a2713aSLionel Sambuc   }
2735*f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeBracket(); // location of ']'
2736*f4a2713aSLionel Sambuc   MultiExprArg Args(ElementExprs);
2737*f4a2713aSLionel Sambuc   return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
2738*f4a2713aSLionel Sambuc }
2739*f4a2713aSLionel Sambuc 
2740*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
2741*f4a2713aSLionel Sambuc   SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
2742*f4a2713aSLionel Sambuc   ConsumeBrace(); // consume the l_square.
2743*f4a2713aSLionel Sambuc   while (Tok.isNot(tok::r_brace)) {
2744*f4a2713aSLionel Sambuc     // Parse the comma separated key : value expressions.
2745*f4a2713aSLionel Sambuc     ExprResult KeyExpr;
2746*f4a2713aSLionel Sambuc     {
2747*f4a2713aSLionel Sambuc       ColonProtectionRAIIObject X(*this);
2748*f4a2713aSLionel Sambuc       KeyExpr = ParseAssignmentExpression();
2749*f4a2713aSLionel Sambuc       if (KeyExpr.isInvalid()) {
2750*f4a2713aSLionel Sambuc         // We must manually skip to a '}', otherwise the expression skipper will
2751*f4a2713aSLionel Sambuc         // stop at the '}' when it skips to the ';'.  We want it to skip beyond
2752*f4a2713aSLionel Sambuc         // the enclosing expression.
2753*f4a2713aSLionel Sambuc         SkipUntil(tok::r_brace, StopAtSemi);
2754*f4a2713aSLionel Sambuc         return KeyExpr;
2755*f4a2713aSLionel Sambuc       }
2756*f4a2713aSLionel Sambuc     }
2757*f4a2713aSLionel Sambuc 
2758*f4a2713aSLionel Sambuc     if (Tok.is(tok::colon)) {
2759*f4a2713aSLionel Sambuc       ConsumeToken();
2760*f4a2713aSLionel Sambuc     } else {
2761*f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_colon);
2762*f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi);
2763*f4a2713aSLionel Sambuc       return ExprError();
2764*f4a2713aSLionel Sambuc     }
2765*f4a2713aSLionel Sambuc 
2766*f4a2713aSLionel Sambuc     ExprResult ValueExpr(ParseAssignmentExpression());
2767*f4a2713aSLionel Sambuc     if (ValueExpr.isInvalid()) {
2768*f4a2713aSLionel Sambuc       // We must manually skip to a '}', otherwise the expression skipper will
2769*f4a2713aSLionel Sambuc       // stop at the '}' when it skips to the ';'.  We want it to skip beyond
2770*f4a2713aSLionel Sambuc       // the enclosing expression.
2771*f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi);
2772*f4a2713aSLionel Sambuc       return ValueExpr;
2773*f4a2713aSLionel Sambuc     }
2774*f4a2713aSLionel Sambuc 
2775*f4a2713aSLionel Sambuc     // Parse the ellipsis that designates this as a pack expansion.
2776*f4a2713aSLionel Sambuc     SourceLocation EllipsisLoc;
2777*f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus)
2778*f4a2713aSLionel Sambuc       EllipsisLoc = ConsumeToken();
2779*f4a2713aSLionel Sambuc 
2780*f4a2713aSLionel Sambuc     // We have a valid expression. Collect it in a vector so we can
2781*f4a2713aSLionel Sambuc     // build the argument list.
2782*f4a2713aSLionel Sambuc     ObjCDictionaryElement Element = {
2783*f4a2713aSLionel Sambuc       KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
2784*f4a2713aSLionel Sambuc     };
2785*f4a2713aSLionel Sambuc     Elements.push_back(Element);
2786*f4a2713aSLionel Sambuc 
2787*f4a2713aSLionel Sambuc     if (Tok.is(tok::comma))
2788*f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the ','.
2789*f4a2713aSLionel Sambuc     else if (Tok.isNot(tok::r_brace))
2790*f4a2713aSLionel Sambuc       return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma));
2791*f4a2713aSLionel Sambuc   }
2792*f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeBrace();
2793*f4a2713aSLionel Sambuc 
2794*f4a2713aSLionel Sambuc   // Create the ObjCDictionaryLiteral.
2795*f4a2713aSLionel Sambuc   return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
2796*f4a2713aSLionel Sambuc                                             Elements.data(), Elements.size());
2797*f4a2713aSLionel Sambuc }
2798*f4a2713aSLionel Sambuc 
2799*f4a2713aSLionel Sambuc ///    objc-encode-expression:
2800*f4a2713aSLionel Sambuc ///      \@encode ( type-name )
2801*f4a2713aSLionel Sambuc ExprResult
2802*f4a2713aSLionel Sambuc Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
2803*f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
2804*f4a2713aSLionel Sambuc 
2805*f4a2713aSLionel Sambuc   SourceLocation EncLoc = ConsumeToken();
2806*f4a2713aSLionel Sambuc 
2807*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2808*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
2809*f4a2713aSLionel Sambuc 
2810*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2811*f4a2713aSLionel Sambuc   T.consumeOpen();
2812*f4a2713aSLionel Sambuc 
2813*f4a2713aSLionel Sambuc   TypeResult Ty = ParseTypeName();
2814*f4a2713aSLionel Sambuc 
2815*f4a2713aSLionel Sambuc   T.consumeClose();
2816*f4a2713aSLionel Sambuc 
2817*f4a2713aSLionel Sambuc   if (Ty.isInvalid())
2818*f4a2713aSLionel Sambuc     return ExprError();
2819*f4a2713aSLionel Sambuc 
2820*f4a2713aSLionel Sambuc   return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(),
2821*f4a2713aSLionel Sambuc                                            Ty.get(), T.getCloseLocation());
2822*f4a2713aSLionel Sambuc }
2823*f4a2713aSLionel Sambuc 
2824*f4a2713aSLionel Sambuc ///     objc-protocol-expression
2825*f4a2713aSLionel Sambuc ///       \@protocol ( protocol-name )
2826*f4a2713aSLionel Sambuc ExprResult
2827*f4a2713aSLionel Sambuc Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
2828*f4a2713aSLionel Sambuc   SourceLocation ProtoLoc = ConsumeToken();
2829*f4a2713aSLionel Sambuc 
2830*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2831*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
2832*f4a2713aSLionel Sambuc 
2833*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2834*f4a2713aSLionel Sambuc   T.consumeOpen();
2835*f4a2713aSLionel Sambuc 
2836*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier))
2837*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_ident));
2838*f4a2713aSLionel Sambuc 
2839*f4a2713aSLionel Sambuc   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
2840*f4a2713aSLionel Sambuc   SourceLocation ProtoIdLoc = ConsumeToken();
2841*f4a2713aSLionel Sambuc 
2842*f4a2713aSLionel Sambuc   T.consumeClose();
2843*f4a2713aSLionel Sambuc 
2844*f4a2713aSLionel Sambuc   return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
2845*f4a2713aSLionel Sambuc                                              T.getOpenLocation(), ProtoIdLoc,
2846*f4a2713aSLionel Sambuc                                              T.getCloseLocation());
2847*f4a2713aSLionel Sambuc }
2848*f4a2713aSLionel Sambuc 
2849*f4a2713aSLionel Sambuc ///     objc-selector-expression
2850*f4a2713aSLionel Sambuc ///       @selector '(' objc-keyword-selector ')'
2851*f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
2852*f4a2713aSLionel Sambuc   SourceLocation SelectorLoc = ConsumeToken();
2853*f4a2713aSLionel Sambuc 
2854*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2855*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
2856*f4a2713aSLionel Sambuc 
2857*f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
2858*f4a2713aSLionel Sambuc   SourceLocation sLoc;
2859*f4a2713aSLionel Sambuc 
2860*f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2861*f4a2713aSLionel Sambuc   T.consumeOpen();
2862*f4a2713aSLionel Sambuc 
2863*f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2864*f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
2865*f4a2713aSLionel Sambuc     cutOffParsing();
2866*f4a2713aSLionel Sambuc     return ExprError();
2867*f4a2713aSLionel Sambuc   }
2868*f4a2713aSLionel Sambuc 
2869*f4a2713aSLionel Sambuc   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
2870*f4a2713aSLionel Sambuc   if (!SelIdent &&  // missing selector name.
2871*f4a2713aSLionel Sambuc       Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
2872*f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_ident));
2873*f4a2713aSLionel Sambuc 
2874*f4a2713aSLionel Sambuc   KeyIdents.push_back(SelIdent);
2875*f4a2713aSLionel Sambuc   unsigned nColons = 0;
2876*f4a2713aSLionel Sambuc   if (Tok.isNot(tok::r_paren)) {
2877*f4a2713aSLionel Sambuc     while (1) {
2878*f4a2713aSLionel Sambuc       if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
2879*f4a2713aSLionel Sambuc         ++nColons;
2880*f4a2713aSLionel Sambuc         KeyIdents.push_back(0);
2881*f4a2713aSLionel Sambuc       } else if (Tok.isNot(tok::colon))
2882*f4a2713aSLionel Sambuc         return ExprError(Diag(Tok, diag::err_expected_colon));
2883*f4a2713aSLionel Sambuc 
2884*f4a2713aSLionel Sambuc       ++nColons;
2885*f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the ':' or '::'.
2886*f4a2713aSLionel Sambuc       if (Tok.is(tok::r_paren))
2887*f4a2713aSLionel Sambuc         break;
2888*f4a2713aSLionel Sambuc 
2889*f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2890*f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
2891*f4a2713aSLionel Sambuc         cutOffParsing();
2892*f4a2713aSLionel Sambuc         return ExprError();
2893*f4a2713aSLionel Sambuc       }
2894*f4a2713aSLionel Sambuc 
2895*f4a2713aSLionel Sambuc       // Check for another keyword selector.
2896*f4a2713aSLionel Sambuc       SourceLocation Loc;
2897*f4a2713aSLionel Sambuc       SelIdent = ParseObjCSelectorPiece(Loc);
2898*f4a2713aSLionel Sambuc       KeyIdents.push_back(SelIdent);
2899*f4a2713aSLionel Sambuc       if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
2900*f4a2713aSLionel Sambuc         break;
2901*f4a2713aSLionel Sambuc     }
2902*f4a2713aSLionel Sambuc   }
2903*f4a2713aSLionel Sambuc   T.consumeClose();
2904*f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
2905*f4a2713aSLionel Sambuc   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
2906*f4a2713aSLionel Sambuc                                              T.getOpenLocation(),
2907*f4a2713aSLionel Sambuc                                              T.getCloseLocation());
2908*f4a2713aSLionel Sambuc  }
2909*f4a2713aSLionel Sambuc 
2910*f4a2713aSLionel Sambuc void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
2911*f4a2713aSLionel Sambuc   // MCDecl might be null due to error in method or c-function  prototype, etc.
2912*f4a2713aSLionel Sambuc   Decl *MCDecl = LM.D;
2913*f4a2713aSLionel Sambuc   bool skip = MCDecl &&
2914*f4a2713aSLionel Sambuc               ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
2915*f4a2713aSLionel Sambuc               (!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
2916*f4a2713aSLionel Sambuc   if (skip)
2917*f4a2713aSLionel Sambuc     return;
2918*f4a2713aSLionel Sambuc 
2919*f4a2713aSLionel Sambuc   // Save the current token position.
2920*f4a2713aSLionel Sambuc   SourceLocation OrigLoc = Tok.getLocation();
2921*f4a2713aSLionel Sambuc 
2922*f4a2713aSLionel Sambuc   assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
2923*f4a2713aSLionel Sambuc   // Append the current token at the end of the new token stream so that it
2924*f4a2713aSLionel Sambuc   // doesn't get lost.
2925*f4a2713aSLionel Sambuc   LM.Toks.push_back(Tok);
2926*f4a2713aSLionel Sambuc   PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
2927*f4a2713aSLionel Sambuc 
2928*f4a2713aSLionel Sambuc   // Consume the previously pushed token.
2929*f4a2713aSLionel Sambuc   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
2930*f4a2713aSLionel Sambuc 
2931*f4a2713aSLionel Sambuc   assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
2932*f4a2713aSLionel Sambuc           Tok.is(tok::colon)) &&
2933*f4a2713aSLionel Sambuc           "Inline objective-c method not starting with '{' or 'try' or ':'");
2934*f4a2713aSLionel Sambuc   // Enter a scope for the method or c-fucntion body.
2935*f4a2713aSLionel Sambuc   ParseScope BodyScope(this,
2936*f4a2713aSLionel Sambuc                        parseMethod
2937*f4a2713aSLionel Sambuc                        ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
2938*f4a2713aSLionel Sambuc                        : Scope::FnScope|Scope::DeclScope);
2939*f4a2713aSLionel Sambuc 
2940*f4a2713aSLionel Sambuc   // Tell the actions module that we have entered a method or c-function definition
2941*f4a2713aSLionel Sambuc   // with the specified Declarator for the method/function.
2942*f4a2713aSLionel Sambuc   if (parseMethod)
2943*f4a2713aSLionel Sambuc     Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
2944*f4a2713aSLionel Sambuc   else
2945*f4a2713aSLionel Sambuc     Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
2946*f4a2713aSLionel Sambuc   if (Tok.is(tok::kw_try))
2947*f4a2713aSLionel Sambuc     MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope);
2948*f4a2713aSLionel Sambuc   else {
2949*f4a2713aSLionel Sambuc     if (Tok.is(tok::colon))
2950*f4a2713aSLionel Sambuc       ParseConstructorInitializer(MCDecl);
2951*f4a2713aSLionel Sambuc     MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope);
2952*f4a2713aSLionel Sambuc   }
2953*f4a2713aSLionel Sambuc 
2954*f4a2713aSLionel Sambuc   if (Tok.getLocation() != OrigLoc) {
2955*f4a2713aSLionel Sambuc     // Due to parsing error, we either went over the cached tokens or
2956*f4a2713aSLionel Sambuc     // there are still cached tokens left. If it's the latter case skip the
2957*f4a2713aSLionel Sambuc     // leftover tokens.
2958*f4a2713aSLionel Sambuc     // Since this is an uncommon situation that should be avoided, use the
2959*f4a2713aSLionel Sambuc     // expensive isBeforeInTranslationUnit call.
2960*f4a2713aSLionel Sambuc     if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
2961*f4a2713aSLionel Sambuc                                                      OrigLoc))
2962*f4a2713aSLionel Sambuc       while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
2963*f4a2713aSLionel Sambuc         ConsumeAnyToken();
2964*f4a2713aSLionel Sambuc   }
2965*f4a2713aSLionel Sambuc 
2966*f4a2713aSLionel Sambuc   return;
2967*f4a2713aSLionel Sambuc }
2968