blob: 7fadb6268fccbe581cc2d684dcd30c2a83ed3973 [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 Lattner839713c2006-08-04 06:15:52 +000031/// storage-class-specifier: [C99 6.7.1] [TODO]
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'
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 Lattner839713c2006-08-04 06:15:52 +000076 DS.Finish(StartLoc, Diags, getLang());
Chris Lattnerb9093cd2006-08-04 04:39:53 +000077 return;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +000078 // type-specifiers
Chris Lattnerb9093cd2006-08-04 04:39:53 +000079 case tok::kw_short:
80 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
81 break;
82 case tok::kw_long:
83 if (DS.TypeSpecWidth != DeclSpec::TSW_long) {
84 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec);
85 } else {
86 DS.TypeSpecWidth = DeclSpec::TSW_unspecified;
87 isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec);
88 }
89 break;
90 case tok::kw_signed:
91 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec);
92 break;
93 case tok::kw_unsigned:
94 isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec);
95 break;
96 case tok::kw__Complex:
97 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec);
98 break;
99 case tok::kw__Imaginary:
100 isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec);
101 break;
102 case tok::kw_void:
103 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec);
104 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000105 case tok::kw_char:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000106 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec);
107 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000108 case tok::kw_int:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000109 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec);
110 break;
111 case tok::kw_float:
112 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec);
113 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000114 case tok::kw_double:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000115 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec);
116 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000117 case tok::kw__Bool:
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000118 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec);
119 break;
120 case tok::kw__Decimal32:
121 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec);
122 break;
123 case tok::kw__Decimal64:
124 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec);
125 break;
126 case tok::kw__Decimal128:
127 isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000128 break;
129
130 //case tok::kw_struct:
131 //case tok::kw_union:
132 //case tok::kw_enum:
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000133
134 // type-qualifier
135 case tok::kw_const:
136 isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
137 break;
138 case tok::kw_volatile:
139 isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
140 break;
141 case tok::kw_restrict:
142 isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
143 break;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000144
145 // function-specifier
146 case tok::kw_inline:
147 isInvalid = DS.SetFuncSpec(DeclSpec::FS_inline, PrevSpec);
148 break;
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000149 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000150 // If the specifier combination wasn't legal, issue a diagnostic.
151 if (isInvalid) {
152 assert(PrevSpec && "Method did not return previous specifier!");
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000153 if (isInvalid == 1) // Error.
154 Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
155 else // extwarn.
156 Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000157 }
158 ConsumeToken();
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000159 }
160}
161
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000162
Chris Lattnerc0acd3d2006-07-31 05:13:43 +0000163/// ParseDeclarator
164/// declarator: [C99 6.7.5]
165/// pointer[opt] direct-declarator
166///
167/// pointer: [C99 6.7.5]
168/// '*' type-qualifier-list[opt]
169/// '*' type-qualifier-list[opt] pointer
170///
171void Parser::ParseDeclarator() {
172 while (Tok.getKind() == tok::star) { // '*' -> pointer.
173 ConsumeToken(); // Eat the *.
174 ParseTypeQualifierListOpt();
175 }
176
177 ParseDirectDeclarator();
178}
179
180/// ParseTypeQualifierListOpt
181/// type-qualifier-list: [C99 6.7.5]
182/// type-qualifier
183/// [GNU] attributes [TODO]
184/// type-qualifier-list type-qualifier
185/// [GNU] type-qualifier-list attributes [TODO]
186///
187void Parser::ParseTypeQualifierListOpt() {
188 while (1) {
189 switch (Tok.getKind()) {
190 default: break;
191 // TODO: attributes.
192 case tok::kw_const:
193 case tok::kw_volatile:
194 case tok::kw_restrict:
195 ConsumeToken();
196 break;
197 }
198 }
199}
200
201
202/// ParseDirectDeclarator
203/// direct-declarator: [C99 6.7.5]
204/// identifier
205/// '(' declarator ')'
206/// [GNU] '(' attributes declarator ')'
207/// direct-declarator array-declarator
208/// direct-declarator '(' parameter-type-list ')'
209/// direct-declarator '(' identifier-list[opt] ')'
210/// [GNU] direct-declarator '(' parameter-forward-declarations
211/// parameter-type-list[opt] ')'
212///
213/// parameter-type-list: [C99 6.7.5]
214/// parameter-list
215/// parameter-list ',' '...'
216///
217/// parameter-list: [C99 6.7.5]
218/// parameter-declaration
219/// parameter-list ',' parameter-declaration
220///
221/// parameter-declaration: [C99 6.7.5]
222/// declaration-specifiers declarator
223/// [GNU] declaration-specifiers declarator attributes
224/// declaration-specifiers abstract-declarator[opt]
225/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
226///
227/// identifier-list: [C99 6.7.5]
228/// identifier
229/// identifier-list ',' identifier
230///
231void Parser::ParseDirectDeclarator() {
232 if (Tok.getKind() == tok::identifier) {
233 ConsumeToken();
234 return;
235 }
236 // FIXME: missing most stuff.
237 assert(0 && "Unknown token!");
238}