blob: ea4cc19f16bb3e90537a6b4608219d8351832600 [file] [log] [blame]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +00001//===--- ParserDeclarations.cpp - Declaration Parsing ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner 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 Declaration portions of the Parser interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
Chris Lattnerb9093cd2006-08-04 04:39:53 +000015#include "clang/Parse/Declarations.h"
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000016using namespace llvm;
17using namespace clang;
18
19//===----------------------------------------------------------------------===//
20// C99 6.7: Declarations.
21//===----------------------------------------------------------------------===//
22
23/// ParseDeclarationSpecifiers
24/// declaration-specifiers: [C99 6.7]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000025/// storage-class-specifier declaration-specifiers [opt]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000026/// type-specifier declaration-specifiers [opt]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000027/// type-qualifier declaration-specifiers [opt]
28/// [C99] function-specifier declaration-specifiers [opt]
29/// [GNU] attributes declaration-specifiers [opt] [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000030///
Chris Lattnerf63f89a2006-08-05 03:28:50 +000031/// storage-class-specifier: [C99 6.7.1]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000032/// 'typedef'
33/// 'extern'
34/// 'static'
35/// 'auto'
36/// 'register'
37/// [GNU] '__thread'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000038/// type-specifier: [C99 6.7.2]
39/// 'void'
40/// 'char'
41/// 'short'
42/// 'int'
43/// 'long'
44/// 'float'
45/// 'double'
46/// 'signed'
47/// 'unsigned'
Chris Lattner8e90ef62006-08-05 03:30:45 +000048/// struct-or-union-specifier [TODO]
49/// enum-specifier [TODO]
50/// typedef-name [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000051/// [C99] '_Bool'
52/// [C99] '_Complex'
Chris Lattnerda48a8e2006-08-04 05:25:55 +000053/// [C99] '_Imaginary' // Removed in TC2?
54/// [GNU] '_Decimal32'
55/// [GNU] '_Decimal64'
56/// [GNU] '_Decimal128'
Chris Lattnerf63f89a2006-08-05 03:28:50 +000057/// [GNU] typeof-specifier [TODO]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000058/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
59/// [OBJC] typedef-name objc-protocol-refs [TODO]
60/// [OBJC] objc-protocol-refs [TODO]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000061/// type-qualifier:
62/// const
63/// volatile
64/// [C99] restrict
Chris Lattnerb9093cd2006-08-04 04:39:53 +000065/// function-specifier: [C99 6.7.4]
66/// [C99] inline
67///
68void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
69 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000070 while (1) {
Chris Lattnerda48a8e2006-08-04 05:25:55 +000071 int isInvalid = false;
Chris Lattnerb9093cd2006-08-04 04:39:53 +000072 const char *PrevSpec = 0;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000073 switch (Tok.getKind()) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +000074 default:
75 // If this is not a declaration specifier token, we're done reading decl
76 // specifiers. First verify that DeclSpec's are consistent.
Chris Lattner839713c2006-08-04 06:15:52 +000077 DS.Finish(StartLoc, Diags, getLang());
Chris Lattnerb9093cd2006-08-04 04:39:53 +000078 return;
Chris Lattnerf63f89a2006-08-05 03:28:50 +000079
80 // storage-class-specifier
81 case tok::kw_typedef:
82 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, PrevSpec);
83 break;
84 case tok::kw_extern:
85 if (DS.SCS_thread_specified)
86 Diag(Tok, diag::ext_thread_before, "extern");
87 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, PrevSpec);
88 break;
89 case tok::kw_static:
90 if (DS.SCS_thread_specified)
91 Diag(Tok, diag::ext_thread_before, "static");
92 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, PrevSpec);
93 break;
94 case tok::kw_auto:
95 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, PrevSpec);
96 break;
97 case tok::kw_register:
98 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, PrevSpec);
99 break;
100 case tok::kw___thread:
101 if (DS.SCS_thread_specified)
102 isInvalid = 2, PrevSpec = "__thread";
103 else
104 DS.SCS_thread_specified = true;
105 break;
106
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000107 // type-specifiers
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000108 case tok::kw_short:
109 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
110 break;
111 case tok::kw_long:
112 if (DS.TypeSpecWidth != DeclSpec::TSW_long) {
113 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec);
114 } else {
115 DS.TypeSpecWidth = DeclSpec::TSW_unspecified;
116 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec);
117 }
118 break;
119 case tok::kw_signed:
120 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec);
121 break;
122 case tok::kw_unsigned:
123 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec);
124 break;
125 case tok::kw__Complex:
126 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec);
127 break;
128 case tok::kw__Imaginary:
129 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec);
130 break;
131 case tok::kw_void:
132 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec);
133 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000134 case tok::kw_char:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000135 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec);
136 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000137 case tok::kw_int:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000138 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec);
139 break;
140 case tok::kw_float:
141 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec);
142 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000143 case tok::kw_double:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000144 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec);
145 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000146 case tok::kw__Bool:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000147 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec);
148 break;
149 case tok::kw__Decimal32:
150 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec);
151 break;
152 case tok::kw__Decimal64:
153 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec);
154 break;
155 case tok::kw__Decimal128:
156 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000157 break;
158
159 //case tok::kw_struct:
160 //case tok::kw_union:
161 //case tok::kw_enum:
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000162
Chris Lattneracd58a32006-08-06 17:24:14 +0000163 //case tok::identifier:
164 // TODO: handle typedef names.
165
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000166 // type-qualifier
167 case tok::kw_const:
168 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
169 break;
170 case tok::kw_volatile:
171 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
172 break;
173 case tok::kw_restrict:
174 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
175 break;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000176
177 // function-specifier
178 case tok::kw_inline:
Chris Lattnerf63f89a2006-08-05 03:28:50 +0000179 // 'inline inline' is ok.
180 DS.FS_inline_specified = true;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000181 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000182 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000183 // If the specifier combination wasn't legal, issue a diagnostic.
184 if (isInvalid) {
185 assert(PrevSpec && "Method did not return previous specifier!");
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000186 if (isInvalid == 1) // Error.
187 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
188 else // extwarn.
189 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000190 }
191 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000192 }
193}
194
Chris Lattneracd58a32006-08-06 17:24:14 +0000195/// isDeclarationSpecifier() - Return true if the current token is part of a
196/// declaration specifier.
197bool Parser::isDeclarationSpecifier() const {
198 switch (Tok.getKind()) {
199 default: return false;
200 // storage-class-specifier
201 case tok::kw_typedef:
202 case tok::kw_extern:
203 case tok::kw_static:
204 case tok::kw_auto:
205 case tok::kw_register:
206 case tok::kw___thread:
207
208 // type-specifiers
209 case tok::kw_short:
210 case tok::kw_long:
211 case tok::kw_signed:
212 case tok::kw_unsigned:
213 case tok::kw__Complex:
214 case tok::kw__Imaginary:
215 case tok::kw_void:
216 case tok::kw_char:
217 case tok::kw_int:
218 case tok::kw_float:
219 case tok::kw_double:
220 case tok::kw__Bool:
221 case tok::kw__Decimal32:
222 case tok::kw__Decimal64:
223 case tok::kw__Decimal128:
224
225 // struct-or-union-specifier
226 case tok::kw_struct:
227 case tok::kw_union:
228 // enum-specifier
229 case tok::kw_enum:
230 // type-qualifier
231 case tok::kw_const:
232 case tok::kw_volatile:
233 case tok::kw_restrict:
234 // function-specifier
235 case tok::kw_inline:
236 return true;
237 // typedef-name
238 case tok::identifier:
239 // FIXME: if this is a typedef return true.
240 return false;
241 // TODO: Attributes.
242 }
243}
244
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000245
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000246/// ParseDeclarator
247/// declarator: [C99 6.7.5]
248/// pointer[opt] direct-declarator
249///
250/// pointer: [C99 6.7.5]
251/// '*' type-qualifier-list[opt]
252/// '*' type-qualifier-list[opt] pointer
253///
Chris Lattner15356a72006-08-06 00:02:28 +0000254void Parser::ParseDeclarator(Declarator &D) {
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000255 while (Tok.getKind() == tok::star) { // '*' -> pointer.
256 ConsumeToken(); // Eat the *.
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000257 DeclSpec DS;
258 ParseTypeQualifierListOpt(DS);
259 // TODO: do something with DS.
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000260 }
261
Chris Lattner15356a72006-08-06 00:02:28 +0000262 ParseDirectDeclarator(D);
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000263}
264
265/// ParseTypeQualifierListOpt
266/// type-qualifier-list: [C99 6.7.5]
267/// type-qualifier
268/// [GNU] attributes [TODO]
269/// type-qualifier-list type-qualifier
270/// [GNU] type-qualifier-list attributes [TODO]
271///
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000272void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
273 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000274 while (1) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000275 int isInvalid = false;
276 const char *PrevSpec = 0;
277
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000278 switch (Tok.getKind()) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000279 default:
280 // If this is not a declaration specifier token, we're done reading decl
281 // specifiers. First verify that DeclSpec's are consistent.
282 DS.Finish(StartLoc, Diags, getLang());
283 return;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000284 // TODO: attributes.
285 case tok::kw_const:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000286 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
287 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000288 case tok::kw_volatile:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000289 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
290 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000291 case tok::kw_restrict:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000292 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000293 break;
294 }
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000295
296 // If the specifier combination wasn't legal, issue a diagnostic.
297 if (isInvalid) {
298 assert(PrevSpec && "Method did not return previous specifier!");
299 if (isInvalid == 1) // Error.
300 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
301 else // extwarn.
302 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
303 }
304 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000305 }
306}
307
308
309/// ParseDirectDeclarator
310/// direct-declarator: [C99 6.7.5]
311/// identifier
312/// '(' declarator ')'
313/// [GNU] '(' attributes declarator ')'
Chris Lattnere8074e62006-08-06 18:30:15 +0000314/// [C90] direct-declarator '[' constant-expression[opt] ']'
315/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
316/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
317/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
318/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000319/// direct-declarator '(' parameter-type-list ')'
320/// direct-declarator '(' identifier-list[opt] ')'
321/// [GNU] direct-declarator '(' parameter-forward-declarations
322/// parameter-type-list[opt] ')'
323///
Chris Lattneracd58a32006-08-06 17:24:14 +0000324void Parser::ParseDirectDeclarator(Declarator &D) {
325 // Parse the first direct-declarator seen.
326 if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
327 assert(Tok.getIdentifierInfo() && "Not an identifier?");
328 D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
329 ConsumeToken();
330 } else if (Tok.getKind() == tok::l_paren) {
331 // direct-declarator: '(' declarator ')'
332 // direct-declarator: '(' attributes declarator ')' [TODO]
333 // Example: 'char (*X)' or 'int (*XX)(void)'
334 ParseParenDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000335 } else if (D.mayOmitIdentifier()) {
336 // This could be something simple like "int" (in which case the declarator
337 // portion is empty), if an abstract-declarator is allowed.
338 D.SetIdentifier(0, Tok.getLocation());
339 } else {
Chris Lattnereec40f92006-08-06 21:55:29 +0000340 // Expected identifier or '('.
341 Diag(Tok, diag::err_expected_ident_lparen);
342 D.SetIdentifier(0, Tok.getLocation());
Chris Lattneracd58a32006-08-06 17:24:14 +0000343 }
344
345 assert(D.isPastIdentifier() &&
346 "Haven't past the location of the identifier yet?");
347
348 while (1) {
349 if (Tok.getKind() == tok::l_paren) {
350 ParseParenDeclarator(D);
351 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000352 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000353 } else {
354 break;
355 }
356 }
357}
358
359/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
360/// either be before the identifier (in which case these are just grouping
361/// parens for precedence) or it may be after the identifier, in which case
362/// these are function arguments.
363///
364/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000365/// parameter-type-list: [C99 6.7.5]
366/// parameter-list
367/// parameter-list ',' '...'
368///
369/// parameter-list: [C99 6.7.5]
370/// parameter-declaration
371/// parameter-list ',' parameter-declaration
372///
373/// parameter-declaration: [C99 6.7.5]
374/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000375/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000376/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000377/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000378///
379/// identifier-list: [C99 6.7.5]
380/// identifier
381/// identifier-list ',' identifier
382///
Chris Lattneracd58a32006-08-06 17:24:14 +0000383void Parser::ParseParenDeclarator(Declarator &D) {
Chris Lattnereec40f92006-08-06 21:55:29 +0000384 SourceLocation LParenLoc = Tok.getLocation();
Chris Lattneracd58a32006-08-06 17:24:14 +0000385 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000386
Chris Lattneracd58a32006-08-06 17:24:14 +0000387 // If we haven't past the identifier yet (or where the identifier would be
388 // stored, if this is an abstract declarator), then this is probably just
389 // grouping parens.
390 if (!D.isPastIdentifier()) {
391 // Okay, this is probably a grouping paren. However, if this could be an
392 // abstract-declarator, then this could also be the start of function
393 // arguments (consider 'void()').
394 bool isGrouping;
395
396 if (!D.mayOmitIdentifier()) {
397 // If this can't be an abstract-declarator, this *must* be a grouping
398 // paren, because we haven't seen the identifier yet.
399 isGrouping = true;
400 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
401 isDeclarationSpecifier()) { // 'int(int)' is a function.
402
403 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000404 } else {
Chris Lattneracd58a32006-08-06 17:24:14 +0000405 // Otherwise, 'int (*X)', this is a grouping paren.
406 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000407 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000408
409 // If this is a grouping paren, handle:
410 // direct-declarator: '(' declarator ')'
411 // direct-declarator: '(' attributes declarator ')' [TODO]
412 if (isGrouping) {
413 ParseDeclarator(D);
Chris Lattnereec40f92006-08-06 21:55:29 +0000414 if (Tok.getKind() == tok::r_paren) {
415 ConsumeParen();
416 } else {
417 // expected ')': skip until we find ')'.
418 Diag(Tok, diag::err_expected_rparen);
419 Diag(LParenLoc, diag::err_matching);
420 SkipUntil(tok::r_paren);
421 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000422 return;
423 }
424
425 // Okay, if this wasn't a grouping paren, it must be the start of a function
426 // argument list. Recognize that this will never have an identifier (and
427 // where it would be), then fall through to the handling of argument lists.
428 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000429 }
430
Chris Lattneracd58a32006-08-06 17:24:14 +0000431 // Okay, this is the parameter list of a function definition, or it is an
432 // identifier list of a K&R-style function.
433
434 // FIXME: enter function-declaration scope, limiting any declarators for
435 // arguments to the function scope.
436 // NOTE: better to only create a scope if not '()'
437 bool isVariadic;
438 bool HasPrototype;
Chris Lattner14776b92006-08-06 22:27:40 +0000439 bool ErrorEmitted = false;
440
Chris Lattneracd58a32006-08-06 17:24:14 +0000441 if (Tok.getKind() == tok::r_paren) {
442 // int() -> no prototype, no '...'.
443 isVariadic = false;
444 HasPrototype = false;
445 } else if (Tok.getKind() == tok::identifier &&
446 0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
447 // Identifier list. Note that '(' identifier-list ')' is only allowed for
448 // normal declarators, not for abstract-declarators.
449 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
450
451 // If there was no identifier specified, either we are in an
452 // abstract-declarator, or we are in a parameter declarator which was found
453 // to be abstract. In abstract-declarators, identifier lists are not valid,
454 // diagnose this.
455 if (!D.getIdentifier())
456 Diag(Tok, diag::ext_ident_list_in_param);
457
458 // FIXME: Remember token.
459 ConsumeToken();
460 while (Tok.getKind() == tok::comma) {
461 // Eat the comma.
462 ConsumeToken();
463
Chris Lattner14776b92006-08-06 22:27:40 +0000464 if (Tok.getKind() != tok::identifier) {
465 // If not identifier, diagnose the error.
466 Diag(Tok, diag::err_expected_ident);
467 ErrorEmitted = true;
468 break;
469 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000470
471 // Eat the id.
472 // FIXME: remember it!
473 ConsumeToken();
474 }
475
Chris Lattneracd58a32006-08-06 17:24:14 +0000476 // K&R 'prototype'.
477 isVariadic = false;
478 HasPrototype = false;
479 } else {
480 isVariadic = false;
481 bool ReadArg = false;
482 // Finally, a normal, non-empty parameter type list.
483 while (1) {
484 if (Tok.getKind() == tok::ellipsis) {
485 isVariadic = true;
486
487 // Check to see if this is "void(...)" which is not allowed.
488 if (!ReadArg) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000489 // Otherwise, parse parameter type list. If it starts with an
490 // ellipsis, diagnose the malformed function.
Chris Lattneracd58a32006-08-06 17:24:14 +0000491 Diag(Tok, diag::err_ellipsis_first_arg);
492 isVariadic = false; // Treat this like 'void()'.
493 }
494
495 // Consume the ellipsis.
496 ConsumeToken();
497 break;
498 }
499
500 ReadArg = true;
501
502 // Parse the declaration-specifiers.
503 DeclSpec DS;
504 ParseDeclarationSpecifiers(DS);
505
506 // Parse the declarator. This is "PrototypeContext", because we must
507 // accept either 'declarator' or 'abstract-declarator' here.
508 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
509 ParseDeclarator(DeclaratorInfo);
510
511 // TODO: do something with the declarator, if it is valid.
512
513 // If the next token is a comma, consume it and keep reading arguments.
514 if (Tok.getKind() != tok::comma) break;
515
516 // Consume the comma.
517 ConsumeToken();
518 }
519
520 HasPrototype = true;
521 }
522
Chris Lattnereec40f92006-08-06 21:55:29 +0000523 // FIXME: pop the scope.
Chris Lattneracd58a32006-08-06 17:24:14 +0000524
Chris Lattner14776b92006-08-06 22:27:40 +0000525
526 // If we have the closing ')', eat it and we're done.
527 if (Tok.getKind() == tok::r_paren) {
528 ConsumeParen();
529 } else {
530 // If an error happened earlier parsing something else in the proto, don't
531 // issue another error.
532 if (!ErrorEmitted)
533 Diag(Tok, diag::err_expected_rparen);
534 SkipUntil(tok::r_paren);
535 }
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000536}
Chris Lattneracd58a32006-08-06 17:24:14 +0000537
Chris Lattnere8074e62006-08-06 18:30:15 +0000538
539/// [C90] direct-declarator '[' constant-expression[opt] ']'
540/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
541/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
542/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
543/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
544void Parser::ParseBracketDeclarator(Declarator &D) {
545 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnereec40f92006-08-06 21:55:29 +0000546 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000547
548 // If valid, this location is the position where we read the 'static' keyword.
549 SourceLocation StaticLoc;
550 if (Tok.getKind() == tok::kw_static) {
551 StaticLoc = Tok.getLocation();
552 ConsumeToken();
553 }
554
555 // If there is a type-qualifier-list, read it now.
556 DeclSpec DS;
557 ParseTypeQualifierListOpt(DS);
558 // TODO: do something with DS.
559
560 // If we haven't already read 'static', check to see if there is one after the
561 // type-qualifier-list.
562 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
563 StaticLoc = Tok.getLocation();
564 ConsumeToken();
565 }
566
567 // Handle "direct-declarator [ type-qual-list[opt] * ]".
Chris Lattnere8074e62006-08-06 18:30:15 +0000568 bool isStar = false;
Chris Lattner1906f802006-08-06 19:14:46 +0000569 if (Tok.getKind() == tok::star) {
570 // Remember the '*' token, in case we have to un-get it.
571 LexerToken StarTok = Tok;
Chris Lattnere8074e62006-08-06 18:30:15 +0000572 ConsumeToken();
Chris Lattner1906f802006-08-06 19:14:46 +0000573
574 // Check that the ']' token is present to avoid incorrectly parsing
575 // expressions starting with '*' as [*].
576 if (Tok.getKind() == tok::r_square) {
577 if (StaticLoc.isValid())
578 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
579 StaticLoc = SourceLocation(); // Drop the static.
580 isStar = true;
Chris Lattner1906f802006-08-06 19:14:46 +0000581 } else {
582 // Otherwise, the * must have been some expression (such as '*ptr') that
583 // started an assign-expr. We already consumed the token, but now we need
584 // to reparse it.
Chris Lattnereec40f92006-08-06 21:55:29 +0000585 // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
586 // macro expansion context, so they will be read again. It is basically
587 // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
Chris Lattner1906f802006-08-06 19:14:46 +0000588 assert(0 && "FIXME: int X[*p] unimplemented");
589 }
590 }
591
592 if (!isStar && Tok.getKind() != tok::r_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000593 // Parse the assignment-expression now.
594 assert(0 && "expr parsing not impl yet!");
595 }
596
Chris Lattnereec40f92006-08-06 21:55:29 +0000597 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000598
599 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
600 // it was not a constant expression.
601 if (!getLang().C99) {
602 // TODO: check C90 array constant exprness.
Chris Lattner8a39edc2006-08-06 18:33:32 +0000603 if (isStar || StaticLoc.isValid() || 0/*constantexpr*/)
604 Diag(StartLoc, diag::ext_c99_array_usage);
Chris Lattnere8074e62006-08-06 18:30:15 +0000605 }
606}
607