blob: 18113d52630fc83be692f8b73606f2e7caa141ba [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/// ParseTypeQualifierListOpt
247/// type-qualifier-list: [C99 6.7.5]
248/// type-qualifier
249/// [GNU] attributes [TODO]
250/// type-qualifier-list type-qualifier
251/// [GNU] type-qualifier-list attributes [TODO]
252///
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000253void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
254 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000255 while (1) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000256 int isInvalid = false;
257 const char *PrevSpec = 0;
258
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000259 switch (Tok.getKind()) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000260 default:
261 // If this is not a declaration specifier token, we're done reading decl
262 // specifiers. First verify that DeclSpec's are consistent.
263 DS.Finish(StartLoc, Diags, getLang());
264 return;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000265 // TODO: attributes.
266 case tok::kw_const:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000267 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
268 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000269 case tok::kw_volatile:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000270 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
271 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000272 case tok::kw_restrict:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000273 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000274 break;
275 }
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000276
277 // If the specifier combination wasn't legal, issue a diagnostic.
278 if (isInvalid) {
279 assert(PrevSpec && "Method did not return previous specifier!");
280 if (isInvalid == 1) // Error.
281 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
282 else // extwarn.
283 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
284 }
285 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000286 }
287}
288
Chris Lattner6c7416c2006-08-07 00:19:33 +0000289/// ParseDeclarator
290/// declarator: [C99 6.7.5]
291/// pointer[opt] direct-declarator
292///
293/// pointer: [C99 6.7.5]
294/// '*' type-qualifier-list[opt]
295/// '*' type-qualifier-list[opt] pointer
296///
297void Parser::ParseDeclarator(Declarator &D) {
298 if (Tok.getKind() != tok::star)
299 return ParseDirectDeclarator(D);
300
301 // Otherwise, '*' -> pointer.
302 SourceLocation Loc = Tok.getLocation();
303 ConsumeToken(); // Eat the *.
304 DeclSpec DS;
305 ParseTypeQualifierListOpt(DS);
306
307 // Recursively parse the declarator.
308 ParseDeclarator(D);
309
310 // Remember that we parsed a pointer type, and remember the type-quals.
311 D.AddTypeInfo(DeclaratorTypeInfo::getPointer(DS.TypeQualifiers, Loc));
312}
313
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000314
315/// ParseDirectDeclarator
316/// direct-declarator: [C99 6.7.5]
317/// identifier
318/// '(' declarator ')'
319/// [GNU] '(' attributes declarator ')'
Chris Lattnere8074e62006-08-06 18:30:15 +0000320/// [C90] direct-declarator '[' constant-expression[opt] ']'
321/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
322/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
323/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
324/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000325/// direct-declarator '(' parameter-type-list ')'
326/// direct-declarator '(' identifier-list[opt] ')'
327/// [GNU] direct-declarator '(' parameter-forward-declarations
328/// parameter-type-list[opt] ')'
329///
Chris Lattneracd58a32006-08-06 17:24:14 +0000330void Parser::ParseDirectDeclarator(Declarator &D) {
331 // Parse the first direct-declarator seen.
332 if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
333 assert(Tok.getIdentifierInfo() && "Not an identifier?");
334 D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
335 ConsumeToken();
336 } else if (Tok.getKind() == tok::l_paren) {
337 // direct-declarator: '(' declarator ')'
338 // direct-declarator: '(' attributes declarator ')' [TODO]
339 // Example: 'char (*X)' or 'int (*XX)(void)'
340 ParseParenDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000341 } else if (D.mayOmitIdentifier()) {
342 // This could be something simple like "int" (in which case the declarator
343 // portion is empty), if an abstract-declarator is allowed.
344 D.SetIdentifier(0, Tok.getLocation());
345 } else {
Chris Lattnereec40f92006-08-06 21:55:29 +0000346 // Expected identifier or '('.
347 Diag(Tok, diag::err_expected_ident_lparen);
348 D.SetIdentifier(0, Tok.getLocation());
Chris Lattneracd58a32006-08-06 17:24:14 +0000349 }
350
351 assert(D.isPastIdentifier() &&
352 "Haven't past the location of the identifier yet?");
353
354 while (1) {
355 if (Tok.getKind() == tok::l_paren) {
356 ParseParenDeclarator(D);
357 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000358 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000359 } else {
360 break;
361 }
362 }
363}
364
365/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
366/// either be before the identifier (in which case these are just grouping
367/// parens for precedence) or it may be after the identifier, in which case
368/// these are function arguments.
369///
370/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000371/// parameter-type-list: [C99 6.7.5]
372/// parameter-list
373/// parameter-list ',' '...'
374///
375/// parameter-list: [C99 6.7.5]
376/// parameter-declaration
377/// parameter-list ',' parameter-declaration
378///
379/// parameter-declaration: [C99 6.7.5]
380/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000381/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000382/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000383/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000384///
385/// identifier-list: [C99 6.7.5]
386/// identifier
387/// identifier-list ',' identifier
388///
Chris Lattneracd58a32006-08-06 17:24:14 +0000389void Parser::ParseParenDeclarator(Declarator &D) {
Chris Lattnereec40f92006-08-06 21:55:29 +0000390 SourceLocation LParenLoc = Tok.getLocation();
Chris Lattneracd58a32006-08-06 17:24:14 +0000391 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000392
Chris Lattneracd58a32006-08-06 17:24:14 +0000393 // If we haven't past the identifier yet (or where the identifier would be
394 // stored, if this is an abstract declarator), then this is probably just
395 // grouping parens.
396 if (!D.isPastIdentifier()) {
397 // Okay, this is probably a grouping paren. However, if this could be an
398 // abstract-declarator, then this could also be the start of function
399 // arguments (consider 'void()').
400 bool isGrouping;
401
402 if (!D.mayOmitIdentifier()) {
403 // If this can't be an abstract-declarator, this *must* be a grouping
404 // paren, because we haven't seen the identifier yet.
405 isGrouping = true;
406 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
407 isDeclarationSpecifier()) { // 'int(int)' is a function.
408
409 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000410 } else {
Chris Lattnera3507222006-08-07 00:33:37 +0000411 // Otherwise, this is a grouping paren, e.g. 'int (*X)'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000412 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000413 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000414
415 // If this is a grouping paren, handle:
416 // direct-declarator: '(' declarator ')'
417 // direct-declarator: '(' attributes declarator ')' [TODO]
418 if (isGrouping) {
419 ParseDeclarator(D);
Chris Lattnereec40f92006-08-06 21:55:29 +0000420 if (Tok.getKind() == tok::r_paren) {
421 ConsumeParen();
422 } else {
423 // expected ')': skip until we find ')'.
424 Diag(Tok, diag::err_expected_rparen);
425 Diag(LParenLoc, diag::err_matching);
426 SkipUntil(tok::r_paren);
427 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000428 return;
429 }
430
431 // Okay, if this wasn't a grouping paren, it must be the start of a function
Chris Lattnera3507222006-08-07 00:33:37 +0000432 // argument list. Recognize that this declarator will never have an
433 // identifier (and remember where it would have been), then fall through to
434 // the handling of argument lists.
Chris Lattneracd58a32006-08-06 17:24:14 +0000435 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000436 }
437
Chris Lattneracd58a32006-08-06 17:24:14 +0000438 // Okay, this is the parameter list of a function definition, or it is an
439 // identifier list of a K&R-style function.
440
441 // FIXME: enter function-declaration scope, limiting any declarators for
442 // arguments to the function scope.
443 // NOTE: better to only create a scope if not '()'
444 bool isVariadic;
445 bool HasPrototype;
Chris Lattner14776b92006-08-06 22:27:40 +0000446 bool ErrorEmitted = false;
447
Chris Lattneracd58a32006-08-06 17:24:14 +0000448 if (Tok.getKind() == tok::r_paren) {
449 // int() -> no prototype, no '...'.
450 isVariadic = false;
451 HasPrototype = false;
452 } else if (Tok.getKind() == tok::identifier &&
453 0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
454 // Identifier list. Note that '(' identifier-list ')' is only allowed for
455 // normal declarators, not for abstract-declarators.
456 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
457
458 // If there was no identifier specified, either we are in an
459 // abstract-declarator, or we are in a parameter declarator which was found
460 // to be abstract. In abstract-declarators, identifier lists are not valid,
461 // diagnose this.
462 if (!D.getIdentifier())
463 Diag(Tok, diag::ext_ident_list_in_param);
464
465 // FIXME: Remember token.
466 ConsumeToken();
467 while (Tok.getKind() == tok::comma) {
468 // Eat the comma.
469 ConsumeToken();
470
Chris Lattner14776b92006-08-06 22:27:40 +0000471 if (Tok.getKind() != tok::identifier) {
472 // If not identifier, diagnose the error.
473 Diag(Tok, diag::err_expected_ident);
474 ErrorEmitted = true;
475 break;
476 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000477
478 // Eat the id.
479 // FIXME: remember it!
480 ConsumeToken();
481 }
482
Chris Lattneracd58a32006-08-06 17:24:14 +0000483 // K&R 'prototype'.
484 isVariadic = false;
485 HasPrototype = false;
486 } else {
487 isVariadic = false;
488 bool ReadArg = false;
489 // Finally, a normal, non-empty parameter type list.
490 while (1) {
491 if (Tok.getKind() == tok::ellipsis) {
492 isVariadic = true;
493
494 // Check to see if this is "void(...)" which is not allowed.
495 if (!ReadArg) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000496 // Otherwise, parse parameter type list. If it starts with an
497 // ellipsis, diagnose the malformed function.
Chris Lattneracd58a32006-08-06 17:24:14 +0000498 Diag(Tok, diag::err_ellipsis_first_arg);
499 isVariadic = false; // Treat this like 'void()'.
500 }
501
502 // Consume the ellipsis.
503 ConsumeToken();
504 break;
505 }
506
507 ReadArg = true;
508
509 // Parse the declaration-specifiers.
510 DeclSpec DS;
511 ParseDeclarationSpecifiers(DS);
512
513 // Parse the declarator. This is "PrototypeContext", because we must
514 // accept either 'declarator' or 'abstract-declarator' here.
515 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
516 ParseDeclarator(DeclaratorInfo);
517
518 // TODO: do something with the declarator, if it is valid.
519
520 // If the next token is a comma, consume it and keep reading arguments.
521 if (Tok.getKind() != tok::comma) break;
522
523 // Consume the comma.
524 ConsumeToken();
525 }
526
527 HasPrototype = true;
528 }
529
Chris Lattnereec40f92006-08-06 21:55:29 +0000530 // FIXME: pop the scope.
Chris Lattneracd58a32006-08-06 17:24:14 +0000531
Chris Lattnera3507222006-08-07 00:33:37 +0000532 // FIXME: Add the function declarator.
Chris Lattner14776b92006-08-06 22:27:40 +0000533
534 // If we have the closing ')', eat it and we're done.
535 if (Tok.getKind() == tok::r_paren) {
536 ConsumeParen();
537 } else {
538 // If an error happened earlier parsing something else in the proto, don't
539 // issue another error.
540 if (!ErrorEmitted)
541 Diag(Tok, diag::err_expected_rparen);
542 SkipUntil(tok::r_paren);
543 }
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000544}
Chris Lattneracd58a32006-08-06 17:24:14 +0000545
Chris Lattnere8074e62006-08-06 18:30:15 +0000546
547/// [C90] direct-declarator '[' constant-expression[opt] ']'
548/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
549/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
550/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
551/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
552void Parser::ParseBracketDeclarator(Declarator &D) {
553 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnereec40f92006-08-06 21:55:29 +0000554 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000555
556 // If valid, this location is the position where we read the 'static' keyword.
557 SourceLocation StaticLoc;
558 if (Tok.getKind() == tok::kw_static) {
559 StaticLoc = Tok.getLocation();
560 ConsumeToken();
561 }
562
563 // If there is a type-qualifier-list, read it now.
564 DeclSpec DS;
565 ParseTypeQualifierListOpt(DS);
Chris Lattnere8074e62006-08-06 18:30:15 +0000566
567 // If we haven't already read 'static', check to see if there is one after the
568 // type-qualifier-list.
569 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
570 StaticLoc = Tok.getLocation();
571 ConsumeToken();
572 }
573
574 // Handle "direct-declarator [ type-qual-list[opt] * ]".
Chris Lattnere8074e62006-08-06 18:30:15 +0000575 bool isStar = false;
Chris Lattner1906f802006-08-06 19:14:46 +0000576 if (Tok.getKind() == tok::star) {
577 // Remember the '*' token, in case we have to un-get it.
578 LexerToken StarTok = Tok;
Chris Lattnere8074e62006-08-06 18:30:15 +0000579 ConsumeToken();
Chris Lattner1906f802006-08-06 19:14:46 +0000580
581 // Check that the ']' token is present to avoid incorrectly parsing
582 // expressions starting with '*' as [*].
583 if (Tok.getKind() == tok::r_square) {
584 if (StaticLoc.isValid())
585 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
586 StaticLoc = SourceLocation(); // Drop the static.
587 isStar = true;
Chris Lattner1906f802006-08-06 19:14:46 +0000588 } else {
589 // Otherwise, the * must have been some expression (such as '*ptr') that
590 // started an assign-expr. We already consumed the token, but now we need
591 // to reparse it.
Chris Lattnereec40f92006-08-06 21:55:29 +0000592 // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
593 // macro expansion context, so they will be read again. It is basically
594 // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
Chris Lattner1906f802006-08-06 19:14:46 +0000595 assert(0 && "FIXME: int X[*p] unimplemented");
596 }
597 }
598
Chris Lattner6c7416c2006-08-07 00:19:33 +0000599 void *NumElts = 0;
Chris Lattner1906f802006-08-06 19:14:46 +0000600 if (!isStar && Tok.getKind() != tok::r_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000601 // Parse the assignment-expression now.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000602 NumElts = /*FIXME: parse array size expr*/0;
Chris Lattnere8074e62006-08-06 18:30:15 +0000603 assert(0 && "expr parsing not impl yet!");
604 }
605
Chris Lattnereec40f92006-08-06 21:55:29 +0000606 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000607
608 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
609 // it was not a constant expression.
610 if (!getLang().C99) {
611 // TODO: check C90 array constant exprness.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000612 if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
Chris Lattner8a39edc2006-08-06 18:33:32 +0000613 Diag(StartLoc, diag::ext_c99_array_usage);
Chris Lattnere8074e62006-08-06 18:30:15 +0000614 }
Chris Lattner6c7416c2006-08-07 00:19:33 +0000615
616 // Remember that we parsed a pointer type, and remember the type-quals.
617 D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
618 StaticLoc.isValid(), isStar,
619 NumElts, StartLoc));
Chris Lattnere8074e62006-08-06 18:30:15 +0000620}
621