blob: 46a5dd720926c5381b4c829b78d64b59db232270 [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);
335 } else if (Tok.getKind() == tok::l_square &&
336 D.mayOmitIdentifier()) {
337 // direct-abstract-declarator[opt] '[' assignment-expression[opt] ']'
338 // direct-abstract-declarator[opt] '[' '*' ']'
339
340 // direct-abstract-declarator was not specified. Remember that this is the
341 // place where the identifier would have been.
342 D.SetIdentifier(0, Tok.getLocation());
343 // Don't consume the '[', handle it below.
344 } else if (D.mayOmitIdentifier()) {
345 // This could be something simple like "int" (in which case the declarator
346 // portion is empty), if an abstract-declarator is allowed.
347 D.SetIdentifier(0, Tok.getLocation());
348 } else {
349 // expected identifier or '(' or '['.
350 assert(0 && "ERROR: should recover!");
351 }
352
353 assert(D.isPastIdentifier() &&
354 "Haven't past the location of the identifier yet?");
355
356 while (1) {
357 if (Tok.getKind() == tok::l_paren) {
358 ParseParenDeclarator(D);
359 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000360 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000361 } else {
362 break;
363 }
364 }
365}
366
367/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
368/// either be before the identifier (in which case these are just grouping
369/// parens for precedence) or it may be after the identifier, in which case
370/// these are function arguments.
371///
372/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000373/// parameter-type-list: [C99 6.7.5]
374/// parameter-list
375/// parameter-list ',' '...'
376///
377/// parameter-list: [C99 6.7.5]
378/// parameter-declaration
379/// parameter-list ',' parameter-declaration
380///
381/// parameter-declaration: [C99 6.7.5]
382/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000383/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000384/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000385/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000386///
387/// identifier-list: [C99 6.7.5]
388/// identifier
389/// identifier-list ',' identifier
390///
Chris Lattneracd58a32006-08-06 17:24:14 +0000391void Parser::ParseParenDeclarator(Declarator &D) {
392 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000393
Chris Lattneracd58a32006-08-06 17:24:14 +0000394 // If we haven't past the identifier yet (or where the identifier would be
395 // stored, if this is an abstract declarator), then this is probably just
396 // grouping parens.
397 if (!D.isPastIdentifier()) {
398 // Okay, this is probably a grouping paren. However, if this could be an
399 // abstract-declarator, then this could also be the start of function
400 // arguments (consider 'void()').
401 bool isGrouping;
402
403 if (!D.mayOmitIdentifier()) {
404 // If this can't be an abstract-declarator, this *must* be a grouping
405 // paren, because we haven't seen the identifier yet.
406 isGrouping = true;
407 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
408 isDeclarationSpecifier()) { // 'int(int)' is a function.
409
410 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000411 } else {
Chris Lattneracd58a32006-08-06 17:24:14 +0000412 // Otherwise, 'int (*X)', this is a grouping paren.
413 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000414 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000415
416 // If this is a grouping paren, handle:
417 // direct-declarator: '(' declarator ')'
418 // direct-declarator: '(' attributes declarator ')' [TODO]
419 if (isGrouping) {
420 ParseDeclarator(D);
421 // expected ')': skip until we find ')'.
422 if (Tok.getKind() != tok::r_paren)
423 assert(0 && "Recover!");
424 ConsumeParen();
425 return;
426 }
427
428 // Okay, if this wasn't a grouping paren, it must be the start of a function
429 // argument list. Recognize that this will never have an identifier (and
430 // where it would be), then fall through to the handling of argument lists.
431 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000432 }
433
Chris Lattneracd58a32006-08-06 17:24:14 +0000434 // Okay, this is the parameter list of a function definition, or it is an
435 // identifier list of a K&R-style function.
436
437 // FIXME: enter function-declaration scope, limiting any declarators for
438 // arguments to the function scope.
439 // NOTE: better to only create a scope if not '()'
440 bool isVariadic;
441 bool HasPrototype;
442 if (Tok.getKind() == tok::r_paren) {
443 // int() -> no prototype, no '...'.
444 isVariadic = false;
445 HasPrototype = false;
446 } else if (Tok.getKind() == tok::identifier &&
447 0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
448 // Identifier list. Note that '(' identifier-list ')' is only allowed for
449 // normal declarators, not for abstract-declarators.
450 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
451
452 // If there was no identifier specified, either we are in an
453 // abstract-declarator, or we are in a parameter declarator which was found
454 // to be abstract. In abstract-declarators, identifier lists are not valid,
455 // diagnose this.
456 if (!D.getIdentifier())
457 Diag(Tok, diag::ext_ident_list_in_param);
458
459 // FIXME: Remember token.
460 ConsumeToken();
461 while (Tok.getKind() == tok::comma) {
462 // Eat the comma.
463 ConsumeToken();
464
465 // FIXME: if not identifier, consume until ')' then break.
466 assert(Tok.getKind() == tok::identifier);
467
468 // Eat the id.
469 // FIXME: remember it!
470 ConsumeToken();
471 }
472
473 // FIXME: if not identifier, consume until ')' then break.
474 assert(Tok.getKind() == tok::r_paren);
475
476 // 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
523
524 // expected ')': skip until we find ')'.
525 if (Tok.getKind() != tok::r_paren)
526 assert(0 && "Recover!");
527 ConsumeParen();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000528}
Chris Lattneracd58a32006-08-06 17:24:14 +0000529
Chris Lattnere8074e62006-08-06 18:30:15 +0000530
531/// [C90] direct-declarator '[' constant-expression[opt] ']'
532/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
533/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
534/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
535/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
536void Parser::ParseBracketDeclarator(Declarator &D) {
537 SourceLocation StartLoc = Tok.getLocation();
538 ConsumeSquare();
539
540 // If valid, this location is the position where we read the 'static' keyword.
541 SourceLocation StaticLoc;
542 if (Tok.getKind() == tok::kw_static) {
543 StaticLoc = Tok.getLocation();
544 ConsumeToken();
545 }
546
547 // If there is a type-qualifier-list, read it now.
548 DeclSpec DS;
549 ParseTypeQualifierListOpt(DS);
550 // TODO: do something with DS.
551
552 // If we haven't already read 'static', check to see if there is one after the
553 // type-qualifier-list.
554 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
555 StaticLoc = Tok.getLocation();
556 ConsumeToken();
557 }
558
559 // Handle "direct-declarator [ type-qual-list[opt] * ]".
560 // Check that the ']' token is present to avoid incorrectly parsing
561 // expressions starting with '*' as [*].
562 bool isStar = false;
563 if (Tok.getKind() == tok::star /*FIXME: && nexttok == tok::r_square*/) {
564 if (StaticLoc.isValid())
565 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
566 StaticLoc = SourceLocation(); // Drop the static.
567 isStar = true;
568 ConsumeToken();
569 } else if (Tok.getKind() != tok::r_square) {
570 // Parse the assignment-expression now.
571 assert(0 && "expr parsing not impl yet!");
572 }
573
574 ConsumeSquare();
575
576 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
577 // it was not a constant expression.
578 if (!getLang().C99) {
579 // TODO: check C90 array constant exprness.
580 }
581}
582