blob: be0e026157b294d049295f9e0eb5ec81144dce52 [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 Jahanianfd225cc2007-09-18 20:26:58 +0000157 DeclTy *CategoryType = Actions.ObjcStartCatInterface(atLoc,
158 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.
Steve Naroffd16245b2007-09-17 15:07:43 +0000271 Actions.ObjcAddMethodsToClass(interfaceDecl,&allMethods[0],allMethods.size());
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000272 return;
Steve Naroff294494e2007-08-22 16:35:03 +0000273}
274
Fariborz Jahaniand0f97d12007-08-31 16:11:31 +0000275/// Parse property attribute declarations.
276///
277/// property-attr-decl: '(' property-attrlist ')'
278/// property-attrlist:
279/// property-attribute
280/// property-attrlist ',' property-attribute
281/// property-attribute:
282/// getter '=' identifier
283/// setter '=' identifier ':'
284/// readonly
285/// readwrite
286/// assign
287/// retain
288/// copy
289/// nonatomic
290///
291void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
292 SourceLocation loc = ConsumeParen(); // consume '('
293 while (isObjCPropertyAttribute()) {
294 const IdentifierInfo *II = Tok.getIdentifierInfo();
295 // getter/setter require extra treatment.
296 if (II == ObjcPropertyAttrs[objc_getter] ||
297 II == ObjcPropertyAttrs[objc_setter]) {
298 // skip getter/setter part.
299 SourceLocation loc = ConsumeToken();
300 if (Tok.getKind() == tok::equal) {
301 loc = ConsumeToken();
302 if (Tok.getKind() == tok::identifier) {
303 if (II == ObjcPropertyAttrs[objc_setter]) {
304 loc = ConsumeToken(); // consume method name
305 if (Tok.getKind() != tok::colon) {
306 Diag(loc, diag::err_expected_colon);
307 SkipUntil(tok::r_paren,true,true);
308 break;
309 }
310 }
311 }
312 else {
313 Diag(loc, diag::err_expected_ident);
314 SkipUntil(tok::r_paren,true,true);
315 break;
316 }
317 }
318 else {
319 Diag(loc, diag::err_objc_expected_equal);
320 SkipUntil(tok::r_paren,true,true);
321 break;
322 }
323 }
324 ConsumeToken(); // consume last attribute token
325 if (Tok.getKind() == tok::comma) {
326 loc = ConsumeToken();
327 continue;
328 }
329 if (Tok.getKind() == tok::r_paren)
330 break;
331 Diag(loc, diag::err_expected_rparen);
332 SkipUntil(tok::semi);
333 return;
334 }
335 if (Tok.getKind() == tok::r_paren)
336 ConsumeParen();
337 else {
338 Diag(loc, diag::err_objc_expected_property_attr);
339 SkipUntil(tok::r_paren); // recover from error inside attribute list
340 }
341}
342
343/// Main routine to parse property declaration.
344///
345/// @property property-attr-decl[opt] property-component-decl ';'
346///
347void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
348 assert(Tok.isObjCAtKeyword(tok::objc_property) &&
349 "ParseObjCPropertyDecl(): Expected @property");
350 ConsumeToken(); // the "property" identifier
351 // Parse property attribute list, if any.
352 if (Tok.getKind() == tok::l_paren) {
353 // property has attribute list.
354 ParseObjCPropertyAttribute(0/*FIXME*/);
355 }
356 // Parse declaration portion of @property.
357 llvm::SmallVector<DeclTy*, 32> PropertyDecls;
358 ParseStructDeclaration(interfaceDecl, PropertyDecls);
359 if (Tok.getKind() == tok::semi)
360 ConsumeToken();
361 else {
362 Diag(Tok, diag::err_expected_semi_decl_list);
363 SkipUntil(tok::r_brace, true, true);
364 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000365}
Steve Naroffdac269b2007-08-20 21:31:48 +0000366
Steve Naroff3536b442007-09-06 21:24:23 +0000367/// objc-method-proto:
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000368/// objc-instance-method objc-method-decl objc-method-attributes[opt]
Steve Naroff3536b442007-09-06 21:24:23 +0000369/// objc-class-method objc-method-decl objc-method-attributes[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000370///
371/// objc-instance-method: '-'
372/// objc-class-method: '+'
373///
Steve Naroff4985ace2007-08-22 18:35:33 +0000374/// objc-method-attributes: [OBJC2]
375/// __attribute__((deprecated))
376///
Fariborz Jahanian00933592007-09-18 00:25:23 +0000377Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
378 tok::ObjCKeywordKind MethodImplKind) {
Steve Naroff294494e2007-08-22 16:35:03 +0000379 assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
380 "expected +/-");
381
382 tok::TokenKind methodType = Tok.getKind();
383 SourceLocation methodLoc = ConsumeToken();
384
Fariborz Jahanian00933592007-09-18 00:25:23 +0000385 DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc, MethodImplKind);
Steve Naroff3536b442007-09-06 21:24:23 +0000386 // Since this rule is used for both method declarations and definitions,
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000387 // the caller is (optionally) responsible for consuming the ';'.
Steve Narofff28b2642007-09-05 23:30:30 +0000388 return MDecl;
Steve Naroff294494e2007-08-22 16:35:03 +0000389}
390
391/// objc-selector:
392/// identifier
393/// one of
394/// enum struct union if else while do for switch case default
395/// break continue return goto asm sizeof typeof __alignof
396/// unsigned long const short volatile signed restrict _Complex
397/// in out inout bycopy byref oneway int char float double void _Bool
398///
399IdentifierInfo *Parser::ParseObjCSelector() {
400 tok::TokenKind tKind = Tok.getKind();
401 IdentifierInfo *II = 0;
Fariborz Jahaniand0649512007-09-27 19:52:15 +0000402 switch (tKind) {
403 case tok::identifier:
404 case tok::kw_typeof:
405 case tok::kw___alignof:
406 case tok::kw_auto:
407 case tok::kw_break:
408 case tok::kw_case:
409 case tok::kw_char:
410 case tok::kw_const:
411 case tok::kw_continue:
412 case tok::kw_default:
413 case tok::kw_do:
414 case tok::kw_double:
415 case tok::kw_else:
416 case tok::kw_enum:
417 case tok::kw_extern:
418 case tok::kw_float:
419 case tok::kw_for:
420 case tok::kw_goto:
421 case tok::kw_if:
422 case tok::kw_inline:
423 case tok::kw_int:
424 case tok::kw_long:
425 case tok::kw_register:
426 case tok::kw_restrict:
427 case tok::kw_return:
428 case tok::kw_short:
429 case tok::kw_signed:
430 case tok::kw_sizeof:
431 case tok::kw_static:
432 case tok::kw_struct:
433 case tok::kw_switch:
434 case tok::kw_typedef:
435 case tok::kw_union:
436 case tok::kw_unsigned:
437 case tok::kw_void:
438 case tok::kw_volatile:
439 case tok::kw_while:
440 case tok::kw__Bool:
441 case tok::kw__Complex:
442 II = Tok.getIdentifierInfo();
443 ConsumeToken();
444 default:
445 break;
446 }
Steve Naroff294494e2007-08-22 16:35:03 +0000447
Steve Naroff294494e2007-08-22 16:35:03 +0000448 return II;
449}
450
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000451/// objc-type-qualifier: one of
452/// in out inout bycopy byref oneway
453///
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000454bool Parser::isObjCTypeQualifier() {
455 if (Tok.getKind() == tok::identifier) {
Chris Lattner34870da2007-08-29 22:54:08 +0000456 const IdentifierInfo *II = Tok.getIdentifierInfo();
457 for (unsigned i = 0; i < objc_NumQuals; ++i)
458 if (II == ObjcTypeQuals[i]) return true;
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000459 }
460 return false;
461}
462
Fariborz Jahaniand0f97d12007-08-31 16:11:31 +0000463/// property-attrlist: one of
464/// readonly getter setter assign retain copy nonatomic
465///
466bool Parser::isObjCPropertyAttribute() {
467 if (Tok.getKind() == tok::identifier) {
468 const IdentifierInfo *II = Tok.getIdentifierInfo();
469 for (unsigned i = 0; i < objc_NumAttrs; ++i)
470 if (II == ObjcPropertyAttrs[i]) return true;
471 }
472 return false;
473}
474
Steve Naroff294494e2007-08-22 16:35:03 +0000475/// objc-type-name:
476/// '(' objc-type-qualifiers[opt] type-name ')'
477/// '(' objc-type-qualifiers[opt] ')'
478///
479/// objc-type-qualifiers:
480/// objc-type-qualifier
481/// objc-type-qualifiers objc-type-qualifier
482///
Steve Narofff28b2642007-09-05 23:30:30 +0000483Parser::TypeTy *Parser::ParseObjCTypeName() {
Steve Naroff294494e2007-08-22 16:35:03 +0000484 assert(Tok.getKind() == tok::l_paren && "expected (");
485
486 SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
Chris Lattner271f1a62007-09-27 15:15:46 +0000487 TypeTy *Ty = 0;
Steve Naroff294494e2007-08-22 16:35:03 +0000488
Steve Naroff4fa7afd2007-08-22 23:18:22 +0000489 while (isObjCTypeQualifier())
490 ConsumeToken();
491
Steve Naroff294494e2007-08-22 16:35:03 +0000492 if (isTypeSpecifierQualifier()) {
Steve Narofff28b2642007-09-05 23:30:30 +0000493 Ty = ParseTypeName();
494 // FIXME: back when Sema support is in place...
495 // assert(Ty && "Parser::ParseObjCTypeName(): missing type");
Steve Naroff294494e2007-08-22 16:35:03 +0000496 }
497 if (Tok.getKind() != tok::r_paren) {
498 MatchRHSPunctuation(tok::r_paren, LParenLoc);
Steve Narofff28b2642007-09-05 23:30:30 +0000499 return 0; // FIXME: decide how we want to handle this error...
Steve Naroff294494e2007-08-22 16:35:03 +0000500 }
501 RParenLoc = ConsumeParen();
Steve Narofff28b2642007-09-05 23:30:30 +0000502 return Ty;
Steve Naroff294494e2007-08-22 16:35:03 +0000503}
504
Steve Naroff5b6b72f2007-09-28 23:39:26 +0000505unsigned Selector::getNumArgs() const {
506 unsigned IIF = getIdentifierInfoFlag();
507 if (IIF == ZeroArg)
508 return 0;
509 if (IIF == OneArg)
510 return 1;
511 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
512 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
513 return SI->getNumArgs();
514}
515
516IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) {
517 IdentifierInfo *II = getAsIdentifierInfo();
518 if (II) {
519 assert(((argIndex == 0) || (argIndex == 1)) && "illegal keyword index");
520 return II;
521 }
522 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
523 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
524 return SI->getIdentifierInfoForSlot(argIndex);
525}
526
527char *MultiKeywordSelector::getName(llvm::SmallVectorImpl<char> &methodName) {
528 methodName[0] = '\0';
529 keyword_iterator KeyIter = keyword_begin();
530 for (unsigned int i = 0; i < NumArgs; i++) {
531 if (KeyIter[i]) {
532 unsigned KeyLen = strlen(KeyIter[i]->getName());
533 methodName.append(KeyIter[i]->getName(), KeyIter[i]->getName()+KeyLen);
534 }
535 methodName.push_back(':');
536 }
537 methodName.push_back('\0');
538 return &methodName[0];
539}
540
541char *Selector::getName(llvm::SmallVectorImpl<char> &methodName) {
542 methodName[0] = '\0';
543 IdentifierInfo *II = getAsIdentifierInfo();
544 if (II) {
545 unsigned NameLen = strlen(II->getName());
546 methodName.append(II->getName(), II->getName()+NameLen);
547 if (getNumArgs() == 1)
548 methodName.push_back(':');
549 methodName.push_back('\0');
550 } else { // We have a multiple keyword selector (no embedded flags).
551 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
552 SI->getName(methodName);
553 }
554 return &methodName[0];
555}
556
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000557Selector Parser::ObjcGetUnarySelector(IdentifierInfo *unarySel)
Steve Naroff68d331a2007-09-27 14:38:14 +0000558{
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000559 return Selector(unarySel, 0);
Steve Naroff68d331a2007-09-27 14:38:14 +0000560}
561
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000562Selector Parser::ObjcGetKeywordSelector(
563 llvm::SmallVectorImpl<IdentifierInfo *> &IIV)
564{
565 if (IIV.size() == 1)
566 return Selector(IIV[0], 1);
567
568 llvm::FoldingSet<MultiKeywordSelector> &SelTab = PP.getSelectorTable();
569
Steve Naroff68d331a2007-09-27 14:38:14 +0000570 // Unique selector, to guarantee there is one per name.
571 llvm::FoldingSetNodeID ID;
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000572 MultiKeywordSelector::Profile(ID, &IIV[0], IIV.size());
Steve Naroff68d331a2007-09-27 14:38:14 +0000573
574 void *InsertPos = 0;
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000575 if (MultiKeywordSelector *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos)) {
576 return Selector(SI);
577 }
578 // MultiKeywordSelector objects are not allocated with new because they have a
Steve Naroff68d331a2007-09-27 14:38:14 +0000579 // variable size array (for parameter types) at the end of them.
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000580 MultiKeywordSelector *SI =
581 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
582 IIV.size()*sizeof(IdentifierInfo *));
583 new (SI) MultiKeywordSelector(IIV.size(), &IIV[0]);
Steve Naroff68d331a2007-09-27 14:38:14 +0000584 SelTab.InsertNode(SI, InsertPos);
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000585 return Selector(SI);
Steve Naroff68d331a2007-09-27 14:38:14 +0000586}
587
Steve Naroff294494e2007-08-22 16:35:03 +0000588/// objc-method-decl:
589/// objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000590/// objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000591/// objc-type-name objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000592/// objc-type-name objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000593///
594/// objc-keyword-selector:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000595/// objc-keyword-decl
Steve Naroff294494e2007-08-22 16:35:03 +0000596/// objc-keyword-selector objc-keyword-decl
597///
598/// objc-keyword-decl:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000599/// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
600/// objc-selector ':' objc-keyword-attributes[opt] identifier
601/// ':' objc-type-name objc-keyword-attributes[opt] identifier
602/// ':' objc-keyword-attributes[opt] identifier
Steve Naroff294494e2007-08-22 16:35:03 +0000603///
Steve Naroff4985ace2007-08-22 18:35:33 +0000604/// objc-parmlist:
605/// objc-parms objc-ellipsis[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000606///
Steve Naroff4985ace2007-08-22 18:35:33 +0000607/// objc-parms:
608/// objc-parms , parameter-declaration
Steve Naroff294494e2007-08-22 16:35:03 +0000609///
Steve Naroff4985ace2007-08-22 18:35:33 +0000610/// objc-ellipsis:
Steve Naroff294494e2007-08-22 16:35:03 +0000611/// , ...
612///
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000613/// objc-keyword-attributes: [OBJC2]
614/// __attribute__((unused))
615///
Steve Naroff68d331a2007-09-27 14:38:14 +0000616Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType,
617 SourceLocation mLoc,
618 tok::ObjCKeywordKind MethodImplKind)
619{
Steve Narofff28b2642007-09-05 23:30:30 +0000620 TypeTy *ReturnType = 0;
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000621 AttributeList *methodAttrs = 0;
Steve Narofff28b2642007-09-05 23:30:30 +0000622
Steve Naroff4985ace2007-08-22 18:35:33 +0000623 // Parse the return type.
Steve Naroff294494e2007-08-22 16:35:03 +0000624 if (Tok.getKind() == tok::l_paren)
Steve Narofff28b2642007-09-05 23:30:30 +0000625 ReturnType = ParseObjCTypeName();
Steve Naroff4985ace2007-08-22 18:35:33 +0000626 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Narofff28b2642007-09-05 23:30:30 +0000627
Steve Naroff68d331a2007-09-27 14:38:14 +0000628 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
629 llvm::SmallVector<Action::TypeTy *, 12> KeyTypes;
630 llvm::SmallVector<IdentifierInfo *, 12> ArgNames;
631
Steve Naroff4985ace2007-08-22 18:35:33 +0000632 if (Tok.getKind() == tok::colon) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000633 Action::TypeTy *TypeInfo;
Steve Narofff28b2642007-09-05 23:30:30 +0000634
Steve Naroff4985ace2007-08-22 18:35:33 +0000635 while (1) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000636 KeyIdents.push_back(selIdent);
Steve Narofff28b2642007-09-05 23:30:30 +0000637
Steve Naroff4985ace2007-08-22 18:35:33 +0000638 // Each iteration parses a single keyword argument.
639 if (Tok.getKind() != tok::colon) {
640 Diag(Tok, diag::err_expected_colon);
641 break;
642 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000643 ConsumeToken(); // Eat the ':'.
Steve Naroff4985ace2007-08-22 18:35:33 +0000644 if (Tok.getKind() == tok::l_paren) // Parse the argument type.
Steve Naroff68d331a2007-09-27 14:38:14 +0000645 TypeInfo = ParseObjCTypeName();
646 else
647 TypeInfo = 0;
648 KeyTypes.push_back(TypeInfo);
649
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000650 // If attributes exist before the argument name, parse them.
Steve Naroff527fe232007-08-23 19:56:30 +0000651 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
Steve Naroff68d331a2007-09-27 14:38:14 +0000652 ParseAttributes(); // FIXME: pass attributes through.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000653
Steve Naroff4985ace2007-08-22 18:35:33 +0000654 if (Tok.getKind() != tok::identifier) {
655 Diag(Tok, diag::err_expected_ident); // missing argument name.
656 break;
657 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000658 ArgNames.push_back(Tok.getIdentifierInfo());
Steve Naroff4985ace2007-08-22 18:35:33 +0000659 ConsumeToken(); // Eat the identifier.
Steve Narofff28b2642007-09-05 23:30:30 +0000660
Steve Naroff37387c92007-09-17 20:25:27 +0000661 // Check for another keyword selector.
Steve Narofff28b2642007-09-05 23:30:30 +0000662 selIdent = ParseObjCSelector();
663 if (!selIdent && Tok.getKind() != tok::colon)
Steve Naroff4985ace2007-08-22 18:35:33 +0000664 break;
665 // We have a selector or a colon, continue parsing.
666 }
667 // Parse the (optional) parameter list.
668 while (Tok.getKind() == tok::comma) {
669 ConsumeToken();
670 if (Tok.getKind() == tok::ellipsis) {
671 ConsumeToken();
672 break;
673 }
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +0000674 // Parse the c-style argument declaration-specifier.
675 DeclSpec DS;
676 ParseDeclarationSpecifiers(DS);
677 // Parse the declarator.
678 Declarator ParmDecl(DS, Declarator::PrototypeContext);
679 ParseDeclarator(ParmDecl);
Steve Naroff4985ace2007-08-22 18:35:33 +0000680 }
Steve Narofff28b2642007-09-05 23:30:30 +0000681 // FIXME: Add support for optional parmameter list...
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000682 // If attributes exist after the method, parse them.
683 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
684 methodAttrs = ParseAttributes();
Steve Naroff68d331a2007-09-27 14:38:14 +0000685
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000686 Selector Sel = ObjcGetKeywordSelector(KeyIdents);
687 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel,
Steve Naroff68d331a2007-09-27 14:38:14 +0000688 &KeyTypes[0], &ArgNames[0],
Fariborz Jahanian00933592007-09-18 00:25:23 +0000689 methodAttrs, MethodImplKind);
Steve Naroff4985ace2007-08-22 18:35:33 +0000690 } else if (!selIdent) {
691 Diag(Tok, diag::err_expected_ident); // missing selector name.
692 }
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000693 // If attributes exist after the method, parse them.
694 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
695 methodAttrs = ParseAttributes();
696
Steve Naroffbcfb06a2007-09-28 22:22:11 +0000697 Selector Sel = ObjcGetUnarySelector(selIdent);
698 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, Sel,
Steve Naroff68d331a2007-09-27 14:38:14 +0000699 0, 0, methodAttrs, MethodImplKind);
Steve Naroff294494e2007-08-22 16:35:03 +0000700}
701
Steve Naroffdac269b2007-08-20 21:31:48 +0000702/// objc-protocol-refs:
703/// '<' identifier-list '>'
704///
Steve Narofff28b2642007-09-05 23:30:30 +0000705bool Parser::ParseObjCProtocolReferences(
706 llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
Steve Naroffdac269b2007-08-20 21:31:48 +0000707 assert(Tok.getKind() == tok::less && "expected <");
708
709 ConsumeToken(); // the "<"
Steve Naroffdac269b2007-08-20 21:31:48 +0000710
711 while (1) {
712 if (Tok.getKind() != tok::identifier) {
713 Diag(Tok, diag::err_expected_ident);
714 SkipUntil(tok::greater);
715 return true;
716 }
717 ProtocolRefs.push_back(Tok.getIdentifierInfo());
718 ConsumeToken();
719
720 if (Tok.getKind() != tok::comma)
721 break;
722 ConsumeToken();
723 }
724 // Consume the '>'.
725 return ExpectAndConsume(tok::greater, diag::err_expected_greater);
726}
727
728/// objc-class-instance-variables:
729/// '{' objc-instance-variable-decl-list[opt] '}'
730///
731/// objc-instance-variable-decl-list:
732/// objc-visibility-spec
733/// objc-instance-variable-decl ';'
734/// ';'
735/// objc-instance-variable-decl-list objc-visibility-spec
736/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
737/// objc-instance-variable-decl-list ';'
738///
739/// objc-visibility-spec:
740/// @private
741/// @protected
742/// @public
Steve Naroffddbff782007-08-21 21:17:12 +0000743/// @package [OBJC2]
Steve Naroffdac269b2007-08-20 21:31:48 +0000744///
745/// objc-instance-variable-decl:
746/// struct-declaration
747///
Steve Naroff3536b442007-09-06 21:24:23 +0000748void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
Steve Naroffddbff782007-08-21 21:17:12 +0000749 assert(Tok.getKind() == tok::l_brace && "expected {");
Steve Naroff3536b442007-09-06 21:24:23 +0000750 llvm::SmallVector<DeclTy*, 16> IvarDecls;
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000751 llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
752 llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
Steve Naroffddbff782007-08-21 21:17:12 +0000753
754 SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
Steve Naroffddbff782007-08-21 21:17:12 +0000755
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000756 tok::ObjCKeywordKind visibility = tok::objc_private;
Steve Naroffddbff782007-08-21 21:17:12 +0000757 // While we still have something to read, read the instance variables.
758 while (Tok.getKind() != tok::r_brace &&
759 Tok.getKind() != tok::eof) {
760 // Each iteration of this loop reads one objc-instance-variable-decl.
761
762 // Check for extraneous top-level semicolon.
763 if (Tok.getKind() == tok::semi) {
764 Diag(Tok, diag::ext_extra_struct_semi);
765 ConsumeToken();
766 continue;
767 }
768 // Set the default visibility to private.
Steve Naroffddbff782007-08-21 21:17:12 +0000769 if (Tok.getKind() == tok::at) { // parse objc-visibility-spec
770 ConsumeToken(); // eat the @ sign
Steve Naroff861cf3e2007-08-23 18:16:40 +0000771 switch (Tok.getObjCKeywordID()) {
Steve Naroffddbff782007-08-21 21:17:12 +0000772 case tok::objc_private:
773 case tok::objc_public:
774 case tok::objc_protected:
775 case tok::objc_package:
Steve Naroff861cf3e2007-08-23 18:16:40 +0000776 visibility = Tok.getObjCKeywordID();
Steve Naroffddbff782007-08-21 21:17:12 +0000777 ConsumeToken();
778 continue;
779 default:
780 Diag(Tok, diag::err_objc_illegal_visibility_spec);
781 ConsumeToken();
782 continue;
783 }
784 }
785 ParseStructDeclaration(interfaceDecl, IvarDecls);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000786 for (unsigned i = 0; i < IvarDecls.size(); i++) {
787 AllIvarDecls.push_back(IvarDecls[i]);
788 AllVisibilities.push_back(visibility);
789 }
Steve Naroff3536b442007-09-06 21:24:23 +0000790 IvarDecls.clear();
791
Steve Naroffddbff782007-08-21 21:17:12 +0000792 if (Tok.getKind() == tok::semi) {
793 ConsumeToken();
794 } else if (Tok.getKind() == tok::r_brace) {
795 Diag(Tok.getLocation(), diag::ext_expected_semi_decl_list);
796 break;
797 } else {
798 Diag(Tok, diag::err_expected_semi_decl_list);
799 // Skip to end of block or statement
800 SkipUntil(tok::r_brace, true, true);
801 }
802 }
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000803 if (AllIvarDecls.size()) { // Check for {} - no ivars in braces
Steve Naroff08d92e42007-09-15 18:49:24 +0000804 Actions.ActOnFields(LBraceLoc, interfaceDecl,
805 &AllIvarDecls[0], AllIvarDecls.size(),
806 &AllVisibilities[0]);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000807 }
Steve Naroffddbff782007-08-21 21:17:12 +0000808 MatchRHSPunctuation(tok::r_brace, LBraceLoc);
809 return;
Reid Spencer5f016e22007-07-11 17:01:13 +0000810}
Steve Naroffdac269b2007-08-20 21:31:48 +0000811
812/// objc-protocol-declaration:
813/// objc-protocol-definition
814/// objc-protocol-forward-reference
815///
816/// objc-protocol-definition:
817/// @protocol identifier
818/// objc-protocol-refs[opt]
Steve Naroff3536b442007-09-06 21:24:23 +0000819/// objc-interface-decl-list
Steve Naroffdac269b2007-08-20 21:31:48 +0000820/// @end
821///
822/// objc-protocol-forward-reference:
823/// @protocol identifier-list ';'
824///
825/// "@protocol identifier ;" should be resolved as "@protocol
Steve Naroff3536b442007-09-06 21:24:23 +0000826/// identifier-list ;": objc-interface-decl-list may not start with a
Steve Naroffdac269b2007-08-20 21:31:48 +0000827/// semicolon in the first alternative if objc-protocol-refs are omitted.
828
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000829Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
Steve Naroff861cf3e2007-08-23 18:16:40 +0000830 assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000831 "ParseObjCAtProtocolDeclaration(): Expected @protocol");
832 ConsumeToken(); // the "protocol" identifier
833
834 if (Tok.getKind() != tok::identifier) {
835 Diag(Tok, diag::err_expected_ident); // missing protocol name.
836 return 0;
837 }
838 // Save the protocol name, then consume it.
839 IdentifierInfo *protocolName = Tok.getIdentifierInfo();
840 SourceLocation nameLoc = ConsumeToken();
841
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000842 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
843 if (Tok.getKind() == tok::semi) { // forward declaration of one protocol.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000844 ConsumeToken();
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000845 ProtocolRefs.push_back(protocolName);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000846 }
847 if (Tok.getKind() == tok::comma) { // list of forward declarations.
848 // Parse the list of forward declarations.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000849 ProtocolRefs.push_back(protocolName);
850
851 while (1) {
852 ConsumeToken(); // the ','
853 if (Tok.getKind() != tok::identifier) {
854 Diag(Tok, diag::err_expected_ident);
855 SkipUntil(tok::semi);
856 return 0;
857 }
858 ProtocolRefs.push_back(Tok.getIdentifierInfo());
859 ConsumeToken(); // the identifier
860
861 if (Tok.getKind() != tok::comma)
862 break;
863 }
864 // Consume the ';'.
865 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
866 return 0;
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000867 }
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000868 if (ProtocolRefs.size() > 0)
869 return Actions.ObjcForwardProtocolDeclaration(CurScope, AtLoc,
870 &ProtocolRefs[0],
871 ProtocolRefs.size());
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000872 // Last, and definitely not least, parse a protocol declaration.
873 if (Tok.getKind() == tok::less) {
Steve Narofff28b2642007-09-05 23:30:30 +0000874 if (ParseObjCProtocolReferences(ProtocolRefs))
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000875 return 0;
876 }
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000877
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000878 DeclTy *ProtoType = Actions.ObjcStartProtoInterface(CurScope, AtLoc,
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000879 protocolName, nameLoc,
880 &ProtocolRefs[0],
881 ProtocolRefs.size());
882 ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000883
884 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
Steve Naroff861cf3e2007-08-23 18:16:40 +0000885 if (Tok.isObjCAtKeyword(tok::objc_end)) {
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000886 ConsumeToken(); // the "end" identifier
887 return 0;
888 }
889 Diag(Tok, diag::err_objc_missing_end);
Steve Naroffdac269b2007-08-20 21:31:48 +0000890 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000891}
Steve Naroffdac269b2007-08-20 21:31:48 +0000892
893/// objc-implementation:
894/// objc-class-implementation-prologue
895/// objc-category-implementation-prologue
896///
897/// objc-class-implementation-prologue:
898/// @implementation identifier objc-superclass[opt]
899/// objc-class-instance-variables[opt]
900///
901/// objc-category-implementation-prologue:
902/// @implementation identifier ( identifier )
903
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000904Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
905 SourceLocation atLoc) {
906 assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
907 "ParseObjCAtImplementationDeclaration(): Expected @implementation");
908 ConsumeToken(); // the "implementation" identifier
909
910 if (Tok.getKind() != tok::identifier) {
911 Diag(Tok, diag::err_expected_ident); // missing class or category name.
912 return 0;
913 }
914 // We have a class or category name - consume it.
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000915 IdentifierInfo *nameId = Tok.getIdentifierInfo();
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000916 SourceLocation nameLoc = ConsumeToken(); // consume class or category name
917
918 if (Tok.getKind() == tok::l_paren) {
919 // we have a category implementation.
920 SourceLocation lparenLoc = ConsumeParen();
921 SourceLocation categoryLoc, rparenLoc;
922 IdentifierInfo *categoryId = 0;
923
924 if (Tok.getKind() == tok::identifier) {
925 categoryId = Tok.getIdentifierInfo();
926 categoryLoc = ConsumeToken();
927 } else {
928 Diag(Tok, diag::err_expected_ident); // missing category name.
929 return 0;
930 }
931 if (Tok.getKind() != tok::r_paren) {
932 Diag(Tok, diag::err_expected_rparen);
933 SkipUntil(tok::r_paren, false); // don't stop at ';'
934 return 0;
935 }
936 rparenLoc = ConsumeParen();
937 return 0;
938 }
939 // We have a class implementation
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000940 SourceLocation superClassLoc;
941 IdentifierInfo *superClassId = 0;
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000942 if (Tok.getKind() == tok::colon) {
943 // We have a super class
944 ConsumeToken();
945 if (Tok.getKind() != tok::identifier) {
946 Diag(Tok, diag::err_expected_ident); // missing super class name.
947 return 0;
948 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000949 superClassId = Tok.getIdentifierInfo();
950 superClassLoc = ConsumeToken(); // Consume super class name
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000951 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000952 DeclTy *ImplClsType = Actions.ObjcStartClassImplementation(CurScope,
953 atLoc,
954 nameId, nameLoc,
955 superClassId, superClassLoc);
956
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000957 if (Tok.getKind() == tok::l_brace)
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000958 ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/); // we have ivars
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000959
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000960 return ImplClsType;
Reid Spencer5f016e22007-07-11 17:01:13 +0000961}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000962Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
963 assert(Tok.isObjCAtKeyword(tok::objc_end) &&
964 "ParseObjCAtEndDeclaration(): Expected @end");
965 ConsumeToken(); // the "end" identifier
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000966 if (ObjcImpDecl) {
967 // Checking is not necessary except that a parse error might have caused
968 // @implementation not to have been parsed to completion and ObjcImpDecl
969 // could be 0.
970 /// Insert collected methods declarations into the @interface object.
971 Actions.ObjcAddMethodsToClass(ObjcImpDecl,
972 &AllImplMethods[0],AllImplMethods.size());
973 ObjcImpDecl = 0;
974 AllImplMethods.clear();
975 }
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000976
Steve Naroffdac269b2007-08-20 21:31:48 +0000977 return 0;
978}
Fariborz Jahaniane992af02007-09-04 19:26:51 +0000979
980/// compatibility-alias-decl:
981/// @compatibility_alias alias-name class-name ';'
982///
983Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
984 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
985 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
986 ConsumeToken(); // consume compatibility_alias
987 if (Tok.getKind() != tok::identifier) {
988 Diag(Tok, diag::err_expected_ident);
989 return 0;
990 }
991 ConsumeToken(); // consume alias-name
992 if (Tok.getKind() != tok::identifier) {
993 Diag(Tok, diag::err_expected_ident);
994 return 0;
995 }
996 ConsumeToken(); // consume class-name;
997 if (Tok.getKind() != tok::semi)
Fariborz Jahanian8cd8c662007-09-04 21:42:12 +0000998 Diag(Tok, diag::err_expected_semi_after, "@compatibility_alias");
Steve Naroffdac269b2007-08-20 21:31:48 +0000999 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001000}
1001
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001002/// property-synthesis:
1003/// @synthesize property-ivar-list ';'
1004///
1005/// property-ivar-list:
1006/// property-ivar
1007/// property-ivar-list ',' property-ivar
1008///
1009/// property-ivar:
1010/// identifier
1011/// identifier '=' identifier
1012///
1013Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1014 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1015 "ParseObjCPropertyDynamic(): Expected '@synthesize'");
1016 SourceLocation loc = ConsumeToken(); // consume dynamic
1017 if (Tok.getKind() != tok::identifier) {
1018 Diag(Tok, diag::err_expected_ident);
1019 return 0;
1020 }
1021 while (Tok.getKind() == tok::identifier) {
1022 ConsumeToken(); // consume property name
1023 if (Tok.getKind() == tok::equal) {
1024 // property '=' ivar-name
1025 ConsumeToken(); // consume '='
1026 if (Tok.getKind() != tok::identifier) {
1027 Diag(Tok, diag::err_expected_ident);
1028 break;
1029 }
1030 ConsumeToken(); // consume ivar-name
1031 }
1032 if (Tok.getKind() != tok::comma)
1033 break;
1034 ConsumeToken(); // consume ','
1035 }
1036 if (Tok.getKind() != tok::semi)
1037 Diag(Tok, diag::err_expected_semi_after, "@synthesize");
1038 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001039}
1040
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001041/// property-dynamic:
1042/// @dynamic property-list
1043///
1044/// property-list:
1045/// identifier
1046/// property-list ',' identifier
1047///
1048Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1049 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1050 "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1051 SourceLocation loc = ConsumeToken(); // consume dynamic
1052 if (Tok.getKind() != tok::identifier) {
1053 Diag(Tok, diag::err_expected_ident);
1054 return 0;
1055 }
1056 while (Tok.getKind() == tok::identifier) {
1057 ConsumeToken(); // consume property name
1058 if (Tok.getKind() != tok::comma)
1059 break;
1060 ConsumeToken(); // consume ','
1061 }
1062 if (Tok.getKind() != tok::semi)
1063 Diag(Tok, diag::err_expected_semi_after, "@dynamic");
1064 return 0;
1065}
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001066
1067/// objc-throw-statement:
1068/// throw expression[opt];
1069///
1070Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation &atLoc) {
1071 ConsumeToken(); // consume throw
1072 if (Tok.getKind() != tok::semi) {
1073 ExprResult Res = ParseAssignmentExpression();
1074 if (Res.isInvalid) {
1075 SkipUntil(tok::semi);
1076 return 0;
1077 }
1078 }
1079 return 0;
1080}
1081
1082/// objc-try-catch-statement:
1083/// @try compound-statement objc-catch-list[opt]
1084/// @try compound-statement objc-catch-list[opt] @finally compound-statement
1085///
1086/// objc-catch-list:
1087/// @catch ( parameter-declaration ) compound-statement
1088/// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1089/// catch-parameter-declaration:
1090/// parameter-declaration
1091/// '...' [OBJC2]
1092///
1093Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation &atLoc) {
1094 bool catch_or_finally_seen = false;
1095 ConsumeToken(); // consume try
1096 if (Tok.getKind() != tok::l_brace) {
1097 Diag (Tok, diag::err_expected_lbrace);
1098 return 0;
1099 }
1100 StmtResult TryBody = ParseCompoundStatementBody();
1101 while (Tok.getKind() == tok::at) {
1102 ConsumeToken();
1103 if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_catch) {
1104 SourceLocation catchLoc = ConsumeToken(); // consume catch
1105 if (Tok.getKind() == tok::l_paren) {
1106 ConsumeParen();
1107 if (Tok.getKind() != tok::ellipsis) {
1108 DeclSpec DS;
1109 ParseDeclarationSpecifiers(DS);
1110 // Parse the parameter-declaration.
1111 // FIXME: BlockContext may not be the right context!
1112 Declarator ParmDecl(DS, Declarator::BlockContext);
1113 ParseDeclarator(ParmDecl);
1114 }
1115 else
1116 ConsumeToken(); // consume '...'
1117 ConsumeParen();
1118 StmtResult CatchMody = ParseCompoundStatementBody();
1119 }
1120 else {
1121 Diag(catchLoc, diag::err_expected_lparen_after, "@catch clause");
1122 return 0;
1123 }
1124 catch_or_finally_seen = true;
1125 }
1126 else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_finally) {
1127 ConsumeToken(); // consume finally
1128 StmtResult FinallyBody = ParseCompoundStatementBody();
1129 catch_or_finally_seen = true;
1130 break;
1131 }
1132 }
1133 if (!catch_or_finally_seen)
1134 Diag(atLoc, diag::err_missing_catch_finally);
1135 return 0;
1136}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001137
Steve Naroff3536b442007-09-06 21:24:23 +00001138/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001139///
1140void Parser::ParseObjCInstanceMethodDefinition() {
1141 assert(Tok.getKind() == tok::minus &&
1142 "ParseObjCInstanceMethodDefinition(): Expected '-'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001143 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001144 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001145 // parse optional ';'
1146 if (Tok.getKind() == tok::semi)
1147 ConsumeToken();
1148
1149 if (Tok.getKind() != tok::l_brace) {
1150 Diag (Tok, diag::err_expected_lbrace);
1151 return;
1152 }
1153
1154 StmtResult FnBody = ParseCompoundStatementBody();
1155}
1156
Steve Naroff3536b442007-09-06 21:24:23 +00001157/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001158///
Steve Naroff7ef58fd2007-08-22 22:17:26 +00001159void Parser::ParseObjCClassMethodDefinition() {
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001160 assert(Tok.getKind() == tok::plus &&
1161 "ParseObjCClassMethodDefinition(): Expected '+'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001162 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001163 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001164 // parse optional ';'
1165 if (Tok.getKind() == tok::semi)
1166 ConsumeToken();
1167 if (Tok.getKind() != tok::l_brace) {
1168 Diag (Tok, diag::err_expected_lbrace);
1169 return;
1170 }
1171
1172 StmtResult FnBody = ParseCompoundStatementBody();
Reid Spencer5f016e22007-07-11 17:01:13 +00001173}
Anders Carlsson55085182007-08-21 17:43:55 +00001174
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001175Parser::ExprResult Parser::ParseObjCExpression(SourceLocation &AtLoc) {
Anders Carlsson55085182007-08-21 17:43:55 +00001176
1177 switch (Tok.getKind()) {
1178 case tok::string_literal: // primary-expression: string-literal
1179 case tok::wide_string_literal:
1180 return ParseObjCStringLiteral();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001181 default:
1182 break;
1183 }
1184
1185 switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001186 case tok::objc_encode:
1187 return ParseObjCEncodeExpression();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001188 case tok::objc_protocol:
1189 return ParseObjCProtocolExpression();
Anders Carlsson55085182007-08-21 17:43:55 +00001190 default:
1191 Diag(AtLoc, diag::err_unexpected_at);
1192 SkipUntil(tok::semi);
1193 break;
1194 }
1195
1196 return 0;
1197}
1198
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001199/// objc-message-expr:
1200/// '[' objc-receiver objc-message-args ']'
1201///
1202/// objc-receiver:
1203/// expression
1204/// class-name
1205/// type-name
1206///
1207/// objc-message-args:
1208/// objc-selector
1209/// objc-keywordarg-list
1210///
1211/// objc-keywordarg-list:
1212/// objc-keywordarg
1213/// objc-keywordarg-list objc-keywordarg
1214///
1215/// objc-keywordarg:
1216/// selector-name[opt] ':' objc-keywordexpr
1217///
1218/// objc-keywordexpr:
1219/// nonempty-expr-list
1220///
1221/// nonempty-expr-list:
1222/// assignment-expression
1223/// nonempty-expr-list , assignment-expression
1224///
1225Parser::ExprResult Parser::ParseObjCMessageExpression() {
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001226 assert(Tok.getKind() == tok::l_square && "'[' expected");
Steve Naroff563477d2007-09-18 23:55:05 +00001227 SourceLocation LBracloc = ConsumeBracket(); // consume '['
Steve Naroff37387c92007-09-17 20:25:27 +00001228 IdentifierInfo *ReceiverName = 0;
1229 ExprTy *ReceiverExpr = 0;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001230 // Parse receiver
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001231 if (Tok.getKind() == tok::identifier &&
Steve Naroff37387c92007-09-17 20:25:27 +00001232 Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
1233 ReceiverName = Tok.getIdentifierInfo();
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001234 ConsumeToken();
Steve Naroff37387c92007-09-17 20:25:27 +00001235 } else {
1236 ExprResult Res = ParseAssignmentExpression();
1237 if (Res.isInvalid) {
1238 SkipUntil(tok::identifier);
1239 return Res;
1240 }
1241 ReceiverExpr = Res.Val;
1242 }
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001243 // Parse objc-selector
1244 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Naroff68d331a2007-09-27 14:38:14 +00001245
1246 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1247 llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
1248
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001249 if (Tok.getKind() == tok::colon) {
1250 while (1) {
1251 // Each iteration parses a single keyword argument.
Steve Naroff68d331a2007-09-27 14:38:14 +00001252 KeyIdents.push_back(selIdent);
Steve Naroff37387c92007-09-17 20:25:27 +00001253
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001254 if (Tok.getKind() != tok::colon) {
1255 Diag(Tok, diag::err_expected_colon);
1256 SkipUntil(tok::semi);
Steve Naroff37387c92007-09-17 20:25:27 +00001257 return true;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001258 }
Steve Naroff68d331a2007-09-27 14:38:14 +00001259 ConsumeToken(); // Eat the ':'.
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001260 /// Parse the expression after ':'
Steve Naroff37387c92007-09-17 20:25:27 +00001261 ExprResult Res = ParseAssignmentExpression();
1262 if (Res.isInvalid) {
1263 SkipUntil(tok::identifier);
1264 return Res;
1265 }
1266 // We have a valid expression.
Steve Naroff68d331a2007-09-27 14:38:14 +00001267 KeyExprs.push_back(Res.Val);
Steve Naroff37387c92007-09-17 20:25:27 +00001268
1269 // Check for another keyword selector.
1270 selIdent = ParseObjCSelector();
1271 if (!selIdent && Tok.getKind() != tok::colon)
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001272 break;
1273 // We have a selector or a colon, continue parsing.
1274 }
1275 // Parse the, optional, argument list, comma separated.
1276 while (Tok.getKind() == tok::comma) {
1277 ConsumeToken();
1278 /// Parse the expression after ','
1279 ParseAssignmentExpression();
1280 }
1281 } else if (!selIdent) {
1282 Diag(Tok, diag::err_expected_ident); // missing selector name.
1283 SkipUntil(tok::semi);
1284 return 0;
1285 }
1286 if (Tok.getKind() != tok::r_square) {
1287 Diag(Tok, diag::err_expected_rsquare);
1288 SkipUntil(tok::semi);
1289 return 0;
1290 }
Steve Naroff563477d2007-09-18 23:55:05 +00001291 SourceLocation RBracloc = ConsumeBracket(); // consume ']'
Steve Naroff37387c92007-09-17 20:25:27 +00001292
Steve Naroff68d331a2007-09-27 14:38:14 +00001293 if (KeyIdents.size()) {
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001294 Selector sel = ObjcGetKeywordSelector(KeyIdents);
Steve Naroff708391a2007-09-17 21:01:15 +00001295 // We've just parsed a keyword message.
1296 if (ReceiverName)
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001297 return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc,
Steve Naroff68d331a2007-09-27 14:38:14 +00001298 &KeyExprs[0]);
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001299 return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc,
Steve Naroff68d331a2007-09-27 14:38:14 +00001300 &KeyExprs[0]);
Steve Naroff708391a2007-09-17 21:01:15 +00001301 }
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001302 Selector sel = ObjcGetUnarySelector(selIdent);
Steve Naroff68d331a2007-09-27 14:38:14 +00001303
Steve Naroff708391a2007-09-17 21:01:15 +00001304 // We've just parsed a unary message (a message with no arguments).
Steve Naroff37387c92007-09-17 20:25:27 +00001305 if (ReceiverName)
Steve Naroffbcfb06a2007-09-28 22:22:11 +00001306 return Actions.ActOnClassMessage(ReceiverName, sel, LBracloc, RBracloc, 0);
1307 return Actions.ActOnInstanceMessage(ReceiverExpr, sel, LBracloc, RBracloc, 0);
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001308}
1309
Anders Carlsson55085182007-08-21 17:43:55 +00001310Parser::ExprResult Parser::ParseObjCStringLiteral() {
1311 ExprResult Res = ParseStringLiteralExpression();
1312
1313 if (Res.isInvalid) return Res;
1314
1315 return Actions.ParseObjCStringLiteral(Res.Val);
1316}
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001317
1318/// objc-encode-expression:
1319/// @encode ( type-name )
1320Parser::ExprResult Parser::ParseObjCEncodeExpression() {
Steve Naroff861cf3e2007-08-23 18:16:40 +00001321 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001322
1323 SourceLocation EncLoc = ConsumeToken();
1324
1325 if (Tok.getKind() != tok::l_paren) {
1326 Diag(Tok, diag::err_expected_lparen_after, "@encode");
1327 return true;
1328 }
1329
1330 SourceLocation LParenLoc = ConsumeParen();
1331
1332 TypeTy *Ty = ParseTypeName();
1333
Anders Carlsson4988ae32007-08-23 15:31:37 +00001334 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001335
1336 return Actions.ParseObjCEncodeExpression(EncLoc, LParenLoc, Ty,
Anders Carlsson4988ae32007-08-23 15:31:37 +00001337 RParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001338}
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001339
1340/// objc-protocol-expression
1341/// @protocol ( protocol-name )
1342
1343Parser::ExprResult Parser::ParseObjCProtocolExpression()
1344{
1345 SourceLocation ProtoLoc = ConsumeToken();
1346
1347 if (Tok.getKind() != tok::l_paren) {
1348 Diag(Tok, diag::err_expected_lparen_after, "@protocol");
1349 return true;
1350 }
1351
1352 SourceLocation LParenLoc = ConsumeParen();
1353
1354 if (Tok.getKind() != tok::identifier) {
1355 Diag(Tok, diag::err_expected_ident);
1356 return true;
1357 }
1358
1359 // FIXME: Do something with the protocol name
1360 ConsumeToken();
1361
Anders Carlsson4988ae32007-08-23 15:31:37 +00001362 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001363
1364 // FIXME
1365 return 0;
1366}