Mercurial > projects > ldc
annotate dmd/enum.c @ 1582:d8e558087001
Fixed a segfault in ldc2 when compiling synchronized{} blocks.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 19 Sep 2009 13:05:10 +0100 |
parents | e961851fb8be |
children | 1b24e9c7cc26 |
rev | line source |
---|---|
1 | 1 |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1146
diff
changeset
|
2 // Copyright (c) 1999-2009 by Digital Mars |
1 | 3 // All Rights Reserved |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include <stdio.h> | |
11 #include <assert.h> | |
12 | |
13 #include "root.h" | |
14 #include "enum.h" | |
15 #include "mtype.h" | |
16 #include "scope.h" | |
336 | 17 #include "declaration.h" |
1 | 18 |
19 /********************************* EnumDeclaration ****************************/ | |
20 | |
21 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype) | |
22 : ScopeDsymbol(id) | |
23 { | |
24 this->loc = loc; | |
25 type = new TypeEnum(this); | |
26 this->memtype = memtype; | |
27 maxval = 0; | |
28 minval = 0; | |
29 defaultval = 0; | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
30 #if IN_DMD |
1 | 31 sinit = NULL; |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
32 #endif |
336 | 33 isdeprecated = 0; |
1 | 34 } |
35 | |
36 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) | |
37 { | |
38 Type *t = NULL; | |
39 if (memtype) | |
40 t = memtype->syntaxCopy(); | |
41 | |
42 EnumDeclaration *ed; | |
43 if (s) | |
44 { ed = (EnumDeclaration *)s; | |
45 ed->memtype = t; | |
46 } | |
47 else | |
48 ed = new EnumDeclaration(loc, ident, t); | |
49 ScopeDsymbol::syntaxCopy(ed); | |
50 return ed; | |
51 } | |
52 | |
53 void EnumDeclaration::semantic(Scope *sc) | |
54 { int i; | |
55 uinteger_t number; | |
56 Type *t; | |
57 Scope *sce; | |
58 | |
59 //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars()); | |
60 if (symtab) // if already done | |
61 return; | |
62 if (!memtype) | |
63 memtype = Type::tint32; | |
336 | 64 if (sc->stc & STCdeprecated) |
65 isdeprecated = 1; | |
66 | |
1 | 67 parent = sc->scopesym; |
68 memtype = memtype->semantic(loc, sc); | |
69 | |
70 /* Check to see if memtype is forward referenced | |
71 */ | |
72 if (memtype->ty == Tenum) | |
73 { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc); | |
74 if (!sym->memtype) | |
75 { | |
76 error("base enum %s is forward referenced", sym->toChars()); | |
77 memtype = Type::tint32; | |
78 } | |
79 } | |
80 | |
81 if (!memtype->isintegral()) | |
82 { error("base type must be of integral type, not %s", memtype->toChars()); | |
83 memtype = Type::tint32; | |
84 } | |
85 | |
86 t = isAnonymous() ? memtype : type; | |
87 symtab = new DsymbolTable(); | |
88 sce = sc->push(this); | |
89 sce->parent = this; | |
90 number = 0; | |
91 if (!members) // enum ident; | |
92 return; | |
93 if (members->dim == 0) | |
94 error("enum %s must have at least one member", toChars()); | |
95 int first = 1; | |
96 for (i = 0; i < members->dim; i++) | |
97 { | |
98 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); | |
99 Expression *e; | |
100 | |
101 if (!em) | |
102 /* The e->semantic(sce) can insert other symbols, such as | |
103 * template instances and function literals. | |
104 */ | |
105 continue; | |
106 | |
107 //printf("Enum member '%s'\n",em->toChars()); | |
108 e = em->value; | |
109 if (e) | |
110 { | |
111 assert(e->dyncast() == DYNCAST_EXPRESSION); | |
112 e = e->semantic(sce); | |
113 e = e->optimize(WANTvalue); | |
114 // Need to copy it because we're going to change the type | |
115 e = e->copy(); | |
116 e = e->implicitCastTo(sc, memtype); | |
117 e = e->optimize(WANTvalue); | |
118 number = e->toInteger(); | |
119 e->type = t; | |
120 } | |
121 else | |
122 { // Default is the previous number plus 1 | |
123 | |
124 // Check for overflow | |
125 if (!first) | |
126 { | |
127 switch (t->toBasetype()->ty) | |
128 { | |
129 case Tbool: | |
130 if (number == 2) goto Loverflow; | |
131 break; | |
132 | |
133 case Tint8: | |
134 if (number == 128) goto Loverflow; | |
135 break; | |
136 | |
137 case Tchar: | |
138 case Tuns8: | |
139 if (number == 256) goto Loverflow; | |
140 break; | |
141 | |
142 case Tint16: | |
143 if (number == 0x8000) goto Loverflow; | |
144 break; | |
145 | |
146 case Twchar: | |
147 case Tuns16: | |
148 if (number == 0x10000) goto Loverflow; | |
149 break; | |
150 | |
151 case Tint32: | |
152 if (number == 0x80000000) goto Loverflow; | |
153 break; | |
154 | |
155 case Tdchar: | |
156 case Tuns32: | |
157 if (number == 0x100000000LL) goto Loverflow; | |
158 break; | |
159 | |
160 case Tint64: | |
161 if (number == 0x8000000000000000LL) goto Loverflow; | |
162 break; | |
163 | |
164 case Tuns64: | |
165 if (number == 0) goto Loverflow; | |
166 break; | |
167 | |
168 Loverflow: | |
169 error("overflow of enum value"); | |
170 break; | |
171 | |
172 default: | |
173 assert(0); | |
174 } | |
175 } | |
176 e = new IntegerExp(em->loc, number, t); | |
177 } | |
178 em->value = e; | |
179 | |
180 // Add to symbol table only after evaluating 'value' | |
181 if (isAnonymous()) | |
182 { | |
183 //sce->enclosing->insert(em); | |
184 for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing) | |
185 { | |
186 if (scx->scopesym) | |
187 { | |
188 if (!scx->scopesym->symtab) | |
189 scx->scopesym->symtab = new DsymbolTable(); | |
190 em->addMember(sce, scx->scopesym, 1); | |
191 break; | |
192 } | |
193 } | |
194 } | |
195 else | |
196 em->addMember(sc, this, 1); | |
197 | |
198 if (first) | |
199 { first = 0; | |
200 defaultval = number; | |
201 minval = number; | |
202 maxval = number; | |
203 } | |
204 else if (memtype->isunsigned()) | |
205 { | |
206 if (number < minval) | |
207 minval = number; | |
208 if (number > maxval) | |
209 maxval = number; | |
210 } | |
211 else | |
212 { | |
213 if ((sinteger_t)number < (sinteger_t)minval) | |
214 minval = number; | |
215 if ((sinteger_t)number > (sinteger_t)maxval) | |
216 maxval = number; | |
217 } | |
218 | |
219 number++; | |
220 } | |
221 //printf("defaultval = %lld\n", defaultval); | |
222 | |
223 sce->pop(); | |
224 //members->print(); | |
225 } | |
226 | |
227 int EnumDeclaration::oneMember(Dsymbol **ps) | |
228 { | |
229 if (isAnonymous()) | |
230 return Dsymbol::oneMembers(members, ps); | |
231 return Dsymbol::oneMember(ps); | |
232 } | |
233 | |
234 void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
235 { int i; | |
236 | |
237 buf->writestring("enum "); | |
238 if (ident) | |
239 { buf->writestring(ident->toChars()); | |
240 buf->writeByte(' '); | |
241 } | |
242 if (memtype) | |
243 { | |
244 buf->writestring(": "); | |
245 memtype->toCBuffer(buf, NULL, hgs); | |
246 } | |
247 if (!members) | |
248 { | |
249 buf->writeByte(';'); | |
250 buf->writenl(); | |
251 return; | |
252 } | |
253 buf->writenl(); | |
254 buf->writeByte('{'); | |
255 buf->writenl(); | |
256 for (i = 0; i < members->dim; i++) | |
257 { | |
258 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); | |
259 if (!em) | |
260 continue; | |
261 //buf->writestring(" "); | |
262 em->toCBuffer(buf, hgs); | |
263 buf->writeByte(','); | |
264 buf->writenl(); | |
265 } | |
266 buf->writeByte('}'); | |
267 buf->writenl(); | |
268 } | |
269 | |
270 Type *EnumDeclaration::getType() | |
271 { | |
272 return type; | |
273 } | |
274 | |
336 | 275 const char *EnumDeclaration::kind() |
1 | 276 { |
277 return "enum"; | |
278 } | |
279 | |
336 | 280 int EnumDeclaration::isDeprecated() |
281 { | |
282 return isdeprecated; | |
283 } | |
284 | |
1 | 285 /********************************* EnumMember ****************************/ |
286 | |
287 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value) | |
288 : Dsymbol(id) | |
289 { | |
290 this->value = value; | |
291 this->loc = loc; | |
292 } | |
293 | |
294 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s) | |
295 { | |
296 Expression *e = NULL; | |
297 if (value) | |
298 e = value->syntaxCopy(); | |
299 | |
300 EnumMember *em; | |
301 if (s) | |
302 { em = (EnumMember *)s; | |
303 em->loc = loc; | |
304 em->value = e; | |
305 } | |
306 else | |
307 em = new EnumMember(loc, ident, e); | |
308 return em; | |
309 } | |
310 | |
311 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
312 { | |
313 buf->writestring(ident->toChars()); | |
314 if (value) | |
315 { | |
316 buf->writestring(" = "); | |
317 value->toCBuffer(buf, hgs); | |
318 } | |
319 } | |
320 | |
336 | 321 const char *EnumMember::kind() |
1 | 322 { |
323 return "enum member"; | |
324 } | |
325 | |
326 |