blob: eb30033ff907eb61aba2b7e681161195a14cda4d [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 Lattnerda48a8e2006-08-04 05:25:55 +000031/// storage-class-specifier: [C99 6.7.1]
32/// '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'
54/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
55/// [OBJC] typedef-name objc-protocol-refs [TODO]
56/// [OBJC] objc-protocol-refs [TODO]
57/// struct-or-union-specifier [TODO]
58/// enum-specifier [TODO]
59/// typedef-name [TODO]
60/// type-qualifier:
61/// const
62/// volatile
63/// [C99] restrict
Chris Lattnerb9093cd2006-08-04 04:39:53 +000064/// function-specifier: [C99 6.7.4]
65/// [C99] inline
66///
67void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
68 SourceLocation StartLoc = Tok.getLocation();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000069 while (1) {
Chris Lattnerda48a8e2006-08-04 05:25:55 +000070 int isInvalid = false;
Chris Lattnerb9093cd2006-08-04 04:39:53 +000071 const char *PrevSpec = 0;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000072 switch (Tok.getKind()) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +000073 default:
74 // If this is not a declaration specifier token, we're done reading decl
75 // specifiers. First verify that DeclSpec's are consistent.
Chris Lattnerda48a8e2006-08-04 05:25:55 +000076 diag::kind Res = DS.Finish(getLang());
Chris Lattnerb9093cd2006-08-04 04:39:53 +000077 if (Res != diag::NUM_DIAGNOSTICS)
78 Diag(StartLoc, Res);
79 return;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000080 // type-specifiers
Chris Lattnerb9093cd2006-08-04 04:39:53 +000081 case tok::kw_short:
82 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
83 break;
84 case tok::kw_long:
85 if (DS.TypeSpecWidth != DeclSpec::TSW_long) {
86 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec);
87 } else {
88 DS.TypeSpecWidth = DeclSpec::TSW_unspecified;
89 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec);
90 }
91 break;
92 case tok::kw_signed:
93 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec);
94 break;
95 case tok::kw_unsigned:
96 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec);
97 break;
98 case tok::kw__Complex:
99 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec);
100 break;
101 case tok::kw__Imaginary:
102 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec);
103 break;
104 case tok::kw_void:
105 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec);
106 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000107 case tok::kw_char:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000108 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec);
109 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000110 case tok::kw_int:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000111 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec);
112 break;
113 case tok::kw_float:
114 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec);
115 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000116 case tok::kw_double:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000117 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec);
118 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000119 case tok::kw__Bool:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000120 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec);
121 break;
122 case tok::kw__Decimal32:
123 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec);
124 break;
125 case tok::kw__Decimal64:
126 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec);
127 break;
128 case tok::kw__Decimal128:
129 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000130 break;
131
132 //case tok::kw_struct:
133 //case tok::kw_union:
134 //case tok::kw_enum:
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000135
136 // type-qualifier
137 case tok::kw_const:
138 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
139 break;
140 case tok::kw_volatile:
141 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
142 break;
143 case tok::kw_restrict:
144 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
145 break;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000146
147 // function-specifier
148 case tok::kw_inline:
149 isInvalid = DS.SetFuncSpec(DeclSpec::FS_inline, PrevSpec);
150 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000151 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000152 // If the specifier combination wasn't legal, issue a diagnostic.
153 if (isInvalid) {
154 assert(PrevSpec && "Method did not return previous specifier!");
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000155 if (isInvalid == 1) // Error.
156 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
157 else // extwarn.
158 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000159 }
160 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000161 }
162}
163
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000164
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000165/// ParseDeclarator
166/// declarator: [C99 6.7.5]
167/// pointer[opt] direct-declarator
168///
169/// pointer: [C99 6.7.5]
170/// '*' type-qualifier-list[opt]
171/// '*' type-qualifier-list[opt] pointer
172///
173void Parser::ParseDeclarator() {
174 while (Tok.getKind() == tok::star) { // '*' -> pointer.
175 ConsumeToken(); // Eat the *.
176 ParseTypeQualifierListOpt();
177 }
178
179 ParseDirectDeclarator();
180}
181
182/// ParseTypeQualifierListOpt
183/// type-qualifier-list: [C99 6.7.5]
184/// type-qualifier
185/// [GNU] attributes [TODO]
186/// type-qualifier-list type-qualifier
187/// [GNU] type-qualifier-list attributes [TODO]
188///
189void Parser::ParseTypeQualifierListOpt() {
190 while (1) {
191 switch (Tok.getKind()) {
192 default: break;
193 // TODO: attributes.
194 case tok::kw_const:
195 case tok::kw_volatile:
196 case tok::kw_restrict:
197 ConsumeToken();
198 break;
199 }
200 }
201}
202
203
204/// ParseDirectDeclarator
205/// direct-declarator: [C99 6.7.5]
206/// identifier
207/// '(' declarator ')'
208/// [GNU] '(' attributes declarator ')'
209/// direct-declarator array-declarator
210/// direct-declarator '(' parameter-type-list ')'
211/// direct-declarator '(' identifier-list[opt] ')'
212/// [GNU] direct-declarator '(' parameter-forward-declarations
213/// parameter-type-list[opt] ')'
214///
215/// parameter-type-list: [C99 6.7.5]
216/// parameter-list
217/// parameter-list ',' '...'
218///
219/// parameter-list: [C99 6.7.5]
220/// parameter-declaration
221/// parameter-list ',' parameter-declaration
222///
223/// parameter-declaration: [C99 6.7.5]
224/// declaration-specifiers declarator
225/// [GNU] declaration-specifiers declarator attributes
226/// declaration-specifiers abstract-declarator[opt]
227/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
228///
229/// identifier-list: [C99 6.7.5]
230/// identifier
231/// identifier-list ',' identifier
232///
233void Parser::ParseDirectDeclarator() {
234 if (Tok.getKind() == tok::identifier) {
235 ConsumeToken();
236 return;
237 }
238 // FIXME: missing most stuff.
239 assert(0 && "Unknown token!");
240}