Allow implicit cast from null to maybe types ("Type?")
[delight/core.git] / dmd2 / enum.c
blobafdddaad161007bd95183271ea5ecc30b7b08e07
2 // Copyright (c) 1999-2007 by Digital Mars
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.
10 /* NOTE: This file has been patched from the original DMD distribution to
11 work with the GDC compiler.
13 Modified by David Friedman, December 2006
16 #include <stdio.h>
17 #include <assert.h>
19 #include "root.h"
20 #include "enum.h"
21 #include "mtype.h"
22 #include "scope.h"
23 #include "id.h"
24 #include "expression.h"
25 #include "module.h"
27 /********************************* EnumDeclaration ****************************/
29 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
30 : ScopeDsymbol(id)
32 this->loc = loc;
33 type = new TypeEnum(this);
34 this->memtype = memtype;
35 maxval = NULL;
36 minval = NULL;
37 defaultval = NULL;
38 sinit = NULL;
39 scope = NULL;
40 attributes = NULL;
43 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
45 Type *t = NULL;
46 if (memtype)
47 t = memtype->syntaxCopy();
49 EnumDeclaration *ed;
50 if (s)
51 { ed = (EnumDeclaration *)s;
52 ed->memtype = t;
54 else
55 ed = new EnumDeclaration(loc, ident, t);
56 ScopeDsymbol::syntaxCopy(ed);
57 return ed;
60 void EnumDeclaration::semantic(Scope *sc)
62 Type *t;
63 Scope *sce;
65 //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
66 //printf("EnumDeclaration::semantic() %s\n", toChars());
67 if (!members) // enum ident;
68 return;
70 if (!memtype && !isAnonymous())
71 { // Set memtype if we can to reduce fwd reference errors
72 memtype = Type::tint32; // case 1) enum ident { ... }
75 if (symtab) // if already done
76 { if (!scope)
77 return; // semantic() already completed
79 else
80 symtab = new DsymbolTable();
82 Scope *scx = NULL;
83 if (scope)
84 { sc = scope;
85 scx = scope; // save so we don't make redundant copies
86 scope = NULL;
89 parent = sc->parent;
90 if (attributes)
91 attributes->append(sc->attributes);
92 else
93 attributes = sc->attributes;
95 /* The separate, and distinct, cases are:
96 * 1. enum { ... }
97 * 2. enum : memtype { ... }
98 * 3. enum ident { ... }
99 * 4. enum ident : memtype { ... }
102 if (memtype)
104 memtype = memtype->semantic(loc, sc);
106 /* Check to see if memtype is forward referenced
108 if (memtype->ty == Tenum)
109 { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
110 if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
111 { // memtype is forward referenced, so try again later
112 scope = scx ? scx : new Scope(*sc);
113 scope->setNoFree();
114 scope->module->addDeferredSemantic(this);
115 printf("\tdeferring %s\n", toChars());
116 return;
119 #if 0 // Decided to abandon this restriction for D 2.0
120 if (!memtype->isintegral())
121 { error("base type must be of integral type, not %s", memtype->toChars());
122 memtype = Type::tint32;
124 #endif
127 type = type->semantic(loc, sc);
128 if (isAnonymous())
129 sce = sc;
130 else
131 { sce = sc->push(this);
132 sce->parent = this;
134 if (members->dim == 0)
135 error("enum %s must have at least one member", toChars());
136 int first = 1;
137 Expression *elast = NULL;
138 for (int i = 0; i < members->dim; i++)
140 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
141 Expression *e;
143 if (!em)
144 /* The e->semantic(sce) can insert other symbols, such as
145 * template instances and function literals.
147 continue;
149 //printf(" Enum member '%s'\n",em->toChars());
150 if (em->type)
151 em->type = em->type->semantic(em->loc, sce);
152 e = em->value;
153 if (e)
155 assert(e->dyncast() == DYNCAST_EXPRESSION);
156 e = e->semantic(sce);
157 e = e->optimize(WANTvalue | WANTinterpret);
158 if (memtype)
160 e = e->implicitCastTo(sce, memtype);
161 e = e->optimize(WANTvalue | WANTinterpret);
162 if (!isAnonymous())
163 e = e->castTo(sce, type);
164 t = memtype;
166 else if (em->type)
168 e = e->implicitCastTo(sce, em->type);
169 e = e->optimize(WANTvalue | WANTinterpret);
170 assert(isAnonymous());
171 t = e->type;
173 else
174 t = e->type;
176 else if (first)
178 if (memtype)
179 t = memtype;
180 else if (em->type)
181 t = em->type;
182 else
183 t = Type::tint32;
184 e = new IntegerExp(em->loc, 0, Type::tint32);
185 e = e->implicitCastTo(sce, t);
186 e = e->optimize(WANTvalue | WANTinterpret);
187 if (!isAnonymous())
188 e = e->castTo(sce, type);
190 else
192 // Set value to (elast + 1).
193 // But first check that (elast != t.max)
194 assert(elast);
195 e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
196 e = e->semantic(sce);
197 e = e->optimize(WANTvalue | WANTinterpret);
198 if (e->toInteger())
199 error("overflow of enum value %s", elast->toChars());
201 // Now set e to (elast + 1)
202 e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
203 e = e->semantic(sce);
204 e = e->castTo(sce, elast->type);
205 e = e->optimize(WANTvalue | WANTinterpret);
207 elast = e;
208 em->value = e;
210 // Add to symbol table only after evaluating 'value'
211 if (isAnonymous())
213 /* Anonymous enum members get added to enclosing scope.
215 for (Scope *scx = sce; scx; scx = scx->enclosing)
217 if (scx->scopesym)
219 if (!scx->scopesym->symtab)
220 scx->scopesym->symtab = new DsymbolTable();
221 em->addMember(sce, scx->scopesym, 1);
222 break;
226 else
227 em->addMember(sc, this, 1);
229 /* Compute .min, .max and .default values.
230 * If enum doesn't have a name, we can never identify the enum type,
231 * so there is no purpose for a .min, .max or .default
233 if (!isAnonymous())
235 if (first)
236 { defaultval = e;
237 minval = e;
238 maxval = e;
240 else
241 { Expression *ec;
243 /* In order to work successfully with UDTs,
244 * build expressions to do the comparisons,
245 * and let the semantic analyzer and constant
246 * folder give us the result.
249 // Compute if(e < minval)
250 ec = new CmpExp(TOKlt, em->loc, e, minval);
251 ec = ec->semantic(sce);
252 ec = ec->optimize(WANTvalue | WANTinterpret);
253 if (ec->toInteger())
254 minval = e;
256 ec = new CmpExp(TOKgt, em->loc, e, maxval);
257 ec = ec->semantic(sce);
258 ec = ec->optimize(WANTvalue | WANTinterpret);
259 if (ec->toInteger())
260 maxval = e;
263 first = 0;
265 //printf("defaultval = %lld\n", defaultval);
267 //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
268 if (sc != sce)
269 sce->pop();
270 //members->print();
273 int EnumDeclaration::oneMember(Dsymbol **ps)
275 if (isAnonymous())
276 return Dsymbol::oneMembers(members, ps);
277 return Dsymbol::oneMember(ps);
280 void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
281 { int i;
283 buf->writestring("enum ");
284 if (ident)
285 { buf->writestring(ident->toChars());
286 buf->writeByte(' ');
288 if (memtype)
290 buf->writestring(": ");
291 memtype->toCBuffer(buf, NULL, hgs);
293 if (!members)
295 buf->writeByte(';');
296 buf->writenl();
297 return;
299 buf->writenl();
300 buf->writeByte('{');
301 buf->writenl();
302 for (i = 0; i < members->dim; i++)
304 EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
305 if (!em)
306 continue;
307 //buf->writestring(" ");
308 em->toCBuffer(buf, hgs);
309 buf->writeByte(',');
310 buf->writenl();
312 buf->writeByte('}');
313 buf->writenl();
316 Type *EnumDeclaration::getType()
318 return type;
321 char *EnumDeclaration::kind()
323 return "enum";
326 Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
328 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
329 if (scope)
330 // Try one last time to resolve this enum
331 semantic(scope);
333 if (!members || !symtab || scope)
334 { error("is forward referenced when looking for '%s'", ident->toChars());
335 //*(char*)0=0;
336 return NULL;
339 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
340 return s;
343 /********************************* EnumMember ****************************/
345 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
346 : Dsymbol(id)
348 this->value = value;
349 this->type = type;
350 this->loc = loc;
353 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
355 Expression *e = NULL;
356 if (value)
357 e = value->syntaxCopy();
359 Type *t = NULL;
360 if (type)
361 t = type->syntaxCopy();
363 EnumMember *em;
364 if (s)
365 { em = (EnumMember *)s;
366 em->loc = loc;
367 em->value = e;
368 em->type = t;
370 else
371 em = new EnumMember(loc, ident, e, t);
372 return em;
375 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
377 if (type)
378 type->toCBuffer(buf, ident, hgs);
379 else
380 buf->writestring(ident->toChars());
381 if (value)
383 buf->writestring(" = ");
384 value->toCBuffer(buf, hgs);
388 char *EnumMember::kind()
390 return "enum member";