blob: e367834f70c0777a8ebd28ff37f25b2db3d12e93 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- ParseObjc.cpp - Objective C Parsing ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Steve Naroff and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Objective-C portions of the Parser interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
Steve Naroff4985ace2007-08-22 18:35:33 +000015#include "clang/Parse/DeclSpec.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000016#include "clang/Basic/Diagnostic.h"
17#include "llvm/ADT/SmallVector.h"
18using namespace clang;
19
20
21/// ParseExternalDeclaration:
22/// external-declaration: [C99 6.9]
23/// [OBJC] objc-class-definition
24/// [OBJC] objc-class-declaration [TODO]
25/// [OBJC] objc-alias-declaration [TODO]
26/// [OBJC] objc-protocol-definition [TODO]
27/// [OBJC] objc-method-definition [TODO]
28/// [OBJC] '@' 'end' [TODO]
Steve Naroffdac269b2007-08-20 21:31:48 +000029Parser::DeclTy *Parser::ParseObjCAtDirectives() {
Reid Spencer5f016e22007-07-11 17:01:13 +000030 SourceLocation AtLoc = ConsumeToken(); // the "@"
31
Steve Naroff861cf3e2007-08-23 18:16:40 +000032 switch (Tok.getObjCKeywordID()) {
Reid Spencer5f016e22007-07-11 17:01:13 +000033 case tok::objc_class:
34 return ParseObjCAtClassDeclaration(AtLoc);
35 case tok::objc_interface:
Steve Naroffdac269b2007-08-20 21:31:48 +000036 return ParseObjCAtInterfaceDeclaration(AtLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +000037 case tok::objc_protocol:
Steve Naroff7ef58fd2007-08-22 22:17:26 +000038 return ParseObjCAtProtocolDeclaration(AtLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +000039 case tok::objc_implementation:
Steve Naroff3536b442007-09-06 21:24:23 +000040 return ObjcImpDecl = ParseObjCAtImplementationDeclaration(AtLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +000041 case tok::objc_end:
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +000042 return ParseObjCAtEndDeclaration(AtLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +000043 case tok::objc_compatibility_alias:
Fariborz Jahaniane992af02007-09-04 19:26:51 +000044 return ParseObjCAtAliasDeclaration(AtLoc);
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +000045 case tok::objc_synthesize:
46 return ParseObjCPropertySynthesize(AtLoc);
47 case tok::objc_dynamic:
48 return ParseObjCPropertyDynamic(AtLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +000049 default:
50 Diag(AtLoc, diag::err_unexpected_at);
51 SkipUntil(tok::semi);
Steve Naroffdac269b2007-08-20 21:31:48 +000052 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +000053 }
54}
55
56///
57/// objc-class-declaration:
58/// '@' 'class' identifier-list ';'
59///
Steve Naroffdac269b2007-08-20 21:31:48 +000060Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
Reid Spencer5f016e22007-07-11 17:01:13 +000061 ConsumeToken(); // the identifier "class"
62 llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
63
64 while (1) {
65 if (Tok.getKind() != tok::identifier) {
66 Diag(Tok, diag::err_expected_ident);
67 SkipUntil(tok::semi);
Steve Naroffdac269b2007-08-20 21:31:48 +000068 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +000069 }
Reid Spencer5f016e22007-07-11 17:01:13 +000070 ClassNames.push_back(Tok.getIdentifierInfo());
71 ConsumeToken();
72
73 if (Tok.getKind() != tok::comma)
74 break;
75
76 ConsumeToken();
77 }
78
79 // Consume the ';'.
80 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
Steve Naroffdac269b2007-08-20 21:31:48 +000081 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +000082
Steve Naroff3536b442007-09-06 21:24:23 +000083 return Actions.ObjcClassDeclaration(CurScope, atLoc,
84 &ClassNames[0], ClassNames.size());
Reid Spencer5f016e22007-07-11 17:01:13 +000085}
86
Steve Naroffdac269b2007-08-20 21:31:48 +000087///
88/// objc-interface:
89/// objc-class-interface-attributes[opt] objc-class-interface
90/// objc-category-interface
91///
92/// objc-class-interface:
93/// '@' 'interface' identifier objc-superclass[opt]
94/// objc-protocol-refs[opt]
95/// objc-class-instance-variables[opt]
96/// objc-interface-decl-list
97/// @end
98///
99/// objc-category-interface:
100/// '@' 'interface' identifier '(' identifier[opt] ')'
101/// objc-protocol-refs[opt]
102/// objc-interface-decl-list
103/// @end
104///
105/// objc-superclass:
106/// ':' identifier
107///
108/// objc-class-interface-attributes:
109/// __attribute__((visibility("default")))
110/// __attribute__((visibility("hidden")))
111/// __attribute__((deprecated))
112/// __attribute__((unavailable))
113/// __attribute__((objc_exception)) - used by NSException on 64-bit
114///
115Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
116 SourceLocation atLoc, AttributeList *attrList) {
Steve Naroff861cf3e2007-08-23 18:16:40 +0000117 assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
Steve Naroffdac269b2007-08-20 21:31:48 +0000118 "ParseObjCAtInterfaceDeclaration(): Expected @interface");
119 ConsumeToken(); // the "interface" identifier
120
121 if (Tok.getKind() != tok::identifier) {
122 Diag(Tok, diag::err_expected_ident); // missing class or category name.
123 return 0;
124 }
125 // We have a class or category name - consume it.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000126 IdentifierInfo *nameId = Tok.getIdentifierInfo();
Steve Naroffdac269b2007-08-20 21:31:48 +0000127 SourceLocation nameLoc = ConsumeToken();
128
Steve Naroff527fe232007-08-23 19:56:30 +0000129 if (Tok.getKind() == tok::l_paren) { // we have a category.
Steve Naroffdac269b2007-08-20 21:31:48 +0000130 SourceLocation lparenLoc = ConsumeParen();
131 SourceLocation categoryLoc, rparenLoc;
132 IdentifierInfo *categoryId = 0;
Fariborz Jahanianfd225cc2007-09-18 20:26:58 +0000133 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
Steve Naroffdac269b2007-08-20 21:31:48 +0000134
Steve Naroff527fe232007-08-23 19:56:30 +0000135 // For ObjC2, the category name is optional (not an error).
Steve Naroffdac269b2007-08-20 21:31:48 +0000136 if (Tok.getKind() == tok::identifier) {
137 categoryId = Tok.getIdentifierInfo();
138 categoryLoc = ConsumeToken();
Steve Naroff527fe232007-08-23 19:56:30 +0000139 } else if (!getLang().ObjC2) {
140 Diag(Tok, diag::err_expected_ident); // missing category name.
141 return 0;
Steve Naroffdac269b2007-08-20 21:31:48 +0000142 }
143 if (Tok.getKind() != tok::r_paren) {
144 Diag(Tok, diag::err_expected_rparen);
145 SkipUntil(tok::r_paren, false); // don't stop at ';'
146 return 0;
147 }
148 rparenLoc = ConsumeParen();
149 // Next, we need to check for any protocol references.
150 if (Tok.getKind() == tok::less) {
Steve Narofff28b2642007-09-05 23:30:30 +0000151 if (ParseObjCProtocolReferences(ProtocolRefs))
Steve Naroffdac269b2007-08-20 21:31:48 +0000152 return 0;
153 }
154 if (attrList) // categories don't support attributes.
155 Diag(Tok, diag::err_objc_no_attributes_on_category);
156
Fariborz Jahanian9d048ff2007-09-29 00:54:24 +0000157 DeclTy *CategoryType = Actions.ObjcStartCatInterface(CurScope, atLoc,
Fariborz Jahanianfd225cc2007-09-18 20:26:58 +0000158 nameId, nameLoc,
159 categoryId, categoryLoc,
160 &ProtocolRefs[0],
161 ProtocolRefs.size());
162
163 ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
Steve Naroffdac269b2007-08-20 21:31:48 +0000164
Steve Naroff294494e2007-08-22 16:35:03 +0000165 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
Steve Naroff861cf3e2007-08-23 18:16:40 +0000166 if (Tok.isObjCAtKeyword(tok::objc_end)) {
Steve Naroff294494e2007-08-22 16:35:03 +0000167 ConsumeToken(); // the "end" identifier
Steve Naroffdac269b2007-08-20 21:31:48 +0000168 return 0;
169 }
Steve Naroff294494e2007-08-22 16:35:03 +0000170 Diag(Tok, diag::err_objc_missing_end);
Steve Naroffdac269b2007-08-20 21:31:48 +0000171 return 0;
172 }
173 // Parse a class interface.
174 IdentifierInfo *superClassId = 0;
175 SourceLocation superClassLoc;
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000176
Steve Naroffdac269b2007-08-20 21:31:48 +0000177 if (Tok.getKind() == tok::colon) { // a super class is specified.
178 ConsumeToken();
179 if (Tok.getKind() != tok::identifier) {
180 Diag(Tok, diag::err_expected_ident); // missing super class name.
181 return 0;
182 }
183 superClassId = Tok.getIdentifierInfo();
184 superClassLoc = ConsumeToken();
185 }
186 // Next, we need to check for any protocol references.
Steve Narofff28b2642007-09-05 23:30:30 +0000187 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
Steve Naroffdac269b2007-08-20 21:31:48 +0000188 if (Tok.getKind() == tok::less) {
Steve Narofff28b2642007-09-05 23:30:30 +0000189 if (ParseObjCProtocolReferences(ProtocolRefs))
Steve Naroffdac269b2007-08-20 21:31:48 +0000190 return 0;
191 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000192 DeclTy *ClsType = Actions.ObjcStartClassInterface(CurScope,
193 atLoc, nameId, nameLoc,
Steve Narofff28b2642007-09-05 23:30:30 +0000194 superClassId, superClassLoc, &ProtocolRefs[0],
195 ProtocolRefs.size(), attrList);
196
Steve Naroffdac269b2007-08-20 21:31:48 +0000197 if (Tok.getKind() == tok::l_brace)
Steve Naroff3536b442007-09-06 21:24:23 +0000198 ParseObjCClassInstanceVariables(ClsType);
Steve Naroffdac269b2007-08-20 21:31:48 +0000199
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000200 ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
Steve Naroff294494e2007-08-22 16:35:03 +0000201
202 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
Steve Naroff861cf3e2007-08-23 18:16:40 +0000203 if (Tok.isObjCAtKeyword(tok::objc_end)) {
Steve Naroff294494e2007-08-22 16:35:03 +0000204 ConsumeToken(); // the "end" identifier
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000205 return ClsType;
Steve Naroffdac269b2007-08-20 21:31:48 +0000206 }
Steve Naroff294494e2007-08-22 16:35:03 +0000207 Diag(Tok, diag::err_objc_missing_end);
Steve Naroffdac269b2007-08-20 21:31:48 +0000208 return 0;
209}
210
211/// objc-interface-decl-list:
212/// empty
Steve Naroffdac269b2007-08-20 21:31:48 +0000213/// objc-interface-decl-list objc-property-decl [OBJC2]
Steve Naroff294494e2007-08-22 16:35:03 +0000214/// objc-interface-decl-list objc-method-requirement [OBJC2]
Steve Naroff3536b442007-09-06 21:24:23 +0000215/// objc-interface-decl-list objc-method-proto ';'
Steve Naroffdac269b2007-08-20 21:31:48 +0000216/// objc-interface-decl-list declaration
217/// objc-interface-decl-list ';'
218///
Steve Naroff294494e2007-08-22 16:35:03 +0000219/// objc-method-requirement: [OBJC2]
220/// @required
221/// @optional
222///
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000223void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
224 tok::ObjCKeywordKind contextKey) {
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000225 llvm::SmallVector<DeclTy*, 32> allMethods;
Fariborz Jahanian00933592007-09-18 00:25:23 +0000226 tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
Steve Naroff294494e2007-08-22 16:35:03 +0000227 while (1) {
228 if (Tok.getKind() == tok::at) {
229 SourceLocation AtLoc = ConsumeToken(); // the "@"
Steve Naroff861cf3e2007-08-23 18:16:40 +0000230 tok::ObjCKeywordKind ocKind = Tok.getObjCKeywordID();
Steve Naroff294494e2007-08-22 16:35:03 +0000231
232 if (ocKind == tok::objc_end) { // terminate list
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000233 break;
Steve Naroff294494e2007-08-22 16:35:03 +0000234 } else if (ocKind == tok::objc_required) { // protocols only
235 ConsumeToken();
Fariborz Jahanian00933592007-09-18 00:25:23 +0000236 MethodImplKind = ocKind;
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000237 if (contextKey != tok::objc_protocol)
238 Diag(AtLoc, diag::err_objc_protocol_required);
Steve Naroff294494e2007-08-22 16:35:03 +0000239 } else if (ocKind == tok::objc_optional) { // protocols only
240 ConsumeToken();
Fariborz Jahanian00933592007-09-18 00:25:23 +0000241 MethodImplKind = ocKind;
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000242 if (contextKey != tok::objc_protocol)
243 Diag(AtLoc, diag::err_objc_protocol_optional);
Steve Naroff294494e2007-08-22 16:35:03 +0000244 } else if (ocKind == tok::objc_property) {
Fariborz Jahaniane55cd002007-09-12 18:23:47 +0000245 ParseObjCPropertyDecl(interfaceDecl);
Steve Naroff294494e2007-08-22 16:35:03 +0000246 continue;
247 } else {
248 Diag(Tok, diag::err_objc_illegal_interface_qual);
249 ConsumeToken();
250 }
251 }
252 if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
Fariborz Jahanian00933592007-09-18 00:25:23 +0000253 DeclTy *methodPrototype = ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000254 allMethods.push_back(methodPrototype);
Steve Naroff3536b442007-09-06 21:24:23 +0000255 // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
256 // method definitions.
Steve Naroffd16245b2007-09-17 15:07:43 +0000257 ExpectAndConsume(tok::semi, diag::err_expected_semi_after,"method proto");
Steve Naroff294494e2007-08-22 16:35:03 +0000258 continue;
259 }
260 if (Tok.getKind() == tok::semi)
261 ConsumeToken();
262 else if (Tok.getKind() == tok::eof)
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000263 break;
Steve Narofff28b2642007-09-05 23:30:30 +0000264 else {
Steve Naroff4985ace2007-08-22 18:35:33 +0000265 // FIXME: as the name implies, this rule allows function definitions.
266 // We could pass a flag or check for functions during semantic analysis.
Steve Naroff3536b442007-09-06 21:24:23 +0000267 ParseDeclarationOrFunctionDefinition();
Steve Narofff28b2642007-09-05 23:30:30 +0000268 }
Steve Naroff294494e2007-08-22 16:35:03 +0000269 }
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000270 /// Insert collected methods declarations into the @interface object.
Fariborz Jahanian9d048ff2007-09-29 00:54:24 +0000271 Actions.ObjcAddMethodsToClass(CurScope,
272 interfaceDecl,&allMethods[0],allMethods.size());
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000273 return;
Steve Naroff294494e2007-08-22 16:35:03 +0000274}
275
Fariborz Jahaniand0f97d12007-08-31 16:11:31 +0000276/// Parse property attribute declarations.
277///
278/// property-attr-decl: '(' property-attrlist ')'
279/// property-attrlist:
280/// property-attribute
281/// property-attrlist ',' property-attribute
282/// property-attribute:
283/// getter '=' identifier
284/// setter '=' identifier ':'
285/// readonly
286/// readwrite
287/// assign
288/// retain
289/// copy
290/// nonatomic
291///
292void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
293 SourceLocation loc = ConsumeParen(); // consume '('
294 while (isObjCPropertyAttribute()) {
295 const IdentifierInfo *II = Tok.getIdentifierInfo();
296 // getter/setter require extra treatment.
297 if (II == ObjcPropertyAttrs[objc_getter] ||
298 II == ObjcPropertyAttrs[objc_setter]) {
299 // skip getter/setter part.
300 SourceLocation loc = ConsumeToken();
301 if (Tok.getKind() == tok::equal) {
302 loc = ConsumeToken();
303 if (Tok.getKind() == tok::identifier) {
304 if (II == ObjcPropertyAttrs[objc_setter]) {
305 loc = ConsumeToken(); // consume method name
306 if (Tok.getKind() != tok::colon) {
307 Diag(loc, diag::err_expected_colon);
308 SkipUntil(tok::r_paren,true,true);
309 break;
310 }
311 }
312 }
313 else {
314 Diag(loc, diag::err_expected_ident);
315 SkipUntil(tok::r_paren,true,true);
316 break;
317 }
318 }
319 else {
320 Diag(loc, diag::err_objc_expected_equal);
321 SkipUntil(tok::r_paren,true,true);
322 break;
323 }
324 }
325 ConsumeToken(); // consume last attribute token
326 if (Tok.getKind() == tok::comma) {
327 loc = ConsumeToken();
328 continue;
329 }
330 if (Tok.getKind() == tok::r_paren)
331 break;
332 Diag(loc, diag::err_expected_rparen);
333 SkipUntil(tok::semi);
334 return;
335 }
336 if (Tok.getKind() == tok::r_paren)
337 ConsumeParen();
338 else {
339 Diag(loc, diag::err_objc_expected_property_attr);
340 SkipUntil(tok::r_paren); // recover from error inside attribute list
341 }
342}
343
344/// Main routine to parse property declaration.
345///
346/// @property property-attr-decl[opt] property-component-decl ';'
347///
348void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
349 assert(Tok.isObjCAtKeyword(tok::objc_property) &&
350 "ParseObjCPropertyDecl(): Expected @property");
351 ConsumeToken(); // the "property" identifier
352 // Parse property attribute list, if any.
353 if (Tok.getKind() == tok::l_paren) {
354 // property has attribute list.
355 ParseObjCPropertyAttribute(0/*FIXME*/);
356 }
357 // Parse declaration portion of @property.
358 llvm::SmallVector<DeclTy*, 32> PropertyDecls;
359 ParseStructDeclaration(interfaceDecl, PropertyDecls);
360 if (Tok.getKind() == tok::semi)
361 ConsumeToken();
362 else {
363 Diag(Tok, diag::err_expected_semi_decl_list);
364 SkipUntil(tok::r_brace, true, true);
365 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000366}
Steve Naroffdac269b2007-08-20 21:31:48 +0000367
Steve Naroff3536b442007-09-06 21:24:23 +0000368/// objc-method-proto:
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000369/// objc-instance-method objc-method-decl objc-method-attributes[opt]
Steve Naroff3536b442007-09-06 21:24:23 +0000370/// objc-class-method objc-method-decl objc-method-attributes[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000371///
372/// objc-instance-method: '-'
373/// objc-class-method: '+'
374///
Steve Naroff4985ace2007-08-22 18:35:33 +0000375/// objc-method-attributes: [OBJC2]
376/// __attribute__((deprecated))
377///
Fariborz Jahanian00933592007-09-18 00:25:23 +0000378Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
379 tok::ObjCKeywordKind MethodImplKind) {
Steve Naroff294494e2007-08-22 16:35:03 +0000380 assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
381 "expected +/-");
382
383 tok::TokenKind methodType = Tok.getKind();
384 SourceLocation methodLoc = ConsumeToken();
385
Fariborz Jahanian00933592007-09-18 00:25:23 +0000386 DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc, MethodImplKind);
Steve Naroff3536b442007-09-06 21:24:23 +0000387 // Since this rule is used for both method declarations and definitions,
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000388 // the caller is (optionally) responsible for consuming the ';'.
Steve Narofff28b2642007-09-05 23:30:30 +0000389 return MDecl;
Steve Naroff294494e2007-08-22 16:35:03 +0000390}
391
392/// objc-selector:
393/// identifier
394/// one of
395/// enum struct union if else while do for switch case default
396/// break continue return goto asm sizeof typeof __alignof
397/// unsigned long const short volatile signed restrict _Complex
398/// in out inout bycopy byref oneway int char float double void _Bool
399///
400IdentifierInfo *Parser::ParseObjCSelector() {
401 tok::TokenKind tKind = Tok.getKind();
402 IdentifierInfo *II = 0;
Fariborz Jahaniand0649512007-09-27 19:52:15 +0000403 switch (tKind) {
404 case tok::identifier:
405 case tok::kw_typeof:
406 case tok::kw___alignof:
407 case tok::kw_auto:
408 case tok::kw_break:
409 case tok::kw_case:
410 case tok::kw_char:
411 case tok::kw_const:
412 case tok::kw_continue:
413 case tok::kw_default:
414 case tok::kw_do:
415 case tok::kw_double:
416 case tok::kw_else:
417 case tok::kw_enum:
418 case tok::kw_extern:
419 case tok::kw_float:
420 case tok::kw_for:
421 case tok::kw_goto:
422 case tok::kw_if:
423 case tok::kw_inline:
424 case tok::kw_int:
425 case tok::kw_long:
426 case tok::kw_register:
427 case tok::kw_restrict:
428 case tok::kw_return:
429 case tok::kw_short:
430 case tok::kw_signed:
431 case tok::kw_sizeof:
432 case tok::kw_static:
433 case tok::kw_struct:
434 case tok::kw_switch:
435 case tok::kw_typedef:
436 case tok::kw_union:
437 case tok::kw_unsigned:
438 case tok::kw_void:
439 case tok::kw_volatile:
440 case tok::kw_while:
441 case tok::kw__Bool:
442 case tok::kw__Complex:
443 II = Tok.getIdentifierInfo();
444 ConsumeToken();
445 default:
446 break;
447 }
Steve Naroff294494e2007-08-22 16:35:03 +0000448
Steve Naroff294494e2007-08-22 16:35:03 +0000449 return II;
450}
451
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000452/// objc-type-qualifier: one of
453/// in out inout bycopy byref oneway
454///
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000455bool Parser::isObjCTypeQualifier() {
456 if (Tok.getKind() == tok::identifier) {
Chris Lattner34870da2007-08-29 22:54:08 +0000457 const IdentifierInfo *II = Tok.getIdentifierInfo();
458 for (unsigned i = 0; i < objc_NumQuals; ++i)
459 if (II == ObjcTypeQuals[i]) return true;
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000460 }
461 return false;
462}
463
Fariborz Jahaniand0f97d12007-08-31 16:11:31 +0000464/// property-attrlist: one of
465/// readonly getter setter assign retain copy nonatomic
466///
467bool Parser::isObjCPropertyAttribute() {
468 if (Tok.getKind() == tok::identifier) {
469 const IdentifierInfo *II = Tok.getIdentifierInfo();
470 for (unsigned i = 0; i < objc_NumAttrs; ++i)
471 if (II == ObjcPropertyAttrs[i]) return true;
472 }
473 return false;
474}
475
Steve Naroff294494e2007-08-22 16:35:03 +0000476/// objc-type-name:
477/// '(' objc-type-qualifiers[opt] type-name ')'
478/// '(' objc-type-qualifiers[opt] ')'
479///
480/// objc-type-qualifiers:
481/// objc-type-qualifier
482/// objc-type-qualifiers objc-type-qualifier
483///
Steve Narofff28b2642007-09-05 23:30:30 +0000484Parser::TypeTy *Parser::ParseObjCTypeName() {
Steve Naroff294494e2007-08-22 16:35:03 +0000485 assert(Tok.getKind() == tok::l_paren && "expected (");
486
487 SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
Chris Lattner271f1a62007-09-27 15:15:46 +0000488 TypeTy *Ty = 0;
Steve Naroff294494e2007-08-22 16:35:03 +0000489
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000490 while (isObjCTypeQualifier())
491 ConsumeToken();
492
Steve Naroff294494e2007-08-22 16:35:03 +0000493 if (isTypeSpecifierQualifier()) {
Steve Narofff28b2642007-09-05 23:30:30 +0000494 Ty = ParseTypeName();
495 // FIXME: back when Sema support is in place...
496 // assert(Ty && "Parser::ParseObjCTypeName(): missing type");
Steve Naroff294494e2007-08-22 16:35:03 +0000497 }
498 if (Tok.getKind() != tok::r_paren) {
499 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Steve Narofff28b2642007-09-05 23:30:30 +0000500 return 0; // FIXME: decide how we want to handle this error...
Steve Naroff294494e2007-08-22 16:35:03 +0000501 }
502 RParenLoc = ConsumeParen();
Steve Narofff28b2642007-09-05 23:30:30 +0000503 return Ty;
Steve Naroff294494e2007-08-22 16:35:03 +0000504}
505
Steve Naroff5b6b72f2007-09-28 23:39:26 +0000506unsigned Selector::getNumArgs() const {
507 unsigned IIF = getIdentifierInfoFlag();
508 if (IIF == ZeroArg)
509 return 0;
510 if (IIF == OneArg)
511 return 1;
512 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
513 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
514 return SI->getNumArgs();
515}
516
517IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) {
518 IdentifierInfo *II = getAsIdentifierInfo();
519 if (II) {
520 assert(((argIndex == 0) || (argIndex == 1)) && "illegal keyword index");
521 return II;
522 }
523 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
524 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
525 return SI->getIdentifierInfoForSlot(argIndex);
526}
527
528char *MultiKeywordSelector::getName(llvm::SmallVectorImpl<char> &methodName) {
529 methodName[0] = '\0';
530 keyword_iterator KeyIter = keyword_begin();
531 for (unsigned int i = 0; i < NumArgs; i++) {
532 if (KeyIter[i]) {
533 unsigned KeyLen = strlen(KeyIter[i]->getName());
534 methodName.append(KeyIter[i]->getName(), KeyIter[i]->getName()+KeyLen);
535 }
536 methodName.push_back(':');
537 }
538 methodName.push_back('\0');
539 return &methodName[0];
540}
541
542char *Selector::getName(llvm::SmallVectorImpl<char> &methodName) {
543 methodName[0] = '\0';
544 IdentifierInfo *II = getAsIdentifierInfo();
545 if (II) {
546 unsigned NameLen = strlen(II->getName());
547 methodName.append(II->getName(), II->getName()+NameLen);
548 if (getNumArgs() == 1)
549 methodName.push_back(':');
550 methodName.push_back('\0');
551 } else { // We have a multiple keyword selector (no embedded flags).
552 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
553 SI->getName(methodName);
554 }
555 return &methodName[0];
556}
557
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000558Selector Parser::ObjcGetUnarySelector(IdentifierInfo *unarySel)
Steve Naroff68d331a2007-09-27 14:38:14 +0000559{
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000560 return Selector(unarySel, 0);
Steve Naroff68d331a2007-09-27 14:38:14 +0000561}
562
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000563Selector Parser::ObjcGetKeywordSelector(
564 llvm::SmallVectorImpl<IdentifierInfo *> &IIV)
565{
566 if (IIV.size() == 1)
567 return Selector(IIV[0], 1);
568
569 llvm::FoldingSet<MultiKeywordSelector> &SelTab = PP.getSelectorTable();
570
Steve Naroff68d331a2007-09-27 14:38:14 +0000571 // Unique selector, to guarantee there is one per name.
572 llvm::FoldingSetNodeID ID;
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000573 MultiKeywordSelector::Profile(ID, &IIV[0], IIV.size());
Steve Naroff68d331a2007-09-27 14:38:14 +0000574
575 void *InsertPos = 0;
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000576 if (MultiKeywordSelector *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos)) {
577 return Selector(SI);
578 }
579 // MultiKeywordSelector objects are not allocated with new because they have a
Steve Naroff68d331a2007-09-27 14:38:14 +0000580 // variable size array (for parameter types) at the end of them.
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000581 MultiKeywordSelector *SI =
582 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
583 IIV.size()*sizeof(IdentifierInfo *));
584 new (SI) MultiKeywordSelector(IIV.size(), &IIV[0]);
Steve Naroff68d331a2007-09-27 14:38:14 +0000585 SelTab.InsertNode(SI, InsertPos);
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000586 return Selector(SI);
Steve Naroff68d331a2007-09-27 14:38:14 +0000587}
588
Steve Naroff294494e2007-08-22 16:35:03 +0000589/// objc-method-decl:
590/// objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000591/// objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000592/// objc-type-name objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000593/// objc-type-name objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000594///
595/// objc-keyword-selector:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000596/// objc-keyword-decl
Steve Naroff294494e2007-08-22 16:35:03 +0000597/// objc-keyword-selector objc-keyword-decl
598///
599/// objc-keyword-decl:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000600/// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
601/// objc-selector ':' objc-keyword-attributes[opt] identifier
602/// ':' objc-type-name objc-keyword-attributes[opt] identifier
603/// ':' objc-keyword-attributes[opt] identifier
Steve Naroff294494e2007-08-22 16:35:03 +0000604///
Steve Naroff4985ace2007-08-22 18:35:33 +0000605/// objc-parmlist:
606/// objc-parms objc-ellipsis[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000607///
Steve Naroff4985ace2007-08-22 18:35:33 +0000608/// objc-parms:
609/// objc-parms , parameter-declaration
Steve Naroff294494e2007-08-22 16:35:03 +0000610///
Steve Naroff4985ace2007-08-22 18:35:33 +0000611/// objc-ellipsis:
Steve Naroff294494e2007-08-22 16:35:03 +0000612/// , ...
613///
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000614/// objc-keyword-attributes: [OBJC2]
615/// __attribute__((unused))
616///
Steve Naroff68d331a2007-09-27 14:38:14 +0000617Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType,
618 SourceLocation mLoc,
619 tok::ObjCKeywordKind MethodImplKind)
620{
Steve Narofff28b2642007-09-05 23:30:30 +0000621 TypeTy *ReturnType = 0;
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000622 AttributeList *methodAttrs = 0;
Steve Narofff28b2642007-09-05 23:30:30 +0000623
Steve Naroff4985ace2007-08-22 18:35:33 +0000624 // Parse the return type.
Steve Naroff294494e2007-08-22 16:35:03 +0000625 if (Tok.getKind() == tok::l_paren)
Steve Narofff28b2642007-09-05 23:30:30 +0000626 ReturnType = ParseObjCTypeName();
Steve Naroff4985ace2007-08-22 18:35:33 +0000627 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Narofff28b2642007-09-05 23:30:30 +0000628
Steve Naroff68d331a2007-09-27 14:38:14 +0000629 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
630 llvm::SmallVector<Action::TypeTy *, 12> KeyTypes;
631 llvm::SmallVector<IdentifierInfo *, 12> ArgNames;
632
Steve Naroff4985ace2007-08-22 18:35:33 +0000633 if (Tok.getKind() == tok::colon) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000634 Action::TypeTy *TypeInfo;
Steve Narofff28b2642007-09-05 23:30:30 +0000635
Steve Naroff4985ace2007-08-22 18:35:33 +0000636 while (1) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000637 KeyIdents.push_back(selIdent);
Steve Narofff28b2642007-09-05 23:30:30 +0000638
Steve Naroff4985ace2007-08-22 18:35:33 +0000639 // Each iteration parses a single keyword argument.
640 if (Tok.getKind() != tok::colon) {
641 Diag(Tok, diag::err_expected_colon);
642 break;
643 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000644 ConsumeToken(); // Eat the ':'.
Steve Naroff4985ace2007-08-22 18:35:33 +0000645 if (Tok.getKind() == tok::l_paren) // Parse the argument type.
Steve Naroff68d331a2007-09-27 14:38:14 +0000646 TypeInfo = ParseObjCTypeName();
647 else
648 TypeInfo = 0;
649 KeyTypes.push_back(TypeInfo);
650
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000651 // If attributes exist before the argument name, parse them.
Steve Naroff527fe232007-08-23 19:56:30 +0000652 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
Steve Naroff68d331a2007-09-27 14:38:14 +0000653 ParseAttributes(); // FIXME: pass attributes through.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000654
Steve Naroff4985ace2007-08-22 18:35:33 +0000655 if (Tok.getKind() != tok::identifier) {
656 Diag(Tok, diag::err_expected_ident); // missing argument name.
657 break;
658 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000659 ArgNames.push_back(Tok.getIdentifierInfo());
Steve Naroff4985ace2007-08-22 18:35:33 +0000660 ConsumeToken(); // Eat the identifier.
Steve Narofff28b2642007-09-05 23:30:30 +0000661
Steve Naroff37387c92007-09-17 20:25:27 +0000662 // Check for another keyword selector.
Steve Narofff28b2642007-09-05 23:30:30 +0000663 selIdent = ParseObjCSelector();
664 if (!selIdent && Tok.getKind() != tok::colon)
Steve Naroff4985ace2007-08-22 18:35:33 +0000665 break;
666 // We have a selector or a colon, continue parsing.
667 }
668 // Parse the (optional) parameter list.
669 while (Tok.getKind() == tok::comma) {
670 ConsumeToken();
671 if (Tok.getKind() == tok::ellipsis) {
672 ConsumeToken();
673 break;
674 }
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +0000675 // Parse the c-style argument declaration-specifier.
676 DeclSpec DS;
677 ParseDeclarationSpecifiers(DS);
678 // Parse the declarator.
679 Declarator ParmDecl(DS, Declarator::PrototypeContext);
680 ParseDeclarator(ParmDecl);
Steve Naroff4985ace2007-08-22 18:35:33 +0000681 }
Steve Narofff28b2642007-09-05 23:30:30 +0000682 // FIXME: Add support for optional parmameter list...
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000683 // If attributes exist after the method, parse them.
684 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
685 methodAttrs = ParseAttributes();
Steve Naroff68d331a2007-09-27 14:38:14 +0000686
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000687 Selector Sel = ObjcGetKeywordSelector(KeyIdents);
688 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel,
Steve Naroff68d331a2007-09-27 14:38:14 +0000689 &KeyTypes[0], &ArgNames[0],
Fariborz Jahanian00933592007-09-18 00:25:23 +0000690 methodAttrs, MethodImplKind);
Steve Naroff4985ace2007-08-22 18:35:33 +0000691 } else if (!selIdent) {
692 Diag(Tok, diag::err_expected_ident); // missing selector name.
693 }
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000694 // If attributes exist after the method, parse them.
695 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
696 methodAttrs = ParseAttributes();
697
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000698 Selector Sel = ObjcGetUnarySelector(selIdent);
699 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel,
Steve Naroff68d331a2007-09-27 14:38:14 +0000700 0, 0, methodAttrs, MethodImplKind);
Steve Naroff294494e2007-08-22 16:35:03 +0000701}
702
Steve Naroffdac269b2007-08-20 21:31:48 +0000703/// objc-protocol-refs:
704/// '<' identifier-list '>'
705///
Steve Narofff28b2642007-09-05 23:30:30 +0000706bool Parser::ParseObjCProtocolReferences(
707 llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
Steve Naroffdac269b2007-08-20 21:31:48 +0000708 assert(Tok.getKind() == tok::less && "expected <");
709
710 ConsumeToken(); // the "<"
Steve Naroffdac269b2007-08-20 21:31:48 +0000711
712 while (1) {
713 if (Tok.getKind() != tok::identifier) {
714 Diag(Tok, diag::err_expected_ident);
715 SkipUntil(tok::greater);
716 return true;
717 }
718 ProtocolRefs.push_back(Tok.getIdentifierInfo());
719 ConsumeToken();
720
721 if (Tok.getKind() != tok::comma)
722 break;
723 ConsumeToken();
724 }
725 // Consume the '>'.
726 return ExpectAndConsume(tok::greater, diag::err_expected_greater);
727}
728
729/// objc-class-instance-variables:
730/// '{' objc-instance-variable-decl-list[opt] '}'
731///
732/// objc-instance-variable-decl-list:
733/// objc-visibility-spec
734/// objc-instance-variable-decl ';'
735/// ';'
736/// objc-instance-variable-decl-list objc-visibility-spec
737/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
738/// objc-instance-variable-decl-list ';'
739///
740/// objc-visibility-spec:
741/// @private
742/// @protected
743/// @public
Steve Naroffddbff782007-08-21 21:17:12 +0000744/// @package [OBJC2]
Steve Naroffdac269b2007-08-20 21:31:48 +0000745///
746/// objc-instance-variable-decl:
747/// struct-declaration
748///
Steve Naroff3536b442007-09-06 21:24:23 +0000749void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
Steve Naroffddbff782007-08-21 21:17:12 +0000750 assert(Tok.getKind() == tok::l_brace && "expected {");
Steve Naroff3536b442007-09-06 21:24:23 +0000751 llvm::SmallVector<DeclTy*, 16> IvarDecls;
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000752 llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
753 llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
Steve Naroffddbff782007-08-21 21:17:12 +0000754
755 SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
Steve Naroffddbff782007-08-21 21:17:12 +0000756
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000757 tok::ObjCKeywordKind visibility = tok::objc_private;
Steve Naroffddbff782007-08-21 21:17:12 +0000758 // While we still have something to read, read the instance variables.
759 while (Tok.getKind() != tok::r_brace &&
760 Tok.getKind() != tok::eof) {
761 // Each iteration of this loop reads one objc-instance-variable-decl.
762
763 // Check for extraneous top-level semicolon.
764 if (Tok.getKind() == tok::semi) {
765 Diag(Tok, diag::ext_extra_struct_semi);
766 ConsumeToken();
767 continue;
768 }
769 // Set the default visibility to private.
Steve Naroffddbff782007-08-21 21:17:12 +0000770 if (Tok.getKind() == tok::at) { // parse objc-visibility-spec
771 ConsumeToken(); // eat the @ sign
Steve Naroff861cf3e2007-08-23 18:16:40 +0000772 switch (Tok.getObjCKeywordID()) {
Steve Naroffddbff782007-08-21 21:17:12 +0000773 case tok::objc_private:
774 case tok::objc_public:
775 case tok::objc_protected:
776 case tok::objc_package:
Steve Naroff861cf3e2007-08-23 18:16:40 +0000777 visibility = Tok.getObjCKeywordID();
Steve Naroffddbff782007-08-21 21:17:12 +0000778 ConsumeToken();
779 continue;
780 default:
781 Diag(Tok, diag::err_objc_illegal_visibility_spec);
782 ConsumeToken();
783 continue;
784 }
785 }
786 ParseStructDeclaration(interfaceDecl, IvarDecls);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000787 for (unsigned i = 0; i < IvarDecls.size(); i++) {
788 AllIvarDecls.push_back(IvarDecls[i]);
789 AllVisibilities.push_back(visibility);
790 }
Steve Naroff3536b442007-09-06 21:24:23 +0000791 IvarDecls.clear();
792
Steve Naroffddbff782007-08-21 21:17:12 +0000793 if (Tok.getKind() == tok::semi) {
794 ConsumeToken();
795 } else if (Tok.getKind() == tok::r_brace) {
796 Diag(Tok.getLocation(), diag::ext_expected_semi_decl_list);
797 break;
798 } else {
799 Diag(Tok, diag::err_expected_semi_decl_list);
800 // Skip to end of block or statement
801 SkipUntil(tok::r_brace, true, true);
802 }
803 }
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000804 if (AllIvarDecls.size()) { // Check for {} - no ivars in braces
Fariborz Jahanian9d048ff2007-09-29 00:54:24 +0000805 Actions.ActOnFields(CurScope, LBraceLoc, interfaceDecl,
Steve Naroff08d92e42007-09-15 18:49:24 +0000806 &AllIvarDecls[0], AllIvarDecls.size(),
807 &AllVisibilities[0]);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000808 }
Steve Naroffddbff782007-08-21 21:17:12 +0000809 MatchRHSPunctuation(tok::r_brace, LBraceLoc);
810 return;
Reid Spencer5f016e22007-07-11 17:01:13 +0000811}
Steve Naroffdac269b2007-08-20 21:31:48 +0000812
813/// objc-protocol-declaration:
814/// objc-protocol-definition
815/// objc-protocol-forward-reference
816///
817/// objc-protocol-definition:
818/// @protocol identifier
819/// objc-protocol-refs[opt]
Steve Naroff3536b442007-09-06 21:24:23 +0000820/// objc-interface-decl-list
Steve Naroffdac269b2007-08-20 21:31:48 +0000821/// @end
822///
823/// objc-protocol-forward-reference:
824/// @protocol identifier-list ';'
825///
826/// "@protocol identifier ;" should be resolved as "@protocol
Steve Naroff3536b442007-09-06 21:24:23 +0000827/// identifier-list ;": objc-interface-decl-list may not start with a
Steve Naroffdac269b2007-08-20 21:31:48 +0000828/// semicolon in the first alternative if objc-protocol-refs are omitted.
829
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000830Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
Steve Naroff861cf3e2007-08-23 18:16:40 +0000831 assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000832 "ParseObjCAtProtocolDeclaration(): Expected @protocol");
833 ConsumeToken(); // the "protocol" identifier
834
835 if (Tok.getKind() != tok::identifier) {
836 Diag(Tok, diag::err_expected_ident); // missing protocol name.
837 return 0;
838 }
839 // Save the protocol name, then consume it.
840 IdentifierInfo *protocolName = Tok.getIdentifierInfo();
841 SourceLocation nameLoc = ConsumeToken();
842
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000843 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
844 if (Tok.getKind() == tok::semi) { // forward declaration of one protocol.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000845 ConsumeToken();
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000846 ProtocolRefs.push_back(protocolName);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000847 }
848 if (Tok.getKind() == tok::comma) { // list of forward declarations.
849 // Parse the list of forward declarations.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000850 ProtocolRefs.push_back(protocolName);
851
852 while (1) {
853 ConsumeToken(); // the ','
854 if (Tok.getKind() != tok::identifier) {
855 Diag(Tok, diag::err_expected_ident);
856 SkipUntil(tok::semi);
857 return 0;
858 }
859 ProtocolRefs.push_back(Tok.getIdentifierInfo());
860 ConsumeToken(); // the identifier
861
862 if (Tok.getKind() != tok::comma)
863 break;
864 }
865 // Consume the ';'.
866 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
867 return 0;
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000868 }
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000869 if (ProtocolRefs.size() > 0)
870 return Actions.ObjcForwardProtocolDeclaration(CurScope, AtLoc,
871 &ProtocolRefs[0],
872 ProtocolRefs.size());
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000873 // Last, and definitely not least, parse a protocol declaration.
874 if (Tok.getKind() == tok::less) {
Steve Narofff28b2642007-09-05 23:30:30 +0000875 if (ParseObjCProtocolReferences(ProtocolRefs))
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000876 return 0;
877 }
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000878
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000879 DeclTy *ProtoType = Actions.ObjcStartProtoInterface(CurScope, AtLoc,
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000880 protocolName, nameLoc,
881 &ProtocolRefs[0],
882 ProtocolRefs.size());
883 ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000884
885 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
Steve Naroff861cf3e2007-08-23 18:16:40 +0000886 if (Tok.isObjCAtKeyword(tok::objc_end)) {
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000887 ConsumeToken(); // the "end" identifier
888 return 0;
889 }
890 Diag(Tok, diag::err_objc_missing_end);
Steve Naroffdac269b2007-08-20 21:31:48 +0000891 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000892}
Steve Naroffdac269b2007-08-20 21:31:48 +0000893
894/// objc-implementation:
895/// objc-class-implementation-prologue
896/// objc-category-implementation-prologue
897///
898/// objc-class-implementation-prologue:
899/// @implementation identifier objc-superclass[opt]
900/// objc-class-instance-variables[opt]
901///
902/// objc-category-implementation-prologue:
903/// @implementation identifier ( identifier )
904
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000905Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
906 SourceLocation atLoc) {
907 assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
908 "ParseObjCAtImplementationDeclaration(): Expected @implementation");
909 ConsumeToken(); // the "implementation" identifier
910
911 if (Tok.getKind() != tok::identifier) {
912 Diag(Tok, diag::err_expected_ident); // missing class or category name.
913 return 0;
914 }
915 // We have a class or category name - consume it.
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000916 IdentifierInfo *nameId = Tok.getIdentifierInfo();
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000917 SourceLocation nameLoc = ConsumeToken(); // consume class or category name
918
919 if (Tok.getKind() == tok::l_paren) {
920 // we have a category implementation.
921 SourceLocation lparenLoc = ConsumeParen();
922 SourceLocation categoryLoc, rparenLoc;
923 IdentifierInfo *categoryId = 0;
924
925 if (Tok.getKind() == tok::identifier) {
926 categoryId = Tok.getIdentifierInfo();
927 categoryLoc = ConsumeToken();
928 } else {
929 Diag(Tok, diag::err_expected_ident); // missing category name.
930 return 0;
931 }
932 if (Tok.getKind() != tok::r_paren) {
933 Diag(Tok, diag::err_expected_rparen);
934 SkipUntil(tok::r_paren, false); // don't stop at ';'
935 return 0;
936 }
937 rparenLoc = ConsumeParen();
938 return 0;
939 }
940 // We have a class implementation
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000941 SourceLocation superClassLoc;
942 IdentifierInfo *superClassId = 0;
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000943 if (Tok.getKind() == tok::colon) {
944 // We have a super class
945 ConsumeToken();
946 if (Tok.getKind() != tok::identifier) {
947 Diag(Tok, diag::err_expected_ident); // missing super class name.
948 return 0;
949 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000950 superClassId = Tok.getIdentifierInfo();
951 superClassLoc = ConsumeToken(); // Consume super class name
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000952 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000953 DeclTy *ImplClsType = Actions.ObjcStartClassImplementation(CurScope,
954 atLoc,
955 nameId, nameLoc,
956 superClassId, superClassLoc);
957
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000958 if (Tok.getKind() == tok::l_brace)
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000959 ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/); // we have ivars
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000960
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000961 return ImplClsType;
Reid Spencer5f016e22007-07-11 17:01:13 +0000962}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000963Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
964 assert(Tok.isObjCAtKeyword(tok::objc_end) &&
965 "ParseObjCAtEndDeclaration(): Expected @end");
966 ConsumeToken(); // the "end" identifier
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000967 if (ObjcImpDecl) {
968 // Checking is not necessary except that a parse error might have caused
969 // @implementation not to have been parsed to completion and ObjcImpDecl
970 // could be 0.
971 /// Insert collected methods declarations into the @interface object.
Fariborz Jahanian9d048ff2007-09-29 00:54:24 +0000972 Actions.ObjcAddMethodsToClass(CurScope, ObjcImpDecl,
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000973 &AllImplMethods[0],AllImplMethods.size());
974 ObjcImpDecl = 0;
975 AllImplMethods.clear();
976 }
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000977
Steve Naroffdac269b2007-08-20 21:31:48 +0000978 return 0;
979}
Fariborz Jahaniane992af02007-09-04 19:26:51 +0000980
981/// compatibility-alias-decl:
982/// @compatibility_alias alias-name class-name ';'
983///
984Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
985 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
986 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
987 ConsumeToken(); // consume compatibility_alias
988 if (Tok.getKind() != tok::identifier) {
989 Diag(Tok, diag::err_expected_ident);
990 return 0;
991 }
992 ConsumeToken(); // consume alias-name
993 if (Tok.getKind() != tok::identifier) {
994 Diag(Tok, diag::err_expected_ident);
995 return 0;
996 }
997 ConsumeToken(); // consume class-name;
998 if (Tok.getKind() != tok::semi)
Fariborz Jahanian8cd8c662007-09-04 21:42:12 +0000999 Diag(Tok, diag::err_expected_semi_after, "@compatibility_alias");
Steve Naroffdac269b2007-08-20 21:31:48 +00001000 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001001}
1002
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001003/// property-synthesis:
1004/// @synthesize property-ivar-list ';'
1005///
1006/// property-ivar-list:
1007/// property-ivar
1008/// property-ivar-list ',' property-ivar
1009///
1010/// property-ivar:
1011/// identifier
1012/// identifier '=' identifier
1013///
1014Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1015 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1016 "ParseObjCPropertyDynamic(): Expected '@synthesize'");
1017 SourceLocation loc = ConsumeToken(); // consume dynamic
1018 if (Tok.getKind() != tok::identifier) {
1019 Diag(Tok, diag::err_expected_ident);
1020 return 0;
1021 }
1022 while (Tok.getKind() == tok::identifier) {
1023 ConsumeToken(); // consume property name
1024 if (Tok.getKind() == tok::equal) {
1025 // property '=' ivar-name
1026 ConsumeToken(); // consume '='
1027 if (Tok.getKind() != tok::identifier) {
1028 Diag(Tok, diag::err_expected_ident);
1029 break;
1030 }
1031 ConsumeToken(); // consume ivar-name
1032 }
1033 if (Tok.getKind() != tok::comma)
1034 break;
1035 ConsumeToken(); // consume ','
1036 }
1037 if (Tok.getKind() != tok::semi)
1038 Diag(Tok, diag::err_expected_semi_after, "@synthesize");
1039 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001040}
1041
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001042/// property-dynamic:
1043/// @dynamic property-list
1044///
1045/// property-list:
1046/// identifier
1047/// property-list ',' identifier
1048///
1049Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1050 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1051 "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1052 SourceLocation loc = ConsumeToken(); // consume dynamic
1053 if (Tok.getKind() != tok::identifier) {
1054 Diag(Tok, diag::err_expected_ident);
1055 return 0;
1056 }
1057 while (Tok.getKind() == tok::identifier) {
1058 ConsumeToken(); // consume property name
1059 if (Tok.getKind() != tok::comma)
1060 break;
1061 ConsumeToken(); // consume ','
1062 }
1063 if (Tok.getKind() != tok::semi)
1064 Diag(Tok, diag::err_expected_semi_after, "@dynamic");
1065 return 0;
1066}
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001067
1068/// objc-throw-statement:
1069/// throw expression[opt];
1070///
1071Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation &atLoc) {
1072 ConsumeToken(); // consume throw
1073 if (Tok.getKind() != tok::semi) {
1074 ExprResult Res = ParseAssignmentExpression();
1075 if (Res.isInvalid) {
1076 SkipUntil(tok::semi);
1077 return 0;
1078 }
1079 }
1080 return 0;
1081}
1082
1083/// objc-try-catch-statement:
1084/// @try compound-statement objc-catch-list[opt]
1085/// @try compound-statement objc-catch-list[opt] @finally compound-statement
1086///
1087/// objc-catch-list:
1088/// @catch ( parameter-declaration ) compound-statement
1089/// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1090/// catch-parameter-declaration:
1091/// parameter-declaration
1092/// '...' [OBJC2]
1093///
1094Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation &atLoc) {
1095 bool catch_or_finally_seen = false;
1096 ConsumeToken(); // consume try
1097 if (Tok.getKind() != tok::l_brace) {
1098 Diag (Tok, diag::err_expected_lbrace);
1099 return 0;
1100 }
1101 StmtResult TryBody = ParseCompoundStatementBody();
1102 while (Tok.getKind() == tok::at) {
1103 ConsumeToken();
1104 if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_catch) {
1105 SourceLocation catchLoc = ConsumeToken(); // consume catch
1106 if (Tok.getKind() == tok::l_paren) {
1107 ConsumeParen();
1108 if (Tok.getKind() != tok::ellipsis) {
1109 DeclSpec DS;
1110 ParseDeclarationSpecifiers(DS);
1111 // Parse the parameter-declaration.
1112 // FIXME: BlockContext may not be the right context!
1113 Declarator ParmDecl(DS, Declarator::BlockContext);
1114 ParseDeclarator(ParmDecl);
1115 }
1116 else
1117 ConsumeToken(); // consume '...'
1118 ConsumeParen();
1119 StmtResult CatchMody = ParseCompoundStatementBody();
1120 }
1121 else {
1122 Diag(catchLoc, diag::err_expected_lparen_after, "@catch clause");
1123 return 0;
1124 }
1125 catch_or_finally_seen = true;
1126 }
1127 else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_finally) {
1128 ConsumeToken(); // consume finally
1129 StmtResult FinallyBody = ParseCompoundStatementBody();
1130 catch_or_finally_seen = true;
1131 break;
1132 }
1133 }
1134 if (!catch_or_finally_seen)
1135 Diag(atLoc, diag::err_missing_catch_finally);
1136 return 0;
1137}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001138
Steve Naroff3536b442007-09-06 21:24:23 +00001139/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001140///
1141void Parser::ParseObjCInstanceMethodDefinition() {
1142 assert(Tok.getKind() == tok::minus &&
1143 "ParseObjCInstanceMethodDefinition(): Expected '-'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001144 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001145 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001146 // parse optional ';'
1147 if (Tok.getKind() == tok::semi)
1148 ConsumeToken();
1149
1150 if (Tok.getKind() != tok::l_brace) {
1151 Diag (Tok, diag::err_expected_lbrace);
1152 return;
1153 }
1154
1155 StmtResult FnBody = ParseCompoundStatementBody();
1156}
1157
Steve Naroff3536b442007-09-06 21:24:23 +00001158/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001159///
Steve Naroff7ef58fd2007-08-22 22:17:26 +00001160void Parser::ParseObjCClassMethodDefinition() {
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001161 assert(Tok.getKind() == tok::plus &&
1162 "ParseObjCClassMethodDefinition(): Expected '+'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001163 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001164 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001165 // parse optional ';'
1166 if (Tok.getKind() == tok::semi)
1167 ConsumeToken();
1168 if (Tok.getKind() != tok::l_brace) {
1169 Diag (Tok, diag::err_expected_lbrace);
1170 return;
1171 }
1172
1173 StmtResult FnBody = ParseCompoundStatementBody();
Reid Spencer5f016e22007-07-11 17:01:13 +00001174}
Anders Carlsson55085182007-08-21 17:43:55 +00001175
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001176Parser::ExprResult Parser::ParseObjCExpression(SourceLocation &AtLoc) {
Anders Carlsson55085182007-08-21 17:43:55 +00001177
1178 switch (Tok.getKind()) {
1179 case tok::string_literal: // primary-expression: string-literal
1180 case tok::wide_string_literal:
1181 return ParseObjCStringLiteral();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001182 default:
1183 break;
1184 }
1185
1186 switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001187 case tok::objc_encode:
1188 return ParseObjCEncodeExpression();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001189 case tok::objc_protocol:
1190 return ParseObjCProtocolExpression();
Anders Carlsson55085182007-08-21 17:43:55 +00001191 default:
1192 Diag(AtLoc, diag::err_unexpected_at);
1193 SkipUntil(tok::semi);
1194 break;
1195 }
1196
1197 return 0;
1198}
1199
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001200/// objc-message-expr:
1201/// '[' objc-receiver objc-message-args ']'
1202///
1203/// objc-receiver:
1204/// expression
1205/// class-name
1206/// type-name
1207///
1208/// objc-message-args:
1209/// objc-selector
1210/// objc-keywordarg-list
1211///
1212/// objc-keywordarg-list:
1213/// objc-keywordarg
1214/// objc-keywordarg-list objc-keywordarg
1215///
1216/// objc-keywordarg:
1217/// selector-name[opt] ':' objc-keywordexpr
1218///
1219/// objc-keywordexpr:
1220/// nonempty-expr-list
1221///
1222/// nonempty-expr-list:
1223/// assignment-expression
1224/// nonempty-expr-list , assignment-expression
1225///
1226Parser::ExprResult Parser::ParseObjCMessageExpression() {
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001227 assert(Tok.getKind() == tok::l_square && "'[' expected");
Steve Naroff563477d2007-09-18 23:55:05 +00001228 SourceLocation LBracloc = ConsumeBracket(); // consume '['
Steve Naroff37387c92007-09-17 20:25:27 +00001229 IdentifierInfo *ReceiverName = 0;
1230 ExprTy *ReceiverExpr = 0;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001231 // Parse receiver
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001232 if (Tok.getKind() == tok::identifier &&
Steve Naroff37387c92007-09-17 20:25:27 +00001233 Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
1234 ReceiverName = Tok.getIdentifierInfo();
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001235 ConsumeToken();
Steve Naroff37387c92007-09-17 20:25:27 +00001236 } else {
1237 ExprResult Res = ParseAssignmentExpression();
1238 if (Res.isInvalid) {
1239 SkipUntil(tok::identifier);
1240 return Res;
1241 }
1242 ReceiverExpr = Res.Val;
1243 }
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001244 // Parse objc-selector
1245 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Naroff68d331a2007-09-27 14:38:14 +00001246
1247 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1248 llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
1249
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001250 if (Tok.getKind() == tok::colon) {
1251 while (1) {
1252 // Each iteration parses a single keyword argument.
Steve Naroff68d331a2007-09-27 14:38:14 +00001253 KeyIdents.push_back(selIdent);
Steve Naroff37387c92007-09-17 20:25:27 +00001254
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001255 if (Tok.getKind() != tok::colon) {
1256 Diag(Tok, diag::err_expected_colon);
1257 SkipUntil(tok::semi);
Steve Naroff37387c92007-09-17 20:25:27 +00001258 return true;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001259 }
Steve Naroff68d331a2007-09-27 14:38:14 +00001260 ConsumeToken(); // Eat the ':'.
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001261 /// Parse the expression after ':'
Steve Naroff37387c92007-09-17 20:25:27 +00001262 ExprResult Res = ParseAssignmentExpression();
1263 if (Res.isInvalid) {
1264 SkipUntil(tok::identifier);
1265 return Res;
1266 }
1267 // We have a valid expression.
Steve Naroff68d331a2007-09-27 14:38:14 +00001268 KeyExprs.push_back(Res.Val);
Steve Naroff37387c92007-09-17 20:25:27 +00001269
1270 // Check for another keyword selector.
1271 selIdent = ParseObjCSelector();
1272 if (!selIdent && Tok.getKind() != tok::colon)
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001273 break;
1274 // We have a selector or a colon, continue parsing.
1275 }
1276 // Parse the, optional, argument list, comma separated.
1277 while (Tok.getKind() == tok::comma) {
1278 ConsumeToken();
1279 /// Parse the expression after ','
1280 ParseAssignmentExpression();
1281 }
1282 } else if (!selIdent) {
1283 Diag(Tok, diag::err_expected_ident); // missing selector name.
1284 SkipUntil(tok::semi);
1285 return 0;
1286 }
1287 if (Tok.getKind() != tok::r_square) {
1288 Diag(Tok, diag::err_expected_rsquare);
1289 SkipUntil(tok::semi);
1290 return 0;
1291 }
Steve Naroff563477d2007-09-18 23:55:05 +00001292 SourceLocation RBracloc = ConsumeBracket(); // consume ']'
Steve Naroff37387c92007-09-17 20:25:27 +00001293
Steve Naroff68d331a2007-09-27 14:38:14 +00001294 if (KeyIdents.size()) {
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001295 Selector sel = ObjcGetKeywordSelector(KeyIdents);
Steve Naroff708391a2007-09-17 21:01:15 +00001296 // We've just parsed a keyword message.
1297 if (ReceiverName)
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001298 return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc,
Steve Naroff68d331a2007-09-27 14:38:14 +00001299 &KeyExprs[0]);
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001300 return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc,
Steve Naroff68d331a2007-09-27 14:38:14 +00001301 &KeyExprs[0]);
Steve Naroff708391a2007-09-17 21:01:15 +00001302 }
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001303 Selector sel = ObjcGetUnarySelector(selIdent);
Steve Naroff68d331a2007-09-27 14:38:14 +00001304
Steve Naroff708391a2007-09-17 21:01:15 +00001305 // We've just parsed a unary message (a message with no arguments).
Steve Naroff37387c92007-09-17 20:25:27 +00001306 if (ReceiverName)
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001307 return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc, 0);
1308 return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc, 0);
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001309}
1310
Anders Carlsson55085182007-08-21 17:43:55 +00001311Parser::ExprResult Parser::ParseObjCStringLiteral() {
1312 ExprResult Res = ParseStringLiteralExpression();
1313
1314 if (Res.isInvalid) return Res;
1315
1316 return Actions.ParseObjCStringLiteral(Res.Val);
1317}
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001318
1319/// objc-encode-expression:
1320/// @encode ( type-name )
1321Parser::ExprResult Parser::ParseObjCEncodeExpression() {
Steve Naroff861cf3e2007-08-23 18:16:40 +00001322 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001323
1324 SourceLocation EncLoc = ConsumeToken();
1325
1326 if (Tok.getKind() != tok::l_paren) {
1327 Diag(Tok, diag::err_expected_lparen_after, "@encode");
1328 return true;
1329 }
1330
1331 SourceLocation LParenLoc = ConsumeParen();
1332
1333 TypeTy *Ty = ParseTypeName();
1334
Anders Carlsson4988ae32007-08-23 15:31:37 +00001335 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001336
1337 return Actions.ParseObjCEncodeExpression(EncLoc, LParenLoc, Ty,
Anders Carlsson4988ae32007-08-23 15:31:37 +00001338 RParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001339}
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001340
1341/// objc-protocol-expression
1342/// @protocol ( protocol-name )
1343
1344Parser::ExprResult Parser::ParseObjCProtocolExpression()
1345{
1346 SourceLocation ProtoLoc = ConsumeToken();
1347
1348 if (Tok.getKind() != tok::l_paren) {
1349 Diag(Tok, diag::err_expected_lparen_after, "@protocol");
1350 return true;
1351 }
1352
1353 SourceLocation LParenLoc = ConsumeParen();
1354
1355 if (Tok.getKind() != tok::identifier) {
1356 Diag(Tok, diag::err_expected_ident);
1357 return true;
1358 }
1359
1360 // FIXME: Do something with the protocol name
1361 ConsumeToken();
1362
Anders Carlsson4988ae32007-08-23 15:31:37 +00001363 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001364
1365 // FIXME
1366 return 0;
1367}