Mercurial > projects > ldc
annotate dmd/enum.c @ 1168:ab186e535e72
A different fix to #218 and DMD2682 that does not lead to constant folding regressions.
Fixes run/const_15, run/c/const_16_B.
The price is removing the lvalueness of struct literals. If it turns out too
much code depends on this behavior or we don't want to break with DMD, we
could keep struct literals as lvalues and instead convert struct literals used
as expression initializers into struct initializers.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sun, 29 Mar 2009 11:43:45 +0200 |
parents | 1860414bf3b7 |
children | e961851fb8be |
rev | line source |
---|---|
1 | 1 |
336 | 2 // Copyright (c) 1999-2008 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 |