blob: 185ac0158f257054860df2ed07f43e437819c0cd [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'
48/// [C99] '_Bool'
49/// [C99] '_Complex'
Chris Lattnerda48a8e2006-08-04 05:25:55 +000050/// [C99] '_Imaginary' // Removed in TC2?
51/// [GNU] '_Decimal32'
52/// [GNU] '_Decimal64'
53/// [GNU] '_Decimal128'
Chris Lattnerf63f89a2006-08-05 03:28:50 +000054/// [GNU] typeof-specifier [TODO]
Chris Lattnerda48a8e2006-08-04 05:25:55 +000055/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
56/// [OBJC] typedef-name objc-protocol-refs [TODO]
57/// [OBJC] objc-protocol-refs [TODO]
58/// struct-or-union-specifier [TODO]
59/// enum-specifier [TODO]
60/// typedef-name [TODO]
61/// 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
163 // type-qualifier
164 case tok::kw_const:
165 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
166 break;
167 case tok::kw_volatile:
168 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
169 break;
170 case tok::kw_restrict:
171 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
172 break;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000173
174 // function-specifier
175 case tok::kw_inline:
Chris Lattnerf63f89a2006-08-05 03:28:50 +0000176 // 'inline inline' is ok.
177 DS.FS_inline_specified = true;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000178 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000179 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000180 // If the specifier combination wasn't legal, issue a diagnostic.
181 if (isInvalid) {
182 assert(PrevSpec && "Method did not return previous specifier!");
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000183 if (isInvalid == 1) // Error.
184 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
185 else // extwarn.
186 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000187 }
188 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000189 }
190}
191
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000192
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000193/// ParseDeclarator
194/// declarator: [C99 6.7.5]
195/// pointer[opt] direct-declarator
196///
197/// pointer: [C99 6.7.5]
198/// '*' type-qualifier-list[opt]
199/// '*' type-qualifier-list[opt] pointer
200///
201void Parser::ParseDeclarator() {
202 while (Tok.getKind() == tok::star) { // '*' -> pointer.
203 ConsumeToken(); // Eat the *.
204 ParseTypeQualifierListOpt();
205 }
206
207 ParseDirectDeclarator();
208}
209
210/// ParseTypeQualifierListOpt
211/// type-qualifier-list: [C99 6.7.5]
212/// type-qualifier
213/// [GNU] attributes [TODO]
214/// type-qualifier-list type-qualifier
215/// [GNU] type-qualifier-list attributes [TODO]
216///
217void Parser::ParseTypeQualifierListOpt() {
218 while (1) {
219 switch (Tok.getKind()) {
220 default: break;
221 // TODO: attributes.
222 case tok::kw_const:
223 case tok::kw_volatile:
224 case tok::kw_restrict:
225 ConsumeToken();
226 break;
227 }
228 }
229}
230
231
232/// ParseDirectDeclarator
233/// direct-declarator: [C99 6.7.5]
234/// identifier
235/// '(' declarator ')'
236/// [GNU] '(' attributes declarator ')'
237/// direct-declarator array-declarator
238/// direct-declarator '(' parameter-type-list ')'
239/// direct-declarator '(' identifier-list[opt] ')'
240/// [GNU] direct-declarator '(' parameter-forward-declarations
241/// parameter-type-list[opt] ')'
242///
243/// parameter-type-list: [C99 6.7.5]
244/// parameter-list
245/// parameter-list ',' '...'
246///
247/// parameter-list: [C99 6.7.5]
248/// parameter-declaration
249/// parameter-list ',' parameter-declaration
250///
251/// parameter-declaration: [C99 6.7.5]
252/// declaration-specifiers declarator
253/// [GNU] declaration-specifiers declarator attributes
254/// declaration-specifiers abstract-declarator[opt]
255/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
256///
257/// identifier-list: [C99 6.7.5]
258/// identifier
259/// identifier-list ',' identifier
260///
261void Parser::ParseDirectDeclarator() {
262 if (Tok.getKind() == tok::identifier) {
263 ConsumeToken();
264 return;
265 }
266 // FIXME: missing most stuff.
267 assert(0 && "Unknown token!");
268}