blob: b8a9052cb646ff586196c3e4b98ec4bcc9013256 [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 Lattnerd5d0a6c2006-08-07 00:58:14 +0000289
290/// ParseDeclarator - Parse and verify a newly-initialized declarator.
291///
292void Parser::ParseDeclarator(Declarator &D) {
293 /// This implements the 'declarator' production in the C grammar, then checks
294 /// for well-formedness and issues diagnostics.
295 ParseDeclaratorInternal(D);
296
297 // FIXME: validate D.
Chris Lattnerbf320c82006-08-07 05:05:30 +0000298
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000299}
300
301/// ParseDeclaratorInternal
Chris Lattner6c7416c2006-08-07 00:19:33 +0000302/// declarator: [C99 6.7.5]
303/// pointer[opt] direct-declarator
304///
305/// pointer: [C99 6.7.5]
306/// '*' type-qualifier-list[opt]
307/// '*' type-qualifier-list[opt] pointer
308///
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000309void Parser::ParseDeclaratorInternal(Declarator &D) {
Chris Lattner6c7416c2006-08-07 00:19:33 +0000310 if (Tok.getKind() != tok::star)
311 return ParseDirectDeclarator(D);
312
313 // Otherwise, '*' -> pointer.
314 SourceLocation Loc = Tok.getLocation();
315 ConsumeToken(); // Eat the *.
316 DeclSpec DS;
317 ParseTypeQualifierListOpt(DS);
318
319 // Recursively parse the declarator.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000320 ParseDeclaratorInternal(D);
Chris Lattner6c7416c2006-08-07 00:19:33 +0000321
322 // Remember that we parsed a pointer type, and remember the type-quals.
323 D.AddTypeInfo(DeclaratorTypeInfo::getPointer(DS.TypeQualifiers, Loc));
324}
325
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000326
327/// ParseDirectDeclarator
328/// direct-declarator: [C99 6.7.5]
329/// identifier
330/// '(' declarator ')'
331/// [GNU] '(' attributes declarator ')'
Chris Lattnere8074e62006-08-06 18:30:15 +0000332/// [C90] direct-declarator '[' constant-expression[opt] ']'
333/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
334/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
335/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
336/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000337/// direct-declarator '(' parameter-type-list ')'
338/// direct-declarator '(' identifier-list[opt] ')'
339/// [GNU] direct-declarator '(' parameter-forward-declarations
340/// parameter-type-list[opt] ')'
341///
Chris Lattneracd58a32006-08-06 17:24:14 +0000342void Parser::ParseDirectDeclarator(Declarator &D) {
343 // Parse the first direct-declarator seen.
344 if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
345 assert(Tok.getIdentifierInfo() && "Not an identifier?");
346 D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
347 ConsumeToken();
348 } else if (Tok.getKind() == tok::l_paren) {
349 // direct-declarator: '(' declarator ')'
350 // direct-declarator: '(' attributes declarator ')' [TODO]
351 // Example: 'char (*X)' or 'int (*XX)(void)'
352 ParseParenDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000353 } else if (D.mayOmitIdentifier()) {
354 // This could be something simple like "int" (in which case the declarator
355 // portion is empty), if an abstract-declarator is allowed.
356 D.SetIdentifier(0, Tok.getLocation());
357 } else {
Chris Lattnereec40f92006-08-06 21:55:29 +0000358 // Expected identifier or '('.
359 Diag(Tok, diag::err_expected_ident_lparen);
360 D.SetIdentifier(0, Tok.getLocation());
Chris Lattneracd58a32006-08-06 17:24:14 +0000361 }
362
363 assert(D.isPastIdentifier() &&
364 "Haven't past the location of the identifier yet?");
365
366 while (1) {
367 if (Tok.getKind() == tok::l_paren) {
368 ParseParenDeclarator(D);
369 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000370 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000371 } else {
372 break;
373 }
374 }
375}
376
377/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
378/// either be before the identifier (in which case these are just grouping
379/// parens for precedence) or it may be after the identifier, in which case
380/// these are function arguments.
381///
382/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000383/// parameter-type-list: [C99 6.7.5]
384/// parameter-list
385/// parameter-list ',' '...'
386///
387/// parameter-list: [C99 6.7.5]
388/// parameter-declaration
389/// parameter-list ',' parameter-declaration
390///
391/// parameter-declaration: [C99 6.7.5]
392/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000393/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000394/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000395/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000396///
397/// identifier-list: [C99 6.7.5]
398/// identifier
399/// identifier-list ',' identifier
400///
Chris Lattneracd58a32006-08-06 17:24:14 +0000401void Parser::ParseParenDeclarator(Declarator &D) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000402 SourceLocation StartLoc = Tok.getLocation();
Chris Lattneracd58a32006-08-06 17:24:14 +0000403 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000404
Chris Lattneracd58a32006-08-06 17:24:14 +0000405 // If we haven't past the identifier yet (or where the identifier would be
406 // stored, if this is an abstract declarator), then this is probably just
407 // grouping parens.
408 if (!D.isPastIdentifier()) {
409 // Okay, this is probably a grouping paren. However, if this could be an
410 // abstract-declarator, then this could also be the start of function
411 // arguments (consider 'void()').
412 bool isGrouping;
413
414 if (!D.mayOmitIdentifier()) {
415 // If this can't be an abstract-declarator, this *must* be a grouping
416 // paren, because we haven't seen the identifier yet.
417 isGrouping = true;
418 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
419 isDeclarationSpecifier()) { // 'int(int)' is a function.
420
421 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000422 } else {
Chris Lattnera3507222006-08-07 00:33:37 +0000423 // Otherwise, this is a grouping paren, e.g. 'int (*X)'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000424 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000425 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000426
427 // If this is a grouping paren, handle:
428 // direct-declarator: '(' declarator ')'
429 // direct-declarator: '(' attributes declarator ')' [TODO]
430 if (isGrouping) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000431 ParseDeclaratorInternal(D);
Chris Lattnereec40f92006-08-06 21:55:29 +0000432 if (Tok.getKind() == tok::r_paren) {
433 ConsumeParen();
434 } else {
435 // expected ')': skip until we find ')'.
436 Diag(Tok, diag::err_expected_rparen);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000437 Diag(StartLoc, diag::err_matching);
Chris Lattnereec40f92006-08-06 21:55:29 +0000438 SkipUntil(tok::r_paren);
439 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000440 return;
441 }
442
443 // Okay, if this wasn't a grouping paren, it must be the start of a function
Chris Lattnera3507222006-08-07 00:33:37 +0000444 // argument list. Recognize that this declarator will never have an
445 // identifier (and remember where it would have been), then fall through to
446 // the handling of argument lists.
Chris Lattneracd58a32006-08-06 17:24:14 +0000447 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000448 }
449
Chris Lattneracd58a32006-08-06 17:24:14 +0000450 // Okay, this is the parameter list of a function definition, or it is an
451 // identifier list of a K&R-style function.
452
453 // FIXME: enter function-declaration scope, limiting any declarators for
454 // arguments to the function scope.
455 // NOTE: better to only create a scope if not '()'
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000456 bool IsVariadic;
Chris Lattneracd58a32006-08-06 17:24:14 +0000457 bool HasPrototype;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000458 bool IsEmpty = false;
Chris Lattner14776b92006-08-06 22:27:40 +0000459 bool ErrorEmitted = false;
460
Chris Lattneracd58a32006-08-06 17:24:14 +0000461 if (Tok.getKind() == tok::r_paren) {
462 // int() -> no prototype, no '...'.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000463 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000464 HasPrototype = false;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000465 IsEmpty = true;
Chris Lattneracd58a32006-08-06 17:24:14 +0000466 } else if (Tok.getKind() == tok::identifier &&
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000467 1/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
Chris Lattneracd58a32006-08-06 17:24:14 +0000468 // Identifier list. Note that '(' identifier-list ')' is only allowed for
469 // normal declarators, not for abstract-declarators.
470 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
471
472 // If there was no identifier specified, either we are in an
473 // abstract-declarator, or we are in a parameter declarator which was found
474 // to be abstract. In abstract-declarators, identifier lists are not valid,
475 // diagnose this.
476 if (!D.getIdentifier())
477 Diag(Tok, diag::ext_ident_list_in_param);
478
479 // FIXME: Remember token.
480 ConsumeToken();
481 while (Tok.getKind() == tok::comma) {
482 // Eat the comma.
483 ConsumeToken();
484
Chris Lattner14776b92006-08-06 22:27:40 +0000485 if (Tok.getKind() != tok::identifier) {
486 // If not identifier, diagnose the error.
487 Diag(Tok, diag::err_expected_ident);
488 ErrorEmitted = true;
489 break;
490 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000491
492 // Eat the id.
493 // FIXME: remember it!
494 ConsumeToken();
495 }
496
Chris Lattneracd58a32006-08-06 17:24:14 +0000497 // K&R 'prototype'.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000498 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000499 HasPrototype = false;
500 } else {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000501 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000502 bool ReadArg = false;
503 // Finally, a normal, non-empty parameter type list.
504 while (1) {
505 if (Tok.getKind() == tok::ellipsis) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000506 IsVariadic = true;
Chris Lattneracd58a32006-08-06 17:24:14 +0000507
508 // Check to see if this is "void(...)" which is not allowed.
509 if (!ReadArg) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000510 // Otherwise, parse parameter type list. If it starts with an
511 // ellipsis, diagnose the malformed function.
Chris Lattneracd58a32006-08-06 17:24:14 +0000512 Diag(Tok, diag::err_ellipsis_first_arg);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000513 IsVariadic = false; // Treat this like 'void()'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000514 }
515
516 // Consume the ellipsis.
517 ConsumeToken();
518 break;
519 }
520
521 ReadArg = true;
522
523 // Parse the declaration-specifiers.
524 DeclSpec DS;
525 ParseDeclarationSpecifiers(DS);
526
527 // Parse the declarator. This is "PrototypeContext", because we must
528 // accept either 'declarator' or 'abstract-declarator' here.
529 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
530 ParseDeclarator(DeclaratorInfo);
531
532 // TODO: do something with the declarator, if it is valid.
533
534 // If the next token is a comma, consume it and keep reading arguments.
535 if (Tok.getKind() != tok::comma) break;
536
537 // Consume the comma.
538 ConsumeToken();
539 }
540
541 HasPrototype = true;
542 }
543
Chris Lattnereec40f92006-08-06 21:55:29 +0000544 // FIXME: pop the scope.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000545
546 // FIXME: capture argument info.
Chris Lattneracd58a32006-08-06 17:24:14 +0000547
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000548 // Remember that we parsed a function type, and remember the attributes.
549 D.AddTypeInfo(DeclaratorTypeInfo::getFunction(HasPrototype, IsVariadic,
Chris Lattnerfff824f2006-08-07 06:31:38 +0000550 IsEmpty, StartLoc));
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000551
Chris Lattner14776b92006-08-06 22:27:40 +0000552
553 // If we have the closing ')', eat it and we're done.
554 if (Tok.getKind() == tok::r_paren) {
555 ConsumeParen();
556 } else {
557 // If an error happened earlier parsing something else in the proto, don't
558 // issue another error.
559 if (!ErrorEmitted)
560 Diag(Tok, diag::err_expected_rparen);
561 SkipUntil(tok::r_paren);
562 }
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000563}
Chris Lattneracd58a32006-08-06 17:24:14 +0000564
Chris Lattnere8074e62006-08-06 18:30:15 +0000565
566/// [C90] direct-declarator '[' constant-expression[opt] ']'
567/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
568/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
569/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
570/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
571void Parser::ParseBracketDeclarator(Declarator &D) {
572 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnereec40f92006-08-06 21:55:29 +0000573 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000574
575 // If valid, this location is the position where we read the 'static' keyword.
576 SourceLocation StaticLoc;
577 if (Tok.getKind() == tok::kw_static) {
578 StaticLoc = Tok.getLocation();
579 ConsumeToken();
580 }
581
582 // If there is a type-qualifier-list, read it now.
583 DeclSpec DS;
584 ParseTypeQualifierListOpt(DS);
Chris Lattnere8074e62006-08-06 18:30:15 +0000585
586 // If we haven't already read 'static', check to see if there is one after the
587 // type-qualifier-list.
588 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
589 StaticLoc = Tok.getLocation();
590 ConsumeToken();
591 }
592
593 // Handle "direct-declarator [ type-qual-list[opt] * ]".
Chris Lattnere8074e62006-08-06 18:30:15 +0000594 bool isStar = false;
Chris Lattner1906f802006-08-06 19:14:46 +0000595 if (Tok.getKind() == tok::star) {
596 // Remember the '*' token, in case we have to un-get it.
597 LexerToken StarTok = Tok;
Chris Lattnere8074e62006-08-06 18:30:15 +0000598 ConsumeToken();
Chris Lattner1906f802006-08-06 19:14:46 +0000599
600 // Check that the ']' token is present to avoid incorrectly parsing
601 // expressions starting with '*' as [*].
602 if (Tok.getKind() == tok::r_square) {
603 if (StaticLoc.isValid())
604 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
605 StaticLoc = SourceLocation(); // Drop the static.
606 isStar = true;
Chris Lattner1906f802006-08-06 19:14:46 +0000607 } else {
608 // Otherwise, the * must have been some expression (such as '*ptr') that
609 // started an assign-expr. We already consumed the token, but now we need
610 // to reparse it.
Chris Lattnereec40f92006-08-06 21:55:29 +0000611 // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
612 // macro expansion context, so they will be read again. It is basically
613 // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
Chris Lattner1906f802006-08-06 19:14:46 +0000614 assert(0 && "FIXME: int X[*p] unimplemented");
615 }
616 }
617
Chris Lattner6c7416c2006-08-07 00:19:33 +0000618 void *NumElts = 0;
Chris Lattner1906f802006-08-06 19:14:46 +0000619 if (!isStar && Tok.getKind() != tok::r_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000620 // Parse the assignment-expression now.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000621 NumElts = /*FIXME: parse array size expr*/0;
Chris Lattnere8074e62006-08-06 18:30:15 +0000622 assert(0 && "expr parsing not impl yet!");
623 }
624
Chris Lattnereec40f92006-08-06 21:55:29 +0000625 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000626
627 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
628 // it was not a constant expression.
629 if (!getLang().C99) {
630 // TODO: check C90 array constant exprness.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000631 if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
Chris Lattner8a39edc2006-08-06 18:33:32 +0000632 Diag(StartLoc, diag::ext_c99_array_usage);
Chris Lattnere8074e62006-08-06 18:30:15 +0000633 }
Chris Lattner6c7416c2006-08-07 00:19:33 +0000634
635 // Remember that we parsed a pointer type, and remember the type-quals.
636 D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
637 StaticLoc.isValid(), isStar,
638 NumElts, StartLoc));
Chris Lattnere8074e62006-08-06 18:30:15 +0000639}
640