blob: 0d31c22da7b878fb23046a63c0c1239f22e5db2c [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +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 Naroff09a0c4c2007-08-22 18:35:33 +000015#include "clang/Parse/DeclSpec.h"
Chris Lattner4b009652007-07-25 00:24:17 +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 Narofffb367882007-08-20 21:31:48 +000029Parser::DeclTy *Parser::ParseObjCAtDirectives() {
Chris Lattner4b009652007-07-25 00:24:17 +000030 SourceLocation AtLoc = ConsumeToken(); // the "@"
31
32 IdentifierInfo *II = Tok.getIdentifierInfo();
33 switch (II ? II->getObjCKeywordID() : tok::objc_not_keyword) {
34 case tok::objc_class:
35 return ParseObjCAtClassDeclaration(AtLoc);
36 case tok::objc_interface:
Steve Narofffb367882007-08-20 21:31:48 +000037 return ParseObjCAtInterfaceDeclaration(AtLoc);
Chris Lattner4b009652007-07-25 00:24:17 +000038 case tok::objc_protocol:
39 return ParseObjCAtProtocolDeclaration();
40 case tok::objc_implementation:
41 return ParseObjCAtImplementationDeclaration();
42 case tok::objc_end:
43 return ParseObjCAtEndDeclaration();
44 case tok::objc_compatibility_alias:
45 return ParseObjCAtAliasDeclaration();
46 default:
47 Diag(AtLoc, diag::err_unexpected_at);
48 SkipUntil(tok::semi);
Steve Narofffb367882007-08-20 21:31:48 +000049 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000050 }
51}
52
53///
54/// objc-class-declaration:
55/// '@' 'class' identifier-list ';'
56///
Steve Narofffb367882007-08-20 21:31:48 +000057Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
Chris Lattner4b009652007-07-25 00:24:17 +000058 ConsumeToken(); // the identifier "class"
59 llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
60
61 while (1) {
62 if (Tok.getKind() != tok::identifier) {
63 Diag(Tok, diag::err_expected_ident);
64 SkipUntil(tok::semi);
Steve Narofffb367882007-08-20 21:31:48 +000065 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000066 }
67
68 ClassNames.push_back(Tok.getIdentifierInfo());
69 ConsumeToken();
70
71 if (Tok.getKind() != tok::comma)
72 break;
73
74 ConsumeToken();
75 }
76
77 // Consume the ';'.
78 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
Steve Narofffb367882007-08-20 21:31:48 +000079 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000080
Steve Narofffb367882007-08-20 21:31:48 +000081 return Actions.ParsedObjcClassDeclaration(CurScope,
82 &ClassNames[0], ClassNames.size());
Chris Lattner4b009652007-07-25 00:24:17 +000083}
84
Steve Narofffb367882007-08-20 21:31:48 +000085///
86/// objc-interface:
87/// objc-class-interface-attributes[opt] objc-class-interface
88/// objc-category-interface
89///
90/// objc-class-interface:
91/// '@' 'interface' identifier objc-superclass[opt]
92/// objc-protocol-refs[opt]
93/// objc-class-instance-variables[opt]
94/// objc-interface-decl-list
95/// @end
96///
97/// objc-category-interface:
98/// '@' 'interface' identifier '(' identifier[opt] ')'
99/// objc-protocol-refs[opt]
100/// objc-interface-decl-list
101/// @end
102///
103/// objc-superclass:
104/// ':' identifier
105///
106/// objc-class-interface-attributes:
107/// __attribute__((visibility("default")))
108/// __attribute__((visibility("hidden")))
109/// __attribute__((deprecated))
110/// __attribute__((unavailable))
111/// __attribute__((objc_exception)) - used by NSException on 64-bit
112///
113Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
114 SourceLocation atLoc, AttributeList *attrList) {
115 assert(Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface &&
116 "ParseObjCAtInterfaceDeclaration(): Expected @interface");
117 ConsumeToken(); // the "interface" identifier
118
119 if (Tok.getKind() != tok::identifier) {
120 Diag(Tok, diag::err_expected_ident); // missing class or category name.
121 return 0;
122 }
123 // We have a class or category name - consume it.
Steve Naroff0bbffd82007-08-22 16:35:03 +0000124 // IdentifierInfo *nameId = Tok.getIdentifierInfo();
Steve Narofffb367882007-08-20 21:31:48 +0000125 SourceLocation nameLoc = ConsumeToken();
126
127 if (Tok.getKind() == tok::l_paren) { // we have a category
128 SourceLocation lparenLoc = ConsumeParen();
129 SourceLocation categoryLoc, rparenLoc;
130 IdentifierInfo *categoryId = 0;
131
132 // OBJC2: The cateogry name is optional (not an error).
133 if (Tok.getKind() == tok::identifier) {
134 categoryId = Tok.getIdentifierInfo();
135 categoryLoc = ConsumeToken();
136 }
137 if (Tok.getKind() != tok::r_paren) {
138 Diag(Tok, diag::err_expected_rparen);
139 SkipUntil(tok::r_paren, false); // don't stop at ';'
140 return 0;
141 }
142 rparenLoc = ConsumeParen();
143 // Next, we need to check for any protocol references.
144 if (Tok.getKind() == tok::less) {
145 if (ParseObjCProtocolReferences())
146 return 0;
147 }
148 if (attrList) // categories don't support attributes.
149 Diag(Tok, diag::err_objc_no_attributes_on_category);
150
Steve Naroff0bbffd82007-08-22 16:35:03 +0000151 ParseObjCInterfaceDeclList(0/*FIXME*/);
Steve Narofffb367882007-08-20 21:31:48 +0000152
Steve Naroff0bbffd82007-08-22 16:35:03 +0000153 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
154 if (Tok.getKind() == tok::identifier &&
155 Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
156 ConsumeToken(); // the "end" identifier
Steve Narofffb367882007-08-20 21:31:48 +0000157 return 0;
158 }
Steve Naroff0bbffd82007-08-22 16:35:03 +0000159 Diag(Tok, diag::err_objc_missing_end);
Steve Narofffb367882007-08-20 21:31:48 +0000160 return 0;
161 }
162 // Parse a class interface.
163 IdentifierInfo *superClassId = 0;
164 SourceLocation superClassLoc;
165
166 if (Tok.getKind() == tok::colon) { // a super class is specified.
167 ConsumeToken();
168 if (Tok.getKind() != tok::identifier) {
169 Diag(Tok, diag::err_expected_ident); // missing super class name.
170 return 0;
171 }
172 superClassId = Tok.getIdentifierInfo();
173 superClassLoc = ConsumeToken();
174 }
175 // Next, we need to check for any protocol references.
176 if (Tok.getKind() == tok::less) {
177 if (ParseObjCProtocolReferences())
178 return 0;
179 }
Steve Naroffc4474992007-08-21 21:17:12 +0000180 // FIXME: add Actions.StartObjCClassInterface(nameId, superClassId, ...)
Steve Narofffb367882007-08-20 21:31:48 +0000181 if (Tok.getKind() == tok::l_brace)
Steve Naroffc4474992007-08-21 21:17:12 +0000182 ParseObjCClassInstanceVariables(0/*FIXME*/);
Steve Narofffb367882007-08-20 21:31:48 +0000183
Steve Naroff0bbffd82007-08-22 16:35:03 +0000184 ParseObjCInterfaceDeclList(0/*FIXME*/);
185
186 // The @ sign was already consumed by ParseObjCInterfaceDeclList().
187 if (Tok.getKind() == tok::identifier &&
188 Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
189 ConsumeToken(); // the "end" identifier
Steve Narofffb367882007-08-20 21:31:48 +0000190 return 0;
191 }
Steve Naroff0bbffd82007-08-22 16:35:03 +0000192 Diag(Tok, diag::err_objc_missing_end);
Steve Narofffb367882007-08-20 21:31:48 +0000193 return 0;
194}
195
196/// objc-interface-decl-list:
197/// empty
Steve Narofffb367882007-08-20 21:31:48 +0000198/// objc-interface-decl-list objc-property-decl [OBJC2]
Steve Naroff0bbffd82007-08-22 16:35:03 +0000199/// objc-interface-decl-list objc-method-requirement [OBJC2]
200/// objc-interface-decl-list objc-method-proto
Steve Narofffb367882007-08-20 21:31:48 +0000201/// objc-interface-decl-list declaration
202/// objc-interface-decl-list ';'
203///
Steve Naroff0bbffd82007-08-22 16:35:03 +0000204/// objc-method-requirement: [OBJC2]
205/// @required
206/// @optional
207///
208void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
209 while (1) {
210 if (Tok.getKind() == tok::at) {
211 SourceLocation AtLoc = ConsumeToken(); // the "@"
212 tok::ObjCKeywordKind ocKind = Tok.getIdentifierInfo()->getObjCKeywordID();
213
214 if (ocKind == tok::objc_end) { // terminate list
215 return;
216 } else if (ocKind == tok::objc_required) { // protocols only
217 ConsumeToken();
218 continue;
219 } else if (ocKind == tok::objc_optional) { // protocols only
220 ConsumeToken();
221 continue;
222 } else if (ocKind == tok::objc_property) {
223 ParseObjCPropertyDecl(AtLoc);
224 continue;
225 } else {
226 Diag(Tok, diag::err_objc_illegal_interface_qual);
227 ConsumeToken();
228 }
229 }
230 if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
231 ParseObjCMethodPrototype();
232 continue;
233 }
234 if (Tok.getKind() == tok::semi)
235 ConsumeToken();
236 else if (Tok.getKind() == tok::eof)
237 return;
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000238 else
239 // FIXME: as the name implies, this rule allows function definitions.
240 // We could pass a flag or check for functions during semantic analysis.
Steve Naroff0bbffd82007-08-22 16:35:03 +0000241 ParseDeclarationOrFunctionDefinition();
242 }
243}
244
245void Parser::ParseObjCPropertyDecl(SourceLocation atLoc) {
Chris Lattner4b009652007-07-25 00:24:17 +0000246 assert(0 && "Unimp");
247}
Steve Narofffb367882007-08-20 21:31:48 +0000248
Steve Naroff0bbffd82007-08-22 16:35:03 +0000249/// objc-methodproto:
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000250/// objc-instance-method objc-method-decl objc-method-attributes[opt] ';'
251/// objc-class-method objc-method-decl objc-method-attributes[opt] ';'
Steve Naroff0bbffd82007-08-22 16:35:03 +0000252///
253/// objc-instance-method: '-'
254/// objc-class-method: '+'
255///
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000256/// objc-method-attributes: [OBJC2]
257/// __attribute__((deprecated))
258///
Steve Naroff0bbffd82007-08-22 16:35:03 +0000259void Parser::ParseObjCMethodPrototype() {
260 assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
261 "expected +/-");
262
263 tok::TokenKind methodType = Tok.getKind();
264 SourceLocation methodLoc = ConsumeToken();
265
266 // FIXME: deal with "context sensitive" protocol qualifiers in prototypes
267 ParseObjCMethodDecl(methodType, methodLoc);
268
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000269 // If attributes exist after the method, parse them.
270 if (Tok.getKind() == tok::kw___attribute)
271 ParseAttributes();
272
Steve Naroff0bbffd82007-08-22 16:35:03 +0000273 // Consume the ';'.
274 ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
275}
276
277/// objc-selector:
278/// identifier
279/// one of
280/// enum struct union if else while do for switch case default
281/// break continue return goto asm sizeof typeof __alignof
282/// unsigned long const short volatile signed restrict _Complex
283/// in out inout bycopy byref oneway int char float double void _Bool
284///
285IdentifierInfo *Parser::ParseObjCSelector() {
286 tok::TokenKind tKind = Tok.getKind();
287 IdentifierInfo *II = 0;
288
289 if (tKind == tok::identifier ||
290 (tKind >= tok::kw_auto && tKind <= tok::kw__Complex)) {
291 // FIXME: make sure the list of keywords jives with gcc. For example,
292 // the above test does not include in/out/inout/bycopy/byref/oneway.
293 II = Tok.getIdentifierInfo();
294 ConsumeToken();
295 }
296 return II;
297}
298
299/// objc-type-name:
300/// '(' objc-type-qualifiers[opt] type-name ')'
301/// '(' objc-type-qualifiers[opt] ')'
302///
303/// objc-type-qualifiers:
304/// objc-type-qualifier
305/// objc-type-qualifiers objc-type-qualifier
306///
307/// objc-type-qualifier: one of
308/// in out inout bycopy byref oneway
309///
310void Parser::ParseObjCTypeName() {
311 assert(Tok.getKind() == tok::l_paren && "expected (");
312
313 SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
314
315 if (isTypeSpecifierQualifier()) {
316 TypeTy *Ty = ParseTypeName();
317
318 assert(Ty && "Parser::ParseObjCTypeName(): missing type");
319 }
320 if (Tok.getKind() != tok::r_paren) {
321 MatchRHSPunctuation(tok::r_paren, LParenLoc);
322 return;
323 }
324 RParenLoc = ConsumeParen();
325}
326
327/// objc-method-decl:
328/// objc-selector
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000329/// objc-keyword-selector objc-parmlist[opt]
Steve Naroff0bbffd82007-08-22 16:35:03 +0000330/// objc-type-name objc-selector
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000331/// objc-type-name objc-keyword-selector objc-parmlist[opt]
Steve Naroff0bbffd82007-08-22 16:35:03 +0000332///
333/// objc-keyword-selector:
334/// objc-keyword-decl
335/// objc-keyword-selector objc-keyword-decl
336///
337/// objc-keyword-decl:
338/// objc-selector ':' objc-type-name identifier
339/// objc-selector ':' identifier
340/// ':' objc-type-name identifier
341/// ':' identifier
342///
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000343/// objc-parmlist:
344/// objc-parms objc-ellipsis[opt]
Steve Naroff0bbffd82007-08-22 16:35:03 +0000345///
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000346/// objc-parms:
347/// objc-parms , parameter-declaration
Steve Naroff0bbffd82007-08-22 16:35:03 +0000348///
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000349/// objc-ellipsis:
Steve Naroff0bbffd82007-08-22 16:35:03 +0000350/// , ...
351///
352void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000353
354 // Parse the return type.
Steve Naroff0bbffd82007-08-22 16:35:03 +0000355 if (Tok.getKind() == tok::l_paren)
356 ParseObjCTypeName();
Steve Naroff09a0c4c2007-08-22 18:35:33 +0000357 IdentifierInfo *selIdent = ParseObjCSelector();
358
359 if (Tok.getKind() == tok::colon) {
360 IdentifierInfo *keywordSelector = selIdent;
361 while (1) {
362 // Each iteration parses a single keyword argument.
363 if (Tok.getKind() != tok::colon) {
364 Diag(Tok, diag::err_expected_colon);
365 break;
366 }
367 ConsumeToken(); // Eat the ':'.
368 if (Tok.getKind() == tok::l_paren) // Parse the argument type.
369 ParseObjCTypeName();
370 if (Tok.getKind() != tok::identifier) {
371 Diag(Tok, diag::err_expected_ident); // missing argument name.
372 break;
373 }
374 ConsumeToken(); // Eat the identifier.
375 // FIXME: add Actions.BuildObjCKeyword()
376
377 keywordSelector = ParseObjCSelector();
378 if (!keywordSelector && Tok.getKind() != tok::colon)
379 break;
380 // We have a selector or a colon, continue parsing.
381 }
382 // Parse the (optional) parameter list.
383 while (Tok.getKind() == tok::comma) {
384 ConsumeToken();
385 if (Tok.getKind() == tok::ellipsis) {
386 ConsumeToken();
387 break;
388 }
389 ParseDeclaration(Declarator::PrototypeContext);
390 }
391 } else if (!selIdent) {
392 Diag(Tok, diag::err_expected_ident); // missing selector name.
393 }
394 // FIXME: add Actions.BuildMethodSignature().
Steve Naroff0bbffd82007-08-22 16:35:03 +0000395}
396
Steve Narofffb367882007-08-20 21:31:48 +0000397/// objc-protocol-refs:
398/// '<' identifier-list '>'
399///
400bool Parser::ParseObjCProtocolReferences() {
401 assert(Tok.getKind() == tok::less && "expected <");
402
403 ConsumeToken(); // the "<"
404 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
405
406 while (1) {
407 if (Tok.getKind() != tok::identifier) {
408 Diag(Tok, diag::err_expected_ident);
409 SkipUntil(tok::greater);
410 return true;
411 }
412 ProtocolRefs.push_back(Tok.getIdentifierInfo());
413 ConsumeToken();
414
415 if (Tok.getKind() != tok::comma)
416 break;
417 ConsumeToken();
418 }
419 // Consume the '>'.
420 return ExpectAndConsume(tok::greater, diag::err_expected_greater);
421}
422
423/// objc-class-instance-variables:
424/// '{' objc-instance-variable-decl-list[opt] '}'
425///
426/// objc-instance-variable-decl-list:
427/// objc-visibility-spec
428/// objc-instance-variable-decl ';'
429/// ';'
430/// objc-instance-variable-decl-list objc-visibility-spec
431/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
432/// objc-instance-variable-decl-list ';'
433///
434/// objc-visibility-spec:
435/// @private
436/// @protected
437/// @public
Steve Naroffc4474992007-08-21 21:17:12 +0000438/// @package [OBJC2]
Steve Narofffb367882007-08-20 21:31:48 +0000439///
440/// objc-instance-variable-decl:
441/// struct-declaration
442///
Steve Naroffc4474992007-08-21 21:17:12 +0000443void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
444 assert(Tok.getKind() == tok::l_brace && "expected {");
445
446 SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
447 llvm::SmallVector<DeclTy*, 32> IvarDecls;
448
449 // While we still have something to read, read the instance variables.
450 while (Tok.getKind() != tok::r_brace &&
451 Tok.getKind() != tok::eof) {
452 // Each iteration of this loop reads one objc-instance-variable-decl.
453
454 // Check for extraneous top-level semicolon.
455 if (Tok.getKind() == tok::semi) {
456 Diag(Tok, diag::ext_extra_struct_semi);
457 ConsumeToken();
458 continue;
459 }
460 // Set the default visibility to private.
461 tok::ObjCKeywordKind visibility = tok::objc_private;
462 if (Tok.getKind() == tok::at) { // parse objc-visibility-spec
463 ConsumeToken(); // eat the @ sign
464 IdentifierInfo *specId = Tok.getIdentifierInfo();
465 switch (specId->getObjCKeywordID()) {
466 case tok::objc_private:
467 case tok::objc_public:
468 case tok::objc_protected:
469 case tok::objc_package:
470 visibility = specId->getObjCKeywordID();
471 ConsumeToken();
472 continue;
473 default:
474 Diag(Tok, diag::err_objc_illegal_visibility_spec);
475 ConsumeToken();
476 continue;
477 }
478 }
479 ParseStructDeclaration(interfaceDecl, IvarDecls);
480
481 if (Tok.getKind() == tok::semi) {
482 ConsumeToken();
483 } else if (Tok.getKind() == tok::r_brace) {
484 Diag(Tok.getLocation(), diag::ext_expected_semi_decl_list);
485 break;
486 } else {
487 Diag(Tok, diag::err_expected_semi_decl_list);
488 // Skip to end of block or statement
489 SkipUntil(tok::r_brace, true, true);
490 }
491 }
492 MatchRHSPunctuation(tok::r_brace, LBraceLoc);
493 return;
Chris Lattner4b009652007-07-25 00:24:17 +0000494}
Steve Narofffb367882007-08-20 21:31:48 +0000495
496/// objc-protocol-declaration:
497/// objc-protocol-definition
498/// objc-protocol-forward-reference
499///
500/// objc-protocol-definition:
501/// @protocol identifier
502/// objc-protocol-refs[opt]
503/// objc-methodprotolist
504/// @end
505///
506/// objc-protocol-forward-reference:
507/// @protocol identifier-list ';'
508///
509/// "@protocol identifier ;" should be resolved as "@protocol
510/// identifier-list ;": objc-methodprotolist may not start with a
511/// semicolon in the first alternative if objc-protocol-refs are omitted.
512
513Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000514 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000515 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000516}
Steve Narofffb367882007-08-20 21:31:48 +0000517
518/// objc-implementation:
519/// objc-class-implementation-prologue
520/// objc-category-implementation-prologue
521///
522/// objc-class-implementation-prologue:
523/// @implementation identifier objc-superclass[opt]
524/// objc-class-instance-variables[opt]
525///
526/// objc-category-implementation-prologue:
527/// @implementation identifier ( identifier )
528
529Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000530 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000531 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000532}
Steve Narofffb367882007-08-20 21:31:48 +0000533Parser::DeclTy *Parser::ParseObjCAtEndDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000534 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000535 return 0;
536}
537Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
538 assert(0 && "Unimp");
539 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000540}
541
542void Parser::ParseObjCInstanceMethodDeclaration() {
543 assert(0 && "Unimp");
544}
545
546void Parser::ParseObjCClassMethodDeclaration() {
547 assert(0 && "Unimp");
548}
Anders Carlssona66cad42007-08-21 17:43:55 +0000549
550Parser::ExprResult Parser::ParseObjCExpression() {
551 SourceLocation AtLoc = ConsumeToken(); // the "@"
552
553 switch (Tok.getKind()) {
554 case tok::string_literal: // primary-expression: string-literal
555 case tok::wide_string_literal:
556 return ParseObjCStringLiteral();
Anders Carlsson8be1d402007-08-22 15:14:15 +0000557 case tok::objc_encode:
558 return ParseObjCEncodeExpression();
559 break;
Anders Carlssona66cad42007-08-21 17:43:55 +0000560 default:
561 Diag(AtLoc, diag::err_unexpected_at);
562 SkipUntil(tok::semi);
563 break;
564 }
565
566 return 0;
567}
568
569Parser::ExprResult Parser::ParseObjCStringLiteral() {
570 ExprResult Res = ParseStringLiteralExpression();
571
572 if (Res.isInvalid) return Res;
573
574 return Actions.ParseObjCStringLiteral(Res.Val);
575}
Anders Carlsson8be1d402007-08-22 15:14:15 +0000576
577/// objc-encode-expression:
578/// @encode ( type-name )
579Parser::ExprResult Parser::ParseObjCEncodeExpression() {
580 assert(Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_encode &&
581 "Not an @encode expression!");
582
583 SourceLocation EncLoc = ConsumeToken();
584
585 if (Tok.getKind() != tok::l_paren) {
586 Diag(Tok, diag::err_expected_lparen_after, "@encode");
587 return true;
588 }
589
590 SourceLocation LParenLoc = ConsumeParen();
591
592 TypeTy *Ty = ParseTypeName();
593
594 if (Tok.getKind() != tok::r_paren) {
595 Diag(Tok, diag::err_expected_rparen);
596 return true;
597 }
598
599 return Actions.ParseObjCEncodeExpression(EncLoc, LParenLoc, Ty,
600 ConsumeParen());
601}