blob: ba29edec4bf83e6abbba777f2ad2b18c8422729b [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 Naroff68d331a2007-09-27 14:38:14 +0000505static SelectorInfo *ObjcGetUnarySelectorInfo(
506 IdentifierInfo *unarySel,
507 llvm::FoldingSet<SelectorInfo> &SelTab)
508{
509 // Unique selector, to guarantee there is one per name.
510 llvm::SmallVector<IdentifierInfo *, 1> IIV;
511 llvm::FoldingSetNodeID ID;
512
513 IIV.push_back(unarySel);
514 SelectorInfo::Profile(ID, &IIV[0], 0);
515
516 void *InsertPos = 0;
517 if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos))
518 return SI;
519
520 // SelectorInfo objects are not allocated with new because they have a
521 // variable size array (for parameter types) at the end of them.
522 SelectorInfo *SI =
523 (SelectorInfo*)malloc(sizeof(SelectorInfo) + sizeof(IdentifierInfo *));
524 new (SI) SelectorInfo(IIV[0]);
525 SelTab.InsertNode(SI, InsertPos);
526 return SI;
527}
528
529static SelectorInfo *ObjcGetKeywordSelectorInfo(
530 llvm::SmallVectorImpl<IdentifierInfo *> &IIV,
531 llvm::FoldingSet<SelectorInfo> &SelTab)
532{
533 // Unique selector, to guarantee there is one per name.
534 llvm::FoldingSetNodeID ID;
535 SelectorInfo::Profile(ID, &IIV[0], IIV.size());
536
537 void *InsertPos = 0;
538 if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos))
539 return SI;
540
541 // SelectorInfo objects are not allocated with new because they have a
542 // variable size array (for parameter types) at the end of them.
543 SelectorInfo *SI =
544 (SelectorInfo*)malloc(sizeof(SelectorInfo) +
545 IIV.size()*sizeof(IdentifierInfo *));
546 new (SI) SelectorInfo(IIV.size(), &IIV[0]);
547 SelTab.InsertNode(SI, InsertPos);
548 return SI;
549}
550
Steve Naroff294494e2007-08-22 16:35:03 +0000551/// objc-method-decl:
552/// objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000553/// objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000554/// objc-type-name objc-selector
Steve Naroff4985ace2007-08-22 18:35:33 +0000555/// objc-type-name objc-keyword-selector objc-parmlist[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000556///
557/// objc-keyword-selector:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000558/// objc-keyword-decl
Steve Naroff294494e2007-08-22 16:35:03 +0000559/// objc-keyword-selector objc-keyword-decl
560///
561/// objc-keyword-decl:
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000562/// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
563/// objc-selector ':' objc-keyword-attributes[opt] identifier
564/// ':' objc-type-name objc-keyword-attributes[opt] identifier
565/// ':' objc-keyword-attributes[opt] identifier
Steve Naroff294494e2007-08-22 16:35:03 +0000566///
Steve Naroff4985ace2007-08-22 18:35:33 +0000567/// objc-parmlist:
568/// objc-parms objc-ellipsis[opt]
Steve Naroff294494e2007-08-22 16:35:03 +0000569///
Steve Naroff4985ace2007-08-22 18:35:33 +0000570/// objc-parms:
571/// objc-parms , parameter-declaration
Steve Naroff294494e2007-08-22 16:35:03 +0000572///
Steve Naroff4985ace2007-08-22 18:35:33 +0000573/// objc-ellipsis:
Steve Naroff294494e2007-08-22 16:35:03 +0000574/// , ...
575///
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000576/// objc-keyword-attributes: [OBJC2]
577/// __attribute__((unused))
578///
Steve Naroff68d331a2007-09-27 14:38:14 +0000579Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType,
580 SourceLocation mLoc,
581 tok::ObjCKeywordKind MethodImplKind)
582{
Steve Narofff28b2642007-09-05 23:30:30 +0000583 TypeTy *ReturnType = 0;
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000584 AttributeList *methodAttrs = 0;
Steve Narofff28b2642007-09-05 23:30:30 +0000585
Steve Naroff4985ace2007-08-22 18:35:33 +0000586 // Parse the return type.
Steve Naroff294494e2007-08-22 16:35:03 +0000587 if (Tok.getKind() == tok::l_paren)
Steve Narofff28b2642007-09-05 23:30:30 +0000588 ReturnType = ParseObjCTypeName();
Steve Naroff4985ace2007-08-22 18:35:33 +0000589 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Narofff28b2642007-09-05 23:30:30 +0000590
Steve Naroff68d331a2007-09-27 14:38:14 +0000591 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
592 llvm::SmallVector<Action::TypeTy *, 12> KeyTypes;
593 llvm::SmallVector<IdentifierInfo *, 12> ArgNames;
594
Steve Naroff4985ace2007-08-22 18:35:33 +0000595 if (Tok.getKind() == tok::colon) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000596 Action::TypeTy *TypeInfo;
Steve Narofff28b2642007-09-05 23:30:30 +0000597
Steve Naroff4985ace2007-08-22 18:35:33 +0000598 while (1) {
Steve Naroff68d331a2007-09-27 14:38:14 +0000599 KeyIdents.push_back(selIdent);
Steve Narofff28b2642007-09-05 23:30:30 +0000600
Steve Naroff4985ace2007-08-22 18:35:33 +0000601 // Each iteration parses a single keyword argument.
602 if (Tok.getKind() != tok::colon) {
603 Diag(Tok, diag::err_expected_colon);
604 break;
605 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000606 ConsumeToken(); // Eat the ':'.
Steve Naroff4985ace2007-08-22 18:35:33 +0000607 if (Tok.getKind() == tok::l_paren) // Parse the argument type.
Steve Naroff68d331a2007-09-27 14:38:14 +0000608 TypeInfo = ParseObjCTypeName();
609 else
610 TypeInfo = 0;
611 KeyTypes.push_back(TypeInfo);
612
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000613 // If attributes exist before the argument name, parse them.
Steve Naroff527fe232007-08-23 19:56:30 +0000614 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
Steve Naroff68d331a2007-09-27 14:38:14 +0000615 ParseAttributes(); // FIXME: pass attributes through.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000616
Steve Naroff4985ace2007-08-22 18:35:33 +0000617 if (Tok.getKind() != tok::identifier) {
618 Diag(Tok, diag::err_expected_ident); // missing argument name.
619 break;
620 }
Steve Naroff68d331a2007-09-27 14:38:14 +0000621 ArgNames.push_back(Tok.getIdentifierInfo());
Steve Naroff4985ace2007-08-22 18:35:33 +0000622 ConsumeToken(); // Eat the identifier.
Steve Narofff28b2642007-09-05 23:30:30 +0000623
Steve Naroff37387c92007-09-17 20:25:27 +0000624 // Check for another keyword selector.
Steve Narofff28b2642007-09-05 23:30:30 +0000625 selIdent = ParseObjCSelector();
626 if (!selIdent && Tok.getKind() != tok::colon)
Steve Naroff4985ace2007-08-22 18:35:33 +0000627 break;
628 // We have a selector or a colon, continue parsing.
629 }
630 // Parse the (optional) parameter list.
631 while (Tok.getKind() == tok::comma) {
632 ConsumeToken();
633 if (Tok.getKind() == tok::ellipsis) {
634 ConsumeToken();
635 break;
636 }
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +0000637 // Parse the c-style argument declaration-specifier.
638 DeclSpec DS;
639 ParseDeclarationSpecifiers(DS);
640 // Parse the declarator.
641 Declarator ParmDecl(DS, Declarator::PrototypeContext);
642 ParseDeclarator(ParmDecl);
Steve Naroff4985ace2007-08-22 18:35:33 +0000643 }
Steve Narofff28b2642007-09-05 23:30:30 +0000644 // FIXME: Add support for optional parmameter list...
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000645 // If attributes exist after the method, parse them.
646 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
647 methodAttrs = ParseAttributes();
Steve Naroff68d331a2007-09-27 14:38:14 +0000648
649 SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents,
650 PP.getSelectorTable());
651 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI,
652 &KeyTypes[0], &ArgNames[0],
Fariborz Jahanian00933592007-09-18 00:25:23 +0000653 methodAttrs, MethodImplKind);
Steve Naroff4985ace2007-08-22 18:35:33 +0000654 } else if (!selIdent) {
655 Diag(Tok, diag::err_expected_ident); // missing selector name.
656 }
Fariborz Jahaniane3a2ca72007-09-10 20:33:04 +0000657 // If attributes exist after the method, parse them.
658 if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
659 methodAttrs = ParseAttributes();
660
Steve Naroff68d331a2007-09-27 14:38:14 +0000661 SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable());
662 return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI,
663 0, 0, methodAttrs, MethodImplKind);
Steve Naroff294494e2007-08-22 16:35:03 +0000664}
665
Steve Naroffdac269b2007-08-20 21:31:48 +0000666/// objc-protocol-refs:
667/// '<' identifier-list '>'
668///
Steve Narofff28b2642007-09-05 23:30:30 +0000669bool Parser::ParseObjCProtocolReferences(
670 llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
Steve Naroffdac269b2007-08-20 21:31:48 +0000671 assert(Tok.getKind() == tok::less && "expected <");
672
673 ConsumeToken(); // the "<"
Steve Naroffdac269b2007-08-20 21:31:48 +0000674
675 while (1) {
676 if (Tok.getKind() != tok::identifier) {
677 Diag(Tok, diag::err_expected_ident);
678 SkipUntil(tok::greater);
679 return true;
680 }
681 ProtocolRefs.push_back(Tok.getIdentifierInfo());
682 ConsumeToken();
683
684 if (Tok.getKind() != tok::comma)
685 break;
686 ConsumeToken();
687 }
688 // Consume the '>'.
689 return ExpectAndConsume(tok::greater, diag::err_expected_greater);
690}
691
692/// objc-class-instance-variables:
693/// '{' objc-instance-variable-decl-list[opt] '}'
694///
695/// objc-instance-variable-decl-list:
696/// objc-visibility-spec
697/// objc-instance-variable-decl ';'
698/// ';'
699/// objc-instance-variable-decl-list objc-visibility-spec
700/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
701/// objc-instance-variable-decl-list ';'
702///
703/// objc-visibility-spec:
704/// @private
705/// @protected
706/// @public
Steve Naroffddbff782007-08-21 21:17:12 +0000707/// @package [OBJC2]
Steve Naroffdac269b2007-08-20 21:31:48 +0000708///
709/// objc-instance-variable-decl:
710/// struct-declaration
711///
Steve Naroff3536b442007-09-06 21:24:23 +0000712void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
Steve Naroffddbff782007-08-21 21:17:12 +0000713 assert(Tok.getKind() == tok::l_brace && "expected {");
Steve Naroff3536b442007-09-06 21:24:23 +0000714 llvm::SmallVector<DeclTy*, 16> IvarDecls;
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000715 llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
716 llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
Steve Naroffddbff782007-08-21 21:17:12 +0000717
718 SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
Steve Naroffddbff782007-08-21 21:17:12 +0000719
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000720 tok::ObjCKeywordKind visibility = tok::objc_private;
Steve Naroffddbff782007-08-21 21:17:12 +0000721 // While we still have something to read, read the instance variables.
722 while (Tok.getKind() != tok::r_brace &&
723 Tok.getKind() != tok::eof) {
724 // Each iteration of this loop reads one objc-instance-variable-decl.
725
726 // Check for extraneous top-level semicolon.
727 if (Tok.getKind() == tok::semi) {
728 Diag(Tok, diag::ext_extra_struct_semi);
729 ConsumeToken();
730 continue;
731 }
732 // Set the default visibility to private.
Steve Naroffddbff782007-08-21 21:17:12 +0000733 if (Tok.getKind() == tok::at) { // parse objc-visibility-spec
734 ConsumeToken(); // eat the @ sign
Steve Naroff861cf3e2007-08-23 18:16:40 +0000735 switch (Tok.getObjCKeywordID()) {
Steve Naroffddbff782007-08-21 21:17:12 +0000736 case tok::objc_private:
737 case tok::objc_public:
738 case tok::objc_protected:
739 case tok::objc_package:
Steve Naroff861cf3e2007-08-23 18:16:40 +0000740 visibility = Tok.getObjCKeywordID();
Steve Naroffddbff782007-08-21 21:17:12 +0000741 ConsumeToken();
742 continue;
743 default:
744 Diag(Tok, diag::err_objc_illegal_visibility_spec);
745 ConsumeToken();
746 continue;
747 }
748 }
749 ParseStructDeclaration(interfaceDecl, IvarDecls);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000750 for (unsigned i = 0; i < IvarDecls.size(); i++) {
751 AllIvarDecls.push_back(IvarDecls[i]);
752 AllVisibilities.push_back(visibility);
753 }
Steve Naroff3536b442007-09-06 21:24:23 +0000754 IvarDecls.clear();
755
Steve Naroffddbff782007-08-21 21:17:12 +0000756 if (Tok.getKind() == tok::semi) {
757 ConsumeToken();
758 } else if (Tok.getKind() == tok::r_brace) {
759 Diag(Tok.getLocation(), diag::ext_expected_semi_decl_list);
760 break;
761 } else {
762 Diag(Tok, diag::err_expected_semi_decl_list);
763 // Skip to end of block or statement
764 SkipUntil(tok::r_brace, true, true);
765 }
766 }
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000767 if (AllIvarDecls.size()) { // Check for {} - no ivars in braces
Steve Naroff08d92e42007-09-15 18:49:24 +0000768 Actions.ActOnFields(LBraceLoc, interfaceDecl,
769 &AllIvarDecls[0], AllIvarDecls.size(),
770 &AllVisibilities[0]);
Fariborz Jahanian7d6402f2007-09-13 20:56:13 +0000771 }
Steve Naroffddbff782007-08-21 21:17:12 +0000772 MatchRHSPunctuation(tok::r_brace, LBraceLoc);
773 return;
Reid Spencer5f016e22007-07-11 17:01:13 +0000774}
Steve Naroffdac269b2007-08-20 21:31:48 +0000775
776/// objc-protocol-declaration:
777/// objc-protocol-definition
778/// objc-protocol-forward-reference
779///
780/// objc-protocol-definition:
781/// @protocol identifier
782/// objc-protocol-refs[opt]
Steve Naroff3536b442007-09-06 21:24:23 +0000783/// objc-interface-decl-list
Steve Naroffdac269b2007-08-20 21:31:48 +0000784/// @end
785///
786/// objc-protocol-forward-reference:
787/// @protocol identifier-list ';'
788///
789/// "@protocol identifier ;" should be resolved as "@protocol
Steve Naroff3536b442007-09-06 21:24:23 +0000790/// identifier-list ;": objc-interface-decl-list may not start with a
Steve Naroffdac269b2007-08-20 21:31:48 +0000791/// semicolon in the first alternative if objc-protocol-refs are omitted.
792
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000793Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
Steve Naroff861cf3e2007-08-23 18:16:40 +0000794 assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000795 "ParseObjCAtProtocolDeclaration(): Expected @protocol");
796 ConsumeToken(); // the "protocol" identifier
797
798 if (Tok.getKind() != tok::identifier) {
799 Diag(Tok, diag::err_expected_ident); // missing protocol name.
800 return 0;
801 }
802 // Save the protocol name, then consume it.
803 IdentifierInfo *protocolName = Tok.getIdentifierInfo();
804 SourceLocation nameLoc = ConsumeToken();
805
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000806 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
807 if (Tok.getKind() == tok::semi) { // forward declaration of one protocol.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000808 ConsumeToken();
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000809 ProtocolRefs.push_back(protocolName);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000810 }
811 if (Tok.getKind() == tok::comma) { // list of forward declarations.
812 // Parse the list of forward declarations.
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000813 ProtocolRefs.push_back(protocolName);
814
815 while (1) {
816 ConsumeToken(); // the ','
817 if (Tok.getKind() != tok::identifier) {
818 Diag(Tok, diag::err_expected_ident);
819 SkipUntil(tok::semi);
820 return 0;
821 }
822 ProtocolRefs.push_back(Tok.getIdentifierInfo());
823 ConsumeToken(); // the identifier
824
825 if (Tok.getKind() != tok::comma)
826 break;
827 }
828 // Consume the ';'.
829 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
830 return 0;
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000831 }
Fariborz Jahanian894c57f2007-09-21 15:40:54 +0000832 if (ProtocolRefs.size() > 0)
833 return Actions.ObjcForwardProtocolDeclaration(CurScope, AtLoc,
834 &ProtocolRefs[0],
835 ProtocolRefs.size());
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000836 // Last, and definitely not least, parse a protocol declaration.
837 if (Tok.getKind() == tok::less) {
Steve Narofff28b2642007-09-05 23:30:30 +0000838 if (ParseObjCProtocolReferences(ProtocolRefs))
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000839 return 0;
840 }
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000841
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000842 DeclTy *ProtoType = Actions.ObjcStartProtoInterface(CurScope, AtLoc,
Fariborz Jahanian25e077d2007-09-17 21:07:36 +0000843 protocolName, nameLoc,
844 &ProtocolRefs[0],
845 ProtocolRefs.size());
846 ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000847
848 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
Steve Naroff861cf3e2007-08-23 18:16:40 +0000849 if (Tok.isObjCAtKeyword(tok::objc_end)) {
Steve Naroff7ef58fd2007-08-22 22:17:26 +0000850 ConsumeToken(); // the "end" identifier
851 return 0;
852 }
853 Diag(Tok, diag::err_objc_missing_end);
Steve Naroffdac269b2007-08-20 21:31:48 +0000854 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000855}
Steve Naroffdac269b2007-08-20 21:31:48 +0000856
857/// objc-implementation:
858/// objc-class-implementation-prologue
859/// objc-category-implementation-prologue
860///
861/// objc-class-implementation-prologue:
862/// @implementation identifier objc-superclass[opt]
863/// objc-class-instance-variables[opt]
864///
865/// objc-category-implementation-prologue:
866/// @implementation identifier ( identifier )
867
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000868Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
869 SourceLocation atLoc) {
870 assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
871 "ParseObjCAtImplementationDeclaration(): Expected @implementation");
872 ConsumeToken(); // the "implementation" identifier
873
874 if (Tok.getKind() != tok::identifier) {
875 Diag(Tok, diag::err_expected_ident); // missing class or category name.
876 return 0;
877 }
878 // We have a class or category name - consume it.
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000879 IdentifierInfo *nameId = Tok.getIdentifierInfo();
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000880 SourceLocation nameLoc = ConsumeToken(); // consume class or category name
881
882 if (Tok.getKind() == tok::l_paren) {
883 // we have a category implementation.
884 SourceLocation lparenLoc = ConsumeParen();
885 SourceLocation categoryLoc, rparenLoc;
886 IdentifierInfo *categoryId = 0;
887
888 if (Tok.getKind() == tok::identifier) {
889 categoryId = Tok.getIdentifierInfo();
890 categoryLoc = ConsumeToken();
891 } else {
892 Diag(Tok, diag::err_expected_ident); // missing category name.
893 return 0;
894 }
895 if (Tok.getKind() != tok::r_paren) {
896 Diag(Tok, diag::err_expected_rparen);
897 SkipUntil(tok::r_paren, false); // don't stop at ';'
898 return 0;
899 }
900 rparenLoc = ConsumeParen();
901 return 0;
902 }
903 // We have a class implementation
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000904 SourceLocation superClassLoc;
905 IdentifierInfo *superClassId = 0;
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000906 if (Tok.getKind() == tok::colon) {
907 // We have a super class
908 ConsumeToken();
909 if (Tok.getKind() != tok::identifier) {
910 Diag(Tok, diag::err_expected_ident); // missing super class name.
911 return 0;
912 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000913 superClassId = Tok.getIdentifierInfo();
914 superClassLoc = ConsumeToken(); // Consume super class name
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000915 }
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000916 DeclTy *ImplClsType = Actions.ObjcStartClassImplementation(CurScope,
917 atLoc,
918 nameId, nameLoc,
919 superClassId, superClassLoc);
920
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000921 if (Tok.getKind() == tok::l_brace)
Fariborz Jahanianccb4f312007-09-25 18:38:09 +0000922 ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/); // we have ivars
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000923
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000924 return ImplClsType;
Reid Spencer5f016e22007-07-11 17:01:13 +0000925}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000926Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
927 assert(Tok.isObjCAtKeyword(tok::objc_end) &&
928 "ParseObjCAtEndDeclaration(): Expected @end");
929 ConsumeToken(); // the "end" identifier
Fariborz Jahaniand0b01542007-09-27 18:57:03 +0000930 if (ObjcImpDecl) {
931 // Checking is not necessary except that a parse error might have caused
932 // @implementation not to have been parsed to completion and ObjcImpDecl
933 // could be 0.
934 /// Insert collected methods declarations into the @interface object.
935 Actions.ObjcAddMethodsToClass(ObjcImpDecl,
936 &AllImplMethods[0],AllImplMethods.size());
937 ObjcImpDecl = 0;
938 AllImplMethods.clear();
939 }
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000940
Steve Naroffdac269b2007-08-20 21:31:48 +0000941 return 0;
942}
Fariborz Jahaniane992af02007-09-04 19:26:51 +0000943
944/// compatibility-alias-decl:
945/// @compatibility_alias alias-name class-name ';'
946///
947Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
948 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
949 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
950 ConsumeToken(); // consume compatibility_alias
951 if (Tok.getKind() != tok::identifier) {
952 Diag(Tok, diag::err_expected_ident);
953 return 0;
954 }
955 ConsumeToken(); // consume alias-name
956 if (Tok.getKind() != tok::identifier) {
957 Diag(Tok, diag::err_expected_ident);
958 return 0;
959 }
960 ConsumeToken(); // consume class-name;
961 if (Tok.getKind() != tok::semi)
Fariborz Jahanian8cd8c662007-09-04 21:42:12 +0000962 Diag(Tok, diag::err_expected_semi_after, "@compatibility_alias");
Steve Naroffdac269b2007-08-20 21:31:48 +0000963 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000964}
965
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +0000966/// property-synthesis:
967/// @synthesize property-ivar-list ';'
968///
969/// property-ivar-list:
970/// property-ivar
971/// property-ivar-list ',' property-ivar
972///
973/// property-ivar:
974/// identifier
975/// identifier '=' identifier
976///
977Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
978 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
979 "ParseObjCPropertyDynamic(): Expected '@synthesize'");
980 SourceLocation loc = ConsumeToken(); // consume dynamic
981 if (Tok.getKind() != tok::identifier) {
982 Diag(Tok, diag::err_expected_ident);
983 return 0;
984 }
985 while (Tok.getKind() == tok::identifier) {
986 ConsumeToken(); // consume property name
987 if (Tok.getKind() == tok::equal) {
988 // property '=' ivar-name
989 ConsumeToken(); // consume '='
990 if (Tok.getKind() != tok::identifier) {
991 Diag(Tok, diag::err_expected_ident);
992 break;
993 }
994 ConsumeToken(); // consume ivar-name
995 }
996 if (Tok.getKind() != tok::comma)
997 break;
998 ConsumeToken(); // consume ','
999 }
1000 if (Tok.getKind() != tok::semi)
1001 Diag(Tok, diag::err_expected_semi_after, "@synthesize");
1002 return 0;
Reid Spencer5f016e22007-07-11 17:01:13 +00001003}
1004
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001005/// property-dynamic:
1006/// @dynamic property-list
1007///
1008/// property-list:
1009/// identifier
1010/// property-list ',' identifier
1011///
1012Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1013 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1014 "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1015 SourceLocation loc = ConsumeToken(); // consume dynamic
1016 if (Tok.getKind() != tok::identifier) {
1017 Diag(Tok, diag::err_expected_ident);
1018 return 0;
1019 }
1020 while (Tok.getKind() == tok::identifier) {
1021 ConsumeToken(); // consume property name
1022 if (Tok.getKind() != tok::comma)
1023 break;
1024 ConsumeToken(); // consume ','
1025 }
1026 if (Tok.getKind() != tok::semi)
1027 Diag(Tok, diag::err_expected_semi_after, "@dynamic");
1028 return 0;
1029}
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001030
1031/// objc-throw-statement:
1032/// throw expression[opt];
1033///
1034Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation &atLoc) {
1035 ConsumeToken(); // consume throw
1036 if (Tok.getKind() != tok::semi) {
1037 ExprResult Res = ParseAssignmentExpression();
1038 if (Res.isInvalid) {
1039 SkipUntil(tok::semi);
1040 return 0;
1041 }
1042 }
1043 return 0;
1044}
1045
1046/// objc-try-catch-statement:
1047/// @try compound-statement objc-catch-list[opt]
1048/// @try compound-statement objc-catch-list[opt] @finally compound-statement
1049///
1050/// objc-catch-list:
1051/// @catch ( parameter-declaration ) compound-statement
1052/// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1053/// catch-parameter-declaration:
1054/// parameter-declaration
1055/// '...' [OBJC2]
1056///
1057Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation &atLoc) {
1058 bool catch_or_finally_seen = false;
1059 ConsumeToken(); // consume try
1060 if (Tok.getKind() != tok::l_brace) {
1061 Diag (Tok, diag::err_expected_lbrace);
1062 return 0;
1063 }
1064 StmtResult TryBody = ParseCompoundStatementBody();
1065 while (Tok.getKind() == tok::at) {
1066 ConsumeToken();
1067 if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_catch) {
1068 SourceLocation catchLoc = ConsumeToken(); // consume catch
1069 if (Tok.getKind() == tok::l_paren) {
1070 ConsumeParen();
1071 if (Tok.getKind() != tok::ellipsis) {
1072 DeclSpec DS;
1073 ParseDeclarationSpecifiers(DS);
1074 // Parse the parameter-declaration.
1075 // FIXME: BlockContext may not be the right context!
1076 Declarator ParmDecl(DS, Declarator::BlockContext);
1077 ParseDeclarator(ParmDecl);
1078 }
1079 else
1080 ConsumeToken(); // consume '...'
1081 ConsumeParen();
1082 StmtResult CatchMody = ParseCompoundStatementBody();
1083 }
1084 else {
1085 Diag(catchLoc, diag::err_expected_lparen_after, "@catch clause");
1086 return 0;
1087 }
1088 catch_or_finally_seen = true;
1089 }
1090 else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_finally) {
1091 ConsumeToken(); // consume finally
1092 StmtResult FinallyBody = ParseCompoundStatementBody();
1093 catch_or_finally_seen = true;
1094 break;
1095 }
1096 }
1097 if (!catch_or_finally_seen)
1098 Diag(atLoc, diag::err_missing_catch_finally);
1099 return 0;
1100}
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001101
Steve Naroff3536b442007-09-06 21:24:23 +00001102/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001103///
1104void Parser::ParseObjCInstanceMethodDefinition() {
1105 assert(Tok.getKind() == tok::minus &&
1106 "ParseObjCInstanceMethodDefinition(): Expected '-'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001107 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001108 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001109 // parse optional ';'
1110 if (Tok.getKind() == tok::semi)
1111 ConsumeToken();
1112
1113 if (Tok.getKind() != tok::l_brace) {
1114 Diag (Tok, diag::err_expected_lbrace);
1115 return;
1116 }
1117
1118 StmtResult FnBody = ParseCompoundStatementBody();
1119}
1120
Steve Naroff3536b442007-09-06 21:24:23 +00001121/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001122///
Steve Naroff7ef58fd2007-08-22 22:17:26 +00001123void Parser::ParseObjCClassMethodDefinition() {
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001124 assert(Tok.getKind() == tok::plus &&
1125 "ParseObjCClassMethodDefinition(): Expected '+'");
Fariborz Jahanian25e077d2007-09-17 21:07:36 +00001126 // FIXME: @optional/@protocol??
Fariborz Jahaniand0b01542007-09-27 18:57:03 +00001127 AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
Fariborz Jahanianac00b7f2007-09-01 00:26:16 +00001128 // parse optional ';'
1129 if (Tok.getKind() == tok::semi)
1130 ConsumeToken();
1131 if (Tok.getKind() != tok::l_brace) {
1132 Diag (Tok, diag::err_expected_lbrace);
1133 return;
1134 }
1135
1136 StmtResult FnBody = ParseCompoundStatementBody();
Reid Spencer5f016e22007-07-11 17:01:13 +00001137}
Anders Carlsson55085182007-08-21 17:43:55 +00001138
Fariborz Jahanian397fcc12007-09-19 19:14:32 +00001139Parser::ExprResult Parser::ParseObjCExpression(SourceLocation &AtLoc) {
Anders Carlsson55085182007-08-21 17:43:55 +00001140
1141 switch (Tok.getKind()) {
1142 case tok::string_literal: // primary-expression: string-literal
1143 case tok::wide_string_literal:
1144 return ParseObjCStringLiteral();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001145 default:
1146 break;
1147 }
1148
1149 switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001150 case tok::objc_encode:
1151 return ParseObjCEncodeExpression();
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001152 case tok::objc_protocol:
1153 return ParseObjCProtocolExpression();
Anders Carlsson55085182007-08-21 17:43:55 +00001154 default:
1155 Diag(AtLoc, diag::err_unexpected_at);
1156 SkipUntil(tok::semi);
1157 break;
1158 }
1159
1160 return 0;
1161}
1162
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001163/// objc-message-expr:
1164/// '[' objc-receiver objc-message-args ']'
1165///
1166/// objc-receiver:
1167/// expression
1168/// class-name
1169/// type-name
1170///
1171/// objc-message-args:
1172/// objc-selector
1173/// objc-keywordarg-list
1174///
1175/// objc-keywordarg-list:
1176/// objc-keywordarg
1177/// objc-keywordarg-list objc-keywordarg
1178///
1179/// objc-keywordarg:
1180/// selector-name[opt] ':' objc-keywordexpr
1181///
1182/// objc-keywordexpr:
1183/// nonempty-expr-list
1184///
1185/// nonempty-expr-list:
1186/// assignment-expression
1187/// nonempty-expr-list , assignment-expression
1188///
1189Parser::ExprResult Parser::ParseObjCMessageExpression() {
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001190 assert(Tok.getKind() == tok::l_square && "'[' expected");
Steve Naroff563477d2007-09-18 23:55:05 +00001191 SourceLocation LBracloc = ConsumeBracket(); // consume '['
Steve Naroff37387c92007-09-17 20:25:27 +00001192 IdentifierInfo *ReceiverName = 0;
1193 ExprTy *ReceiverExpr = 0;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001194 // Parse receiver
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001195 if (Tok.getKind() == tok::identifier &&
Steve Naroff37387c92007-09-17 20:25:27 +00001196 Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
1197 ReceiverName = Tok.getIdentifierInfo();
Steve Naroff8c9f13e2007-09-16 16:16:00 +00001198 ConsumeToken();
Steve Naroff37387c92007-09-17 20:25:27 +00001199 } else {
1200 ExprResult Res = ParseAssignmentExpression();
1201 if (Res.isInvalid) {
1202 SkipUntil(tok::identifier);
1203 return Res;
1204 }
1205 ReceiverExpr = Res.Val;
1206 }
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001207 // Parse objc-selector
1208 IdentifierInfo *selIdent = ParseObjCSelector();
Steve Naroff68d331a2007-09-27 14:38:14 +00001209
1210 llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
1211 llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
1212
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001213 if (Tok.getKind() == tok::colon) {
1214 while (1) {
1215 // Each iteration parses a single keyword argument.
Steve Naroff68d331a2007-09-27 14:38:14 +00001216 KeyIdents.push_back(selIdent);
Steve Naroff37387c92007-09-17 20:25:27 +00001217
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001218 if (Tok.getKind() != tok::colon) {
1219 Diag(Tok, diag::err_expected_colon);
1220 SkipUntil(tok::semi);
Steve Naroff37387c92007-09-17 20:25:27 +00001221 return true;
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001222 }
Steve Naroff68d331a2007-09-27 14:38:14 +00001223 ConsumeToken(); // Eat the ':'.
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001224 /// Parse the expression after ':'
Steve Naroff37387c92007-09-17 20:25:27 +00001225 ExprResult Res = ParseAssignmentExpression();
1226 if (Res.isInvalid) {
1227 SkipUntil(tok::identifier);
1228 return Res;
1229 }
1230 // We have a valid expression.
Steve Naroff68d331a2007-09-27 14:38:14 +00001231 KeyExprs.push_back(Res.Val);
Steve Naroff37387c92007-09-17 20:25:27 +00001232
1233 // Check for another keyword selector.
1234 selIdent = ParseObjCSelector();
1235 if (!selIdent && Tok.getKind() != tok::colon)
Fariborz Jahaniana65ff6c2007-09-05 23:08:20 +00001236 break;
1237 // We have a selector or a colon, continue parsing.
1238 }
1239 // Parse the, optional, argument list, comma separated.
1240 while (Tok.getKind() == tok::comma) {
1241 ConsumeToken();
1242 /// Parse the expression after ','
1243 ParseAssignmentExpression();
1244 }
1245 } else if (!selIdent) {
1246 Diag(Tok, diag::err_expected_ident); // missing selector name.
1247 SkipUntil(tok::semi);
1248 return 0;
1249 }
1250 if (Tok.getKind() != tok::r_square) {
1251 Diag(Tok, diag::err_expected_rsquare);
1252 SkipUntil(tok::semi);
1253 return 0;
1254 }
Steve Naroff563477d2007-09-18 23:55:05 +00001255 SourceLocation RBracloc = ConsumeBracket(); // consume ']'
Steve Naroff37387c92007-09-17 20:25:27 +00001256
Steve Naroff68d331a2007-09-27 14:38:14 +00001257 if (KeyIdents.size()) {
1258 SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents,
1259 PP.getSelectorTable());
Steve Naroff708391a2007-09-17 21:01:15 +00001260 // We've just parsed a keyword message.
1261 if (ReceiverName)
Steve Naroff68d331a2007-09-27 14:38:14 +00001262 return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc,
1263 &KeyExprs[0]);
1264 return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc,
1265 &KeyExprs[0]);
Steve Naroff708391a2007-09-17 21:01:15 +00001266 }
Steve Naroff68d331a2007-09-27 14:38:14 +00001267 SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable());
1268
Steve Naroff708391a2007-09-17 21:01:15 +00001269 // We've just parsed a unary message (a message with no arguments).
Steve Naroff37387c92007-09-17 20:25:27 +00001270 if (ReceiverName)
Steve Naroff68d331a2007-09-27 14:38:14 +00001271 return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc, 0);
1272 return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc, 0);
Fariborz Jahanian0ccb27d2007-09-05 19:52:07 +00001273}
1274
Anders Carlsson55085182007-08-21 17:43:55 +00001275Parser::ExprResult Parser::ParseObjCStringLiteral() {
1276 ExprResult Res = ParseStringLiteralExpression();
1277
1278 if (Res.isInvalid) return Res;
1279
1280 return Actions.ParseObjCStringLiteral(Res.Val);
1281}
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001282
1283/// objc-encode-expression:
1284/// @encode ( type-name )
1285Parser::ExprResult Parser::ParseObjCEncodeExpression() {
Steve Naroff861cf3e2007-08-23 18:16:40 +00001286 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001287
1288 SourceLocation EncLoc = ConsumeToken();
1289
1290 if (Tok.getKind() != tok::l_paren) {
1291 Diag(Tok, diag::err_expected_lparen_after, "@encode");
1292 return true;
1293 }
1294
1295 SourceLocation LParenLoc = ConsumeParen();
1296
1297 TypeTy *Ty = ParseTypeName();
1298
Anders Carlsson4988ae32007-08-23 15:31:37 +00001299 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001300
1301 return Actions.ParseObjCEncodeExpression(EncLoc, LParenLoc, Ty,
Anders Carlsson4988ae32007-08-23 15:31:37 +00001302 RParenLoc);
Anders Carlssonf9bcf012007-08-22 15:14:15 +00001303}
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001304
1305/// objc-protocol-expression
1306/// @protocol ( protocol-name )
1307
1308Parser::ExprResult Parser::ParseObjCProtocolExpression()
1309{
1310 SourceLocation ProtoLoc = ConsumeToken();
1311
1312 if (Tok.getKind() != tok::l_paren) {
1313 Diag(Tok, diag::err_expected_lparen_after, "@protocol");
1314 return true;
1315 }
1316
1317 SourceLocation LParenLoc = ConsumeParen();
1318
1319 if (Tok.getKind() != tok::identifier) {
1320 Diag(Tok, diag::err_expected_ident);
1321 return true;
1322 }
1323
1324 // FIXME: Do something with the protocol name
1325 ConsumeToken();
1326
Anders Carlsson4988ae32007-08-23 15:31:37 +00001327 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
Anders Carlsson29b2cb12007-08-23 15:25:28 +00001328
1329 // FIXME
1330 return 0;
1331}