blob: 829d6754a26ef767038118f0f4c76aa09c900137 [file] [log] [blame]
Chris Lattnereb8a28f2006-08-10 18:43:39 +00001//===--- Declaration.cpp - Declaration Parsing ----------------------------===//
Chris Lattnerc0acd3d2006-07-31 05:13:43 +00002//
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
Chris Lattner53361ac2006-08-10 05:19:57 +000023/// ParseDeclaration - Parse a full 'declaration', which consists of
24/// declaration-specifiers, some number of declarators, and a semicolon.
25/// 'Context' should be a Declarator::TheContext value.
26void Parser::ParseDeclaration(unsigned Context) {
27 // Parse the common declaration-specifiers piece.
28 DeclSpec DS;
29 ParseDeclarationSpecifiers(DS);
30
31 Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
32 ParseDeclarator(DeclaratorInfo);
33
34 ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
35}
36
37void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
38 // At this point, we know that it is not a function definition. Parse the
39 // rest of the init-declarator-list.
40 while (1) {
41 // must be: decl-spec[opt] declarator init-declarator-list
42 // Parse declarator '=' initializer.
43 if (Tok.getKind() == tok::equal) {
44 ConsumeToken();
Chris Lattner2f9980e2006-08-10 18:39:24 +000045 // FIXME: THIS IS WRONG: should ParseInitializer!!
Chris Lattner53361ac2006-08-10 05:19:57 +000046 ParseExpression();
47 }
48
49
50 // TODO: install declarator.
51
52 // If we don't have a comma, it is either the end of the list (a ';') or an
53 // error, bail out.
54 if (Tok.getKind() != tok::comma)
55 break;
56
57 // Consume the comma.
58 ConsumeToken();
59
60 // Parse the next declarator.
61 D.clear();
62 ParseDeclarator(D);
63 }
64
65 if (Tok.getKind() == tok::semi) {
66 ConsumeToken();
67 } else {
68 Diag(Tok, diag::err_parse_error);
69 // Skip to end of block or statement
70 SkipUntil(tok::r_brace, true);
71 if (Tok.getKind() == tok::semi)
72 ConsumeToken();
73 }
74}
75
76
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000077/// ParseDeclarationSpecifiers
78/// declaration-specifiers: [C99 6.7]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000079/// storage-class-specifier declaration-specifiers [opt]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000080/// type-specifier declaration-specifiers [opt]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000081/// type-qualifier declaration-specifiers [opt]
82/// [C99] function-specifier declaration-specifiers [opt]
83/// [GNU] attributes declaration-specifiers [opt] [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000084///
Chris Lattnerf63f89a2006-08-05 03:28:50 +000085/// storage-class-specifier: [C99 6.7.1]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000086/// 'typedef'
87/// 'extern'
88/// 'static'
89/// 'auto'
90/// 'register'
91/// [GNU] '__thread'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000092/// type-specifier: [C99 6.7.2]
93/// 'void'
94/// 'char'
95/// 'short'
96/// 'int'
97/// 'long'
98/// 'float'
99/// 'double'
100/// 'signed'
101/// 'unsigned'
Chris Lattner8e90ef62006-08-05 03:30:45 +0000102/// struct-or-union-specifier [TODO]
103/// enum-specifier [TODO]
104/// typedef-name [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000105/// [C99] '_Bool'
106/// [C99] '_Complex'
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000107/// [C99] '_Imaginary' // Removed in TC2?
108/// [GNU] '_Decimal32'
109/// [GNU] '_Decimal64'
110/// [GNU] '_Decimal128'
Chris Lattnerf63f89a2006-08-05 03:28:50 +0000111/// [GNU] typeof-specifier [TODO]
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000112/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
113/// [OBJC] typedef-name objc-protocol-refs [TODO]
114/// [OBJC] objc-protocol-refs [TODO]
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000115/// type-qualifier:
116/// const
117/// volatile
118/// [C99] restrict
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000119/// function-specifier: [C99 6.7.4]
120/// [C99] inline
121///
122void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
123 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000124 while (1) {
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000125 int isInvalid = false;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000126 const char *PrevSpec = 0;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000127 switch (Tok.getKind()) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000128 default:
129 // If this is not a declaration specifier token, we're done reading decl
130 // specifiers. First verify that DeclSpec's are consistent.
Chris Lattner839713c2006-08-04 06:15:52 +0000131 DS.Finish(StartLoc, Diags, getLang());
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000132 return;
Chris Lattnerf63f89a2006-08-05 03:28:50 +0000133
134 // storage-class-specifier
135 case tok::kw_typedef:
136 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, PrevSpec);
137 break;
138 case tok::kw_extern:
139 if (DS.SCS_thread_specified)
140 Diag(Tok, diag::ext_thread_before, "extern");
141 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, PrevSpec);
142 break;
143 case tok::kw_static:
144 if (DS.SCS_thread_specified)
145 Diag(Tok, diag::ext_thread_before, "static");
146 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, PrevSpec);
147 break;
148 case tok::kw_auto:
149 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, PrevSpec);
150 break;
151 case tok::kw_register:
152 isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, PrevSpec);
153 break;
154 case tok::kw___thread:
155 if (DS.SCS_thread_specified)
156 isInvalid = 2, PrevSpec = "__thread";
157 else
158 DS.SCS_thread_specified = true;
159 break;
160
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000161 // type-specifiers
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000162 case tok::kw_short:
163 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
164 break;
165 case tok::kw_long:
166 if (DS.TypeSpecWidth != DeclSpec::TSW_long) {
167 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec);
168 } else {
169 DS.TypeSpecWidth = DeclSpec::TSW_unspecified;
170 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec);
171 }
172 break;
173 case tok::kw_signed:
174 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec);
175 break;
176 case tok::kw_unsigned:
177 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec);
178 break;
179 case tok::kw__Complex:
180 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec);
181 break;
182 case tok::kw__Imaginary:
183 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec);
184 break;
185 case tok::kw_void:
186 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec);
187 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000188 case tok::kw_char:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000189 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec);
190 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000191 case tok::kw_int:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000192 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec);
193 break;
194 case tok::kw_float:
195 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec);
196 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000197 case tok::kw_double:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000198 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec);
199 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000200 case tok::kw__Bool:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000201 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec);
202 break;
203 case tok::kw__Decimal32:
204 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec);
205 break;
206 case tok::kw__Decimal64:
207 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec);
208 break;
209 case tok::kw__Decimal128:
210 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000211 break;
212
213 //case tok::kw_struct:
214 //case tok::kw_union:
215 //case tok::kw_enum:
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000216
Chris Lattneracd58a32006-08-06 17:24:14 +0000217 //case tok::identifier:
218 // TODO: handle typedef names.
219
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000220 // type-qualifier
221 case tok::kw_const:
222 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
223 break;
224 case tok::kw_volatile:
225 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
226 break;
227 case tok::kw_restrict:
228 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
229 break;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000230
231 // function-specifier
232 case tok::kw_inline:
Chris Lattnerf63f89a2006-08-05 03:28:50 +0000233 // 'inline inline' is ok.
234 DS.FS_inline_specified = true;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000235 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000236 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000237 // If the specifier combination wasn't legal, issue a diagnostic.
238 if (isInvalid) {
239 assert(PrevSpec && "Method did not return previous specifier!");
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000240 if (isInvalid == 1) // Error.
241 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
242 else // extwarn.
243 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000244 }
245 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000246 }
247}
248
Chris Lattneracd58a32006-08-06 17:24:14 +0000249/// isDeclarationSpecifier() - Return true if the current token is part of a
250/// declaration specifier.
251bool Parser::isDeclarationSpecifier() const {
252 switch (Tok.getKind()) {
253 default: return false;
254 // storage-class-specifier
255 case tok::kw_typedef:
256 case tok::kw_extern:
257 case tok::kw_static:
258 case tok::kw_auto:
259 case tok::kw_register:
260 case tok::kw___thread:
261
262 // type-specifiers
263 case tok::kw_short:
264 case tok::kw_long:
265 case tok::kw_signed:
266 case tok::kw_unsigned:
267 case tok::kw__Complex:
268 case tok::kw__Imaginary:
269 case tok::kw_void:
270 case tok::kw_char:
271 case tok::kw_int:
272 case tok::kw_float:
273 case tok::kw_double:
274 case tok::kw__Bool:
275 case tok::kw__Decimal32:
276 case tok::kw__Decimal64:
277 case tok::kw__Decimal128:
278
279 // struct-or-union-specifier
280 case tok::kw_struct:
281 case tok::kw_union:
282 // enum-specifier
283 case tok::kw_enum:
284 // type-qualifier
285 case tok::kw_const:
286 case tok::kw_volatile:
287 case tok::kw_restrict:
288 // function-specifier
289 case tok::kw_inline:
290 return true;
291 // typedef-name
292 case tok::identifier:
293 // FIXME: if this is a typedef return true.
294 return false;
295 // TODO: Attributes.
296 }
297}
298
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000299
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000300/// ParseTypeQualifierListOpt
301/// type-qualifier-list: [C99 6.7.5]
302/// type-qualifier
303/// [GNU] attributes [TODO]
304/// type-qualifier-list type-qualifier
305/// [GNU] type-qualifier-list attributes [TODO]
306///
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000307void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
308 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000309 while (1) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000310 int isInvalid = false;
311 const char *PrevSpec = 0;
312
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000313 switch (Tok.getKind()) {
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000314 default:
315 // If this is not a declaration specifier token, we're done reading decl
316 // specifiers. First verify that DeclSpec's are consistent.
317 DS.Finish(StartLoc, Diags, getLang());
318 return;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000319 // TODO: attributes.
320 case tok::kw_const:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000321 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
322 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000323 case tok::kw_volatile:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000324 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
325 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000326 case tok::kw_restrict:
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000327 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000328 break;
329 }
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000330
331 // If the specifier combination wasn't legal, issue a diagnostic.
332 if (isInvalid) {
333 assert(PrevSpec && "Method did not return previous specifier!");
334 if (isInvalid == 1) // Error.
335 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
336 else // extwarn.
337 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
338 }
339 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000340 }
341}
342
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000343
344/// ParseDeclarator - Parse and verify a newly-initialized declarator.
345///
346void Parser::ParseDeclarator(Declarator &D) {
347 /// This implements the 'declarator' production in the C grammar, then checks
348 /// for well-formedness and issues diagnostics.
349 ParseDeclaratorInternal(D);
350
351 // FIXME: validate D.
Chris Lattnerbf320c82006-08-07 05:05:30 +0000352
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000353}
354
355/// ParseDeclaratorInternal
Chris Lattner6c7416c2006-08-07 00:19:33 +0000356/// declarator: [C99 6.7.5]
357/// pointer[opt] direct-declarator
358///
359/// pointer: [C99 6.7.5]
360/// '*' type-qualifier-list[opt]
361/// '*' type-qualifier-list[opt] pointer
362///
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000363void Parser::ParseDeclaratorInternal(Declarator &D) {
Chris Lattner6c7416c2006-08-07 00:19:33 +0000364 if (Tok.getKind() != tok::star)
365 return ParseDirectDeclarator(D);
366
367 // Otherwise, '*' -> pointer.
368 SourceLocation Loc = Tok.getLocation();
369 ConsumeToken(); // Eat the *.
370 DeclSpec DS;
371 ParseTypeQualifierListOpt(DS);
372
373 // Recursively parse the declarator.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000374 ParseDeclaratorInternal(D);
Chris Lattner6c7416c2006-08-07 00:19:33 +0000375
376 // Remember that we parsed a pointer type, and remember the type-quals.
377 D.AddTypeInfo(DeclaratorTypeInfo::getPointer(DS.TypeQualifiers, Loc));
378}
379
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000380
381/// ParseDirectDeclarator
382/// direct-declarator: [C99 6.7.5]
383/// identifier
384/// '(' declarator ')'
385/// [GNU] '(' attributes declarator ')'
Chris Lattnere8074e62006-08-06 18:30:15 +0000386/// [C90] direct-declarator '[' constant-expression[opt] ']'
387/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
388/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
389/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
390/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000391/// direct-declarator '(' parameter-type-list ')'
392/// direct-declarator '(' identifier-list[opt] ')'
393/// [GNU] direct-declarator '(' parameter-forward-declarations
394/// parameter-type-list[opt] ')'
395///
Chris Lattneracd58a32006-08-06 17:24:14 +0000396void Parser::ParseDirectDeclarator(Declarator &D) {
397 // Parse the first direct-declarator seen.
398 if (Tok.getKind() == tok::identifier && D.mayHaveIdentifier()) {
399 assert(Tok.getIdentifierInfo() && "Not an identifier?");
400 D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
401 ConsumeToken();
402 } else if (Tok.getKind() == tok::l_paren) {
403 // direct-declarator: '(' declarator ')'
404 // direct-declarator: '(' attributes declarator ')' [TODO]
405 // Example: 'char (*X)' or 'int (*XX)(void)'
406 ParseParenDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000407 } else if (D.mayOmitIdentifier()) {
408 // This could be something simple like "int" (in which case the declarator
409 // portion is empty), if an abstract-declarator is allowed.
410 D.SetIdentifier(0, Tok.getLocation());
411 } else {
Chris Lattnereec40f92006-08-06 21:55:29 +0000412 // Expected identifier or '('.
413 Diag(Tok, diag::err_expected_ident_lparen);
414 D.SetIdentifier(0, Tok.getLocation());
Chris Lattneracd58a32006-08-06 17:24:14 +0000415 }
416
417 assert(D.isPastIdentifier() &&
418 "Haven't past the location of the identifier yet?");
419
420 while (1) {
421 if (Tok.getKind() == tok::l_paren) {
422 ParseParenDeclarator(D);
423 } else if (Tok.getKind() == tok::l_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000424 ParseBracketDeclarator(D);
Chris Lattneracd58a32006-08-06 17:24:14 +0000425 } else {
426 break;
427 }
428 }
429}
430
431/// ParseParenDeclarator - We parsed the declarator D up to a paren. This may
432/// either be before the identifier (in which case these are just grouping
433/// parens for precedence) or it may be after the identifier, in which case
434/// these are function arguments.
435///
436/// This method also handles this portion of the grammar:
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000437/// parameter-type-list: [C99 6.7.5]
438/// parameter-list
439/// parameter-list ',' '...'
440///
441/// parameter-list: [C99 6.7.5]
442/// parameter-declaration
443/// parameter-list ',' parameter-declaration
444///
445/// parameter-declaration: [C99 6.7.5]
446/// declaration-specifiers declarator
Chris Lattneracd58a32006-08-06 17:24:14 +0000447/// [GNU] declaration-specifiers declarator attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000448/// declaration-specifiers abstract-declarator[opt]
Chris Lattneracd58a32006-08-06 17:24:14 +0000449/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO]
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000450///
451/// identifier-list: [C99 6.7.5]
452/// identifier
453/// identifier-list ',' identifier
454///
Chris Lattneracd58a32006-08-06 17:24:14 +0000455void Parser::ParseParenDeclarator(Declarator &D) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000456 SourceLocation StartLoc = Tok.getLocation();
Chris Lattneracd58a32006-08-06 17:24:14 +0000457 ConsumeParen();
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000458
Chris Lattneracd58a32006-08-06 17:24:14 +0000459 // If we haven't past the identifier yet (or where the identifier would be
460 // stored, if this is an abstract declarator), then this is probably just
461 // grouping parens.
462 if (!D.isPastIdentifier()) {
463 // Okay, this is probably a grouping paren. However, if this could be an
464 // abstract-declarator, then this could also be the start of function
465 // arguments (consider 'void()').
466 bool isGrouping;
467
468 if (!D.mayOmitIdentifier()) {
469 // If this can't be an abstract-declarator, this *must* be a grouping
470 // paren, because we haven't seen the identifier yet.
471 isGrouping = true;
472 } else if (Tok.getKind() == tok::r_paren || // 'int()' is a function.
473 isDeclarationSpecifier()) { // 'int(int)' is a function.
474
475 isGrouping = false;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000476 } else {
Chris Lattnera3507222006-08-07 00:33:37 +0000477 // Otherwise, this is a grouping paren, e.g. 'int (*X)'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000478 isGrouping = true;
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000479 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000480
481 // If this is a grouping paren, handle:
482 // direct-declarator: '(' declarator ')'
483 // direct-declarator: '(' attributes declarator ')' [TODO]
484 if (isGrouping) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000485 ParseDeclaratorInternal(D);
Chris Lattnereec40f92006-08-06 21:55:29 +0000486 if (Tok.getKind() == tok::r_paren) {
487 ConsumeParen();
488 } else {
489 // expected ')': skip until we find ')'.
490 Diag(Tok, diag::err_expected_rparen);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000491 Diag(StartLoc, diag::err_matching);
Chris Lattnereec40f92006-08-06 21:55:29 +0000492 SkipUntil(tok::r_paren);
493 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000494 return;
495 }
496
497 // Okay, if this wasn't a grouping paren, it must be the start of a function
Chris Lattnera3507222006-08-07 00:33:37 +0000498 // argument list. Recognize that this declarator will never have an
499 // identifier (and remember where it would have been), then fall through to
500 // the handling of argument lists.
Chris Lattneracd58a32006-08-06 17:24:14 +0000501 D.SetIdentifier(0, Tok.getLocation());
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000502 }
503
Chris Lattneracd58a32006-08-06 17:24:14 +0000504 // Okay, this is the parameter list of a function definition, or it is an
505 // identifier list of a K&R-style function.
506
507 // FIXME: enter function-declaration scope, limiting any declarators for
508 // arguments to the function scope.
509 // NOTE: better to only create a scope if not '()'
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000510 bool IsVariadic;
Chris Lattneracd58a32006-08-06 17:24:14 +0000511 bool HasPrototype;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000512 bool IsEmpty = false;
Chris Lattner14776b92006-08-06 22:27:40 +0000513 bool ErrorEmitted = false;
514
Chris Lattneracd58a32006-08-06 17:24:14 +0000515 if (Tok.getKind() == tok::r_paren) {
516 // int() -> no prototype, no '...'.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000517 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000518 HasPrototype = false;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000519 IsEmpty = true;
Chris Lattneracd58a32006-08-06 17:24:14 +0000520 } else if (Tok.getKind() == tok::identifier &&
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000521 1/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
Chris Lattneracd58a32006-08-06 17:24:14 +0000522 // Identifier list. Note that '(' identifier-list ')' is only allowed for
523 // normal declarators, not for abstract-declarators.
524 assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");
525
526 // If there was no identifier specified, either we are in an
527 // abstract-declarator, or we are in a parameter declarator which was found
528 // to be abstract. In abstract-declarators, identifier lists are not valid,
529 // diagnose this.
530 if (!D.getIdentifier())
531 Diag(Tok, diag::ext_ident_list_in_param);
532
533 // FIXME: Remember token.
534 ConsumeToken();
535 while (Tok.getKind() == tok::comma) {
536 // Eat the comma.
537 ConsumeToken();
538
Chris Lattner14776b92006-08-06 22:27:40 +0000539 if (Tok.getKind() != tok::identifier) {
540 // If not identifier, diagnose the error.
541 Diag(Tok, diag::err_expected_ident);
542 ErrorEmitted = true;
543 break;
544 }
Chris Lattneracd58a32006-08-06 17:24:14 +0000545
546 // Eat the id.
547 // FIXME: remember it!
548 ConsumeToken();
549 }
550
Chris Lattneracd58a32006-08-06 17:24:14 +0000551 // K&R 'prototype'.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000552 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000553 HasPrototype = false;
554 } else {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000555 IsVariadic = false;
Chris Lattneracd58a32006-08-06 17:24:14 +0000556 bool ReadArg = false;
557 // Finally, a normal, non-empty parameter type list.
558 while (1) {
559 if (Tok.getKind() == tok::ellipsis) {
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000560 IsVariadic = true;
Chris Lattneracd58a32006-08-06 17:24:14 +0000561
562 // Check to see if this is "void(...)" which is not allowed.
563 if (!ReadArg) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000564 // Otherwise, parse parameter type list. If it starts with an
565 // ellipsis, diagnose the malformed function.
Chris Lattneracd58a32006-08-06 17:24:14 +0000566 Diag(Tok, diag::err_ellipsis_first_arg);
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000567 IsVariadic = false; // Treat this like 'void()'.
Chris Lattneracd58a32006-08-06 17:24:14 +0000568 }
569
570 // Consume the ellipsis.
571 ConsumeToken();
572 break;
573 }
574
575 ReadArg = true;
576
577 // Parse the declaration-specifiers.
578 DeclSpec DS;
579 ParseDeclarationSpecifiers(DS);
580
581 // Parse the declarator. This is "PrototypeContext", because we must
582 // accept either 'declarator' or 'abstract-declarator' here.
583 Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
584 ParseDeclarator(DeclaratorInfo);
585
586 // TODO: do something with the declarator, if it is valid.
587
588 // If the next token is a comma, consume it and keep reading arguments.
589 if (Tok.getKind() != tok::comma) break;
590
591 // Consume the comma.
592 ConsumeToken();
593 }
594
595 HasPrototype = true;
596 }
597
Chris Lattnereec40f92006-08-06 21:55:29 +0000598 // FIXME: pop the scope.
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000599
600 // FIXME: capture argument info.
Chris Lattneracd58a32006-08-06 17:24:14 +0000601
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000602 // Remember that we parsed a function type, and remember the attributes.
603 D.AddTypeInfo(DeclaratorTypeInfo::getFunction(HasPrototype, IsVariadic,
Chris Lattnerfff824f2006-08-07 06:31:38 +0000604 IsEmpty, StartLoc));
Chris Lattnerd5d0a6c2006-08-07 00:58:14 +0000605
Chris Lattner14776b92006-08-06 22:27:40 +0000606
607 // If we have the closing ')', eat it and we're done.
608 if (Tok.getKind() == tok::r_paren) {
609 ConsumeParen();
610 } else {
611 // If an error happened earlier parsing something else in the proto, don't
612 // issue another error.
613 if (!ErrorEmitted)
614 Diag(Tok, diag::err_expected_rparen);
615 SkipUntil(tok::r_paren);
616 }
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000617}
Chris Lattneracd58a32006-08-06 17:24:14 +0000618
Chris Lattnere8074e62006-08-06 18:30:15 +0000619
620/// [C90] direct-declarator '[' constant-expression[opt] ']'
621/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
622/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
623/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
624/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
625void Parser::ParseBracketDeclarator(Declarator &D) {
626 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnereec40f92006-08-06 21:55:29 +0000627 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000628
629 // If valid, this location is the position where we read the 'static' keyword.
630 SourceLocation StaticLoc;
631 if (Tok.getKind() == tok::kw_static) {
632 StaticLoc = Tok.getLocation();
633 ConsumeToken();
634 }
635
636 // If there is a type-qualifier-list, read it now.
637 DeclSpec DS;
638 ParseTypeQualifierListOpt(DS);
Chris Lattnere8074e62006-08-06 18:30:15 +0000639
640 // If we haven't already read 'static', check to see if there is one after the
641 // type-qualifier-list.
642 if (!StaticLoc.isValid() && Tok.getKind() == tok::kw_static) {
643 StaticLoc = Tok.getLocation();
644 ConsumeToken();
645 }
646
647 // Handle "direct-declarator [ type-qual-list[opt] * ]".
Chris Lattnere8074e62006-08-06 18:30:15 +0000648 bool isStar = false;
Chris Lattner1906f802006-08-06 19:14:46 +0000649 if (Tok.getKind() == tok::star) {
650 // Remember the '*' token, in case we have to un-get it.
651 LexerToken StarTok = Tok;
Chris Lattnere8074e62006-08-06 18:30:15 +0000652 ConsumeToken();
Chris Lattner1906f802006-08-06 19:14:46 +0000653
654 // Check that the ']' token is present to avoid incorrectly parsing
655 // expressions starting with '*' as [*].
656 if (Tok.getKind() == tok::r_square) {
657 if (StaticLoc.isValid())
658 Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
659 StaticLoc = SourceLocation(); // Drop the static.
660 isStar = true;
Chris Lattner1906f802006-08-06 19:14:46 +0000661 } else {
662 // Otherwise, the * must have been some expression (such as '*ptr') that
663 // started an assign-expr. We already consumed the token, but now we need
664 // to reparse it.
Chris Lattnereec40f92006-08-06 21:55:29 +0000665 // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
666 // macro expansion context, so they will be read again. It is basically
667 // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
Chris Lattner1906f802006-08-06 19:14:46 +0000668 assert(0 && "FIXME: int X[*p] unimplemented");
669 }
670 }
671
Chris Lattner6c7416c2006-08-07 00:19:33 +0000672 void *NumElts = 0;
Chris Lattner1906f802006-08-06 19:14:46 +0000673 if (!isStar && Tok.getKind() != tok::r_square) {
Chris Lattnere8074e62006-08-06 18:30:15 +0000674 // Parse the assignment-expression now.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000675 NumElts = /*FIXME: parse array size expr*/0;
Chris Lattnere8074e62006-08-06 18:30:15 +0000676 assert(0 && "expr parsing not impl yet!");
677 }
678
Chris Lattnereec40f92006-08-06 21:55:29 +0000679 ConsumeBracket();
Chris Lattnere8074e62006-08-06 18:30:15 +0000680
681 // If C99 isn't enabled, emit an ext-warn if the arg list wasn't empty and if
682 // it was not a constant expression.
683 if (!getLang().C99) {
684 // TODO: check C90 array constant exprness.
Chris Lattner6c7416c2006-08-07 00:19:33 +0000685 if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
Chris Lattner8a39edc2006-08-06 18:33:32 +0000686 Diag(StartLoc, diag::ext_c99_array_usage);
Chris Lattnere8074e62006-08-06 18:30:15 +0000687 }
Chris Lattner6c7416c2006-08-07 00:19:33 +0000688
689 // Remember that we parsed a pointer type, and remember the type-quals.
690 D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
691 StaticLoc.isValid(), isStar,
692 NumElts, StartLoc));
Chris Lattnere8074e62006-08-06 18:30:15 +0000693}
694