blob: f0bf6a675cf67cee54d525716fae8b5bd287ad54 [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.
298
299
300}
301
302/// ParseDeclaratorInternal
Chris Lattner6c7416c2006-08-07 00:19:33 +0000303/// declarator: [C99 6.7.5]
304/// pointer[opt] direct-declarator
305///
306/// pointer: [C99 6.7.5]
307/// '*' type-qualifier-list[opt]
308/// '*' type-qualifier-list[opt] pointer
309///
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000310void Parser::ParseDeclaratorInternal(Declarator &D) {
Chris Lattner6c7416c2006-08-07 00:19:33 +0000311 if (Tok.getKind() != tok::star)
312 return ParseDirectDeclarator(D);
313
314 // Otherwise, '*' -> pointer.
315 SourceLocation Loc = Tok.getLocation();
316 ConsumeToken(); // Eat the *.
317 DeclSpec DS;
318 ParseTypeQualifierListOpt(DS);
319
320 // Recursively parse the declarator.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000321 ParseDeclaratorInternal(D);
Chris Lattner6c7416c2006-08-07 00:19:33 +0000322
323 // Remember that we parsed a pointer type, and remember the type-quals.
324 D.AddTypeInfo(DeclaratorTypeInfo::getPointer(DS.TypeQualifiers, Loc));
325}
326
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000327
328/// ParseDirectDeclarator
329/// direct-declarator: [C99 6.7.5]
330/// identifier
331/// '(' declarator ')'
332/// [GNU] '(' attributes declarator ')'
Chris Lattnere8074e62006-08-06 18:30:15 +0000333/// [C90] direct-declarator '[' constant-expression[opt] ']'
334/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
335/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
336/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
337/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000338/// direct-declarator '(' parameter-type-list ')'
339/// direct-declarator '(' identifier-list[opt] ')'
340/// [GNU] direct-declarator '(' parameter-forward-declarations
341/// parameter-type-list[opt] ')'
342///
Chris Lattneracd58a32006-08-06 17:24:14 +0000343void Parser::ParseDirectDeclarator(Declarator &D) {
344 // Parse the first direct-declarator seen.
345 if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
346 assert(Tok.getIdentifierInfo() && "Not an identifier?");
347 D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
348 ConsumeToken();
349 } else if (Tok.getKind() == tok::l_paren) {
350 // direct-declarator: '(' declarator ')'
351 // direct-declarator: '(' attributes declarator ')' [TODO]
352 // Example: 'char (*X)' or 'int (*XX)(void)'
353 ParseParenDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000354 } else if (D.mayOmitIdentifier()) {
355 // This could be something simple like "int" (in which case the declarator
356 // portion is empty), if an abstract-declarator is allowed.
357 D.SetIdentifier(0, Tok.getLocation());
358 } else {
Chris Lattnereec40f92006-08-06 21:55:29 +0000359 // Expected identifier or '('.
360 Diag(Tok, diag::err_expected_ident_lparen);
361 D.SetIdentifier(0, Tok.getLocation());
Chris Lattneracd58a32006-08-06 17:24:14 +0000362 }
363
364 assert(D.isPastIdentifier() &&
365 "Haven't past the location of the identifier yet?");
366
367 while (1) {
368 if (Tok.getKind() == tok::l_paren) {
369 ParseParenDeclarator(D);
370 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000371 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000372 } else {
373 break;
374 }
375 }
376}
377
378/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
379/// either be before the identifier (in which case these are just grouping
380/// parens for precedence) or it may be after the identifier, in which case
381/// these are function arguments.
382///
383/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000384/// parameter-type-list: [C99 6.7.5]
385/// parameter-list
386/// parameter-list ',' '...'
387///
388/// parameter-list: [C99 6.7.5]
389/// parameter-declaration
390/// parameter-list ',' parameter-declaration
391///
392/// parameter-declaration: [C99 6.7.5]
393/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000394/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000395/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000396/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000397///
398/// identifier-list: [C99 6.7.5]
399/// identifier
400/// identifier-list ',' identifier
401///
Chris Lattneracd58a32006-08-06 17:24:14 +0000402void Parser::ParseParenDeclarator(Declarator &D) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000403 SourceLocation StartLoc = Tok.getLocation();
Chris Lattneracd58a32006-08-06 17:24:14 +0000404 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000405
Chris Lattneracd58a32006-08-06 17:24:14 +0000406 // If we haven't past the identifier yet (or where the identifier would be
407 // stored, if this is an abstract declarator), then this is probably just
408 // grouping parens.
409 if (!D.isPastIdentifier()) {
410 // Okay, this is probably a grouping paren. However, if this could be an
411 // abstract-declarator, then this could also be the start of function
412 // arguments (consider 'void()').
413 bool isGrouping;
414
415 if (!D.mayOmitIdentifier()) {
416 // If this can't be an abstract-declarator, this *must* be a grouping
417 // paren, because we haven't seen the identifier yet.
418 isGrouping = true;
419 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
420 isDeclarationSpecifier()) { // 'int(int)' is a function.
421
422 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000423 } else {
Chris Lattnera3507222006-08-07 00:33:37 +0000424 // Otherwise, this is a grouping paren, e.g. 'int (*X)'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000425 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000426 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000427
428 // If this is a grouping paren, handle:
429 // direct-declarator: '(' declarator ')'
430 // direct-declarator: '(' attributes declarator ')' [TODO]
431 if (isGrouping) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000432 ParseDeclaratorInternal(D);
Chris Lattnereec40f92006-08-06 21:55:29 +0000433 if (Tok.getKind() == tok::r_paren) {
434 ConsumeParen();
435 } else {
436 // expected ')': skip until we find ')'.
437 Diag(Tok, diag::err_expected_rparen);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000438 Diag(StartLoc, diag::err_matching);
Chris Lattnereec40f92006-08-06 21:55:29 +0000439 SkipUntil(tok::r_paren);
440 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000441 return;
442 }
443
444 // Okay, if this wasn't a grouping paren, it must be the start of a function
Chris Lattnera3507222006-08-07 00:33:37 +0000445 // argument list. Recognize that this declarator will never have an
446 // identifier (and remember where it would have been), then fall through to
447 // the handling of argument lists.
Chris Lattneracd58a32006-08-06 17:24:14 +0000448 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000449 }
450
Chris Lattneracd58a32006-08-06 17:24:14 +0000451 // Okay, this is the parameter list of a function definition, or it is an
452 // identifier list of a K&R-style function.
453
454 // FIXME: enter function-declaration scope, limiting any declarators for
455 // arguments to the function scope.
456 // NOTE: better to only create a scope if not '()'
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000457 bool IsVariadic;
Chris Lattneracd58a32006-08-06 17:24:14 +0000458 bool HasPrototype;
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;
465 } else if (Tok.getKind() == tok::identifier &&
466 0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
467 // Identifier list. Note that '(' identifier-list ')' is only allowed for
468 // normal declarators, not for abstract-declarators.
469 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
470
471 // If there was no identifier specified, either we are in an
472 // abstract-declarator, or we are in a parameter declarator which was found
473 // to be abstract. In abstract-declarators, identifier lists are not valid,
474 // diagnose this.
475 if (!D.getIdentifier())
476 Diag(Tok, diag::ext_ident_list_in_param);
477
478 // FIXME: Remember token.
479 ConsumeToken();
480 while (Tok.getKind() == tok::comma) {
481 // Eat the comma.
482 ConsumeToken();
483
Chris Lattner14776b92006-08-06 22:27:40 +0000484 if (Tok.getKind() != tok::identifier) {
485 // If not identifier, diagnose the error.
486 Diag(Tok, diag::err_expected_ident);
487 ErrorEmitted = true;
488 break;
489 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000490
491 // Eat the id.
492 // FIXME: remember it!
493 ConsumeToken();
494 }
495
Chris Lattneracd58a32006-08-06 17:24:14 +0000496 // K&R 'prototype'.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000497 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000498 HasPrototype = false;
499 } else {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000500 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000501 bool ReadArg = false;
502 // Finally, a normal, non-empty parameter type list.
503 while (1) {
504 if (Tok.getKind() == tok::ellipsis) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000505 IsVariadic = true;
Chris Lattneracd58a32006-08-06 17:24:14 +0000506
507 // Check to see if this is "void(...)" which is not allowed.
508 if (!ReadArg) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000509 // Otherwise, parse parameter type list. If it starts with an
510 // ellipsis, diagnose the malformed function.
Chris Lattneracd58a32006-08-06 17:24:14 +0000511 Diag(Tok, diag::err_ellipsis_first_arg);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000512 IsVariadic = false; // Treat this like 'void()'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000513 }
514
515 // Consume the ellipsis.
516 ConsumeToken();
517 break;
518 }
519
520 ReadArg = true;
521
522 // Parse the declaration-specifiers.
523 DeclSpec DS;
524 ParseDeclarationSpecifiers(DS);
525
526 // Parse the declarator. This is "PrototypeContext", because we must
527 // accept either 'declarator' or 'abstract-declarator' here.
528 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
529 ParseDeclarator(DeclaratorInfo);
530
531 // TODO: do something with the declarator, if it is valid.
532
533 // If the next token is a comma, consume it and keep reading arguments.
534 if (Tok.getKind() != tok::comma) break;
535
536 // Consume the comma.
537 ConsumeToken();
538 }
539
540 HasPrototype = true;
541 }
542
Chris Lattnereec40f92006-08-06 21:55:29 +0000543 // FIXME: pop the scope.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000544
545 // FIXME: capture argument info.
Chris Lattneracd58a32006-08-06 17:24:14 +0000546
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000547 // Remember that we parsed a function type, and remember the attributes.
548 D.AddTypeInfo(DeclaratorTypeInfo::getFunction(HasPrototype, IsVariadic,
549 StartLoc));
550
Chris Lattner14776b92006-08-06 22:27:40 +0000551
552 // If we have the closing ')', eat it and we're done.
553 if (Tok.getKind() == tok::r_paren) {
554 ConsumeParen();
555 } else {
556 // If an error happened earlier parsing something else in the proto, don't
557 // issue another error.
558 if (!ErrorEmitted)
559 Diag(Tok, diag::err_expected_rparen);
560 SkipUntil(tok::r_paren);
561 }
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000562}
Chris Lattneracd58a32006-08-06 17:24:14 +0000563
Chris Lattnere8074e62006-08-06 18:30:15 +0000564
565/// [C90] direct-declarator '[' constant-expression[opt] ']'
566/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
567/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
568/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
569/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
570void Parser::ParseBracketDeclarator(Declarator &D) {
571 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnereec40f92006-08-06 21:55:29 +0000572 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000573
574 // If valid, this location is the position where we read the 'static' keyword.
575 SourceLocation StaticLoc;
576 if (Tok.getKind() == tok::kw_static) {
577 StaticLoc = Tok.getLocation();
578 ConsumeToken();
579 }
580
581 // If there is a type-qualifier-list, read it now.
582 DeclSpec DS;
583 ParseTypeQualifierListOpt(DS);
Chris Lattnere8074e62006-08-06 18:30:15 +0000584
585 // If we haven't already read 'static', check to see if there is one after the
586 // type-qualifier-list.
587 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
588 StaticLoc = Tok.getLocation();
589 ConsumeToken();
590 }
591
592 // Handle "direct-declarator [ type-qual-list[opt] * ]".
Chris Lattnere8074e62006-08-06 18:30:15 +0000593 bool isStar = false;
Chris Lattner1906f802006-08-06 19:14:46 +0000594 if (Tok.getKind() == tok::star) {
595 // Remember the '*' token, in case we have to un-get it.
596 LexerToken StarTok = Tok;
Chris Lattnere8074e62006-08-06 18:30:15 +0000597 ConsumeToken();
Chris Lattner1906f802006-08-06 19:14:46 +0000598
599 // Check that the ']' token is present to avoid incorrectly parsing
600 // expressions starting with '*' as [*].
601 if (Tok.getKind() == tok::r_square) {
602 if (StaticLoc.isValid())
603 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
604 StaticLoc = SourceLocation(); // Drop the static.
605 isStar = true;
Chris Lattner1906f802006-08-06 19:14:46 +0000606 } else {
607 // Otherwise, the * must have been some expression (such as '*ptr') that
608 // started an assign-expr. We already consumed the token, but now we need
609 // to reparse it.
Chris Lattnereec40f92006-08-06 21:55:29 +0000610 // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
611 // macro expansion context, so they will be read again. It is basically
612 // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
Chris Lattner1906f802006-08-06 19:14:46 +0000613 assert(0 && "FIXME: int X[*p] unimplemented");
614 }
615 }
616
Chris Lattner6c7416c2006-08-07 00:19:33 +0000617 void *NumElts = 0;
Chris Lattner1906f802006-08-06 19:14:46 +0000618 if (!isStar && Tok.getKind() != tok::r_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000619 // Parse the assignment-expression now.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000620 NumElts = /*FIXME: parse array size expr*/0;
Chris Lattnere8074e62006-08-06 18:30:15 +0000621 assert(0 && "expr parsing not impl yet!");
622 }
623
Chris Lattnereec40f92006-08-06 21:55:29 +0000624 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000625
626 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
627 // it was not a constant expression.
628 if (!getLang().C99) {
629 // TODO: check C90 array constant exprness.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000630 if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
Chris Lattner8a39edc2006-08-06 18:33:32 +0000631 Diag(StartLoc, diag::ext_c99_array_usage);
Chris Lattnere8074e62006-08-06 18:30:15 +0000632 }
Chris Lattner6c7416c2006-08-07 00:19:33 +0000633
634 // Remember that we parsed a pointer type, and remember the type-quals.
635 D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
636 StaticLoc.isValid(), isStar,
637 NumElts, StartLoc));
Chris Lattnere8074e62006-08-06 18:30:15 +0000638}
639