2 // Copyright (c) 1999-2007 by Digital Mars
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
24 #include "expression.h"
27 /********************************* EnumDeclaration ****************************/
29 EnumDeclaration::EnumDeclaration(Loc loc
, Identifier
*id
, Type
*memtype
)
33 type
= new TypeEnum(this);
34 this->memtype
= memtype
;
43 Dsymbol
*EnumDeclaration::syntaxCopy(Dsymbol
*s
)
47 t
= memtype
->syntaxCopy();
51 { ed
= (EnumDeclaration
*)s
;
55 ed
= new EnumDeclaration(loc
, ident
, t
);
56 ScopeDsymbol::syntaxCopy(ed
);
60 void EnumDeclaration::semantic(Scope
*sc
)
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;
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
77 return; // semantic() already completed
80 symtab
= new DsymbolTable();
85 scx
= scope
; // save so we don't make redundant copies
91 attributes
->append(sc
->attributes
);
93 attributes
= sc
->attributes
;
95 /* The separate, and distinct, cases are:
97 * 2. enum : memtype { ... }
98 * 3. enum ident { ... }
99 * 4. enum ident : 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
);
114 scope
->module
->addDeferredSemantic(this);
115 printf("\tdeferring %s\n", toChars());
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
;
127 type
= type
->semantic(loc
, sc
);
131 { sce
= sc
->push(this);
134 if (members
->dim
== 0)
135 error("enum %s must have at least one member", toChars());
137 Expression
*elast
= NULL
;
138 for (int i
= 0; i
< members
->dim
; i
++)
140 EnumMember
*em
= ((Dsymbol
*)members
->data
[i
])->isEnumMember();
144 /* The e->semantic(sce) can insert other symbols, such as
145 * template instances and function literals.
149 //printf(" Enum member '%s'\n",em->toChars());
151 em
->type
= em
->type
->semantic(em
->loc
, sce
);
155 assert(e
->dyncast() == DYNCAST_EXPRESSION
);
156 e
= e
->semantic(sce
);
157 e
= e
->optimize(WANTvalue
| WANTinterpret
);
160 e
= e
->implicitCastTo(sce
, memtype
);
161 e
= e
->optimize(WANTvalue
| WANTinterpret
);
163 e
= e
->castTo(sce
, type
);
168 e
= e
->implicitCastTo(sce
, em
->type
);
169 e
= e
->optimize(WANTvalue
| WANTinterpret
);
170 assert(isAnonymous());
184 e
= new IntegerExp(em
->loc
, 0, Type::tint32
);
185 e
= e
->implicitCastTo(sce
, t
);
186 e
= e
->optimize(WANTvalue
| WANTinterpret
);
188 e
= e
->castTo(sce
, type
);
192 // Set value to (elast + 1).
193 // But first check that (elast != t.max)
195 e
= new EqualExp(TOKequal
, em
->loc
, elast
, t
->getProperty(0, Id::max
));
196 e
= e
->semantic(sce
);
197 e
= e
->optimize(WANTvalue
| WANTinterpret
);
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
);
210 // Add to symbol table only after evaluating 'value'
213 /* Anonymous enum members get added to enclosing scope.
215 for (Scope
*scx
= sce
; scx
; scx
= scx
->enclosing
)
219 if (!scx
->scopesym
->symtab
)
220 scx
->scopesym
->symtab
= new DsymbolTable();
221 em
->addMember(sce
, scx
->scopesym
, 1);
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
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
);
256 ec
= new CmpExp(TOKgt
, em
->loc
, e
, maxval
);
257 ec
= ec
->semantic(sce
);
258 ec
= ec
->optimize(WANTvalue
| WANTinterpret
);
265 //printf("defaultval = %lld\n", defaultval);
267 //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
273 int EnumDeclaration::oneMember(Dsymbol
**ps
)
276 return Dsymbol::oneMembers(members
, ps
);
277 return Dsymbol::oneMember(ps
);
280 void EnumDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
283 buf
->writestring("enum ");
285 { buf
->writestring(ident
->toChars());
290 buf
->writestring(": ");
291 memtype
->toCBuffer(buf
, NULL
, hgs
);
302 for (i
= 0; i
< members
->dim
; i
++)
304 EnumMember
*em
= ((Dsymbol
*)members
->data
[i
])->isEnumMember();
307 //buf->writestring(" ");
308 em
->toCBuffer(buf
, hgs
);
316 Type
*EnumDeclaration::getType()
321 char *EnumDeclaration::kind()
326 Dsymbol
*EnumDeclaration::search(Loc loc
, Identifier
*ident
, int flags
)
328 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
330 // Try one last time to resolve this enum
333 if (!members
|| !symtab
|| scope
)
334 { error("is forward referenced when looking for '%s'", ident
->toChars());
339 Dsymbol
*s
= ScopeDsymbol::search(loc
, ident
, flags
);
343 /********************************* EnumMember ****************************/
345 EnumMember::EnumMember(Loc loc
, Identifier
*id
, Expression
*value
, Type
*type
)
353 Dsymbol
*EnumMember::syntaxCopy(Dsymbol
*s
)
355 Expression
*e
= NULL
;
357 e
= value
->syntaxCopy();
361 t
= type
->syntaxCopy();
365 { em
= (EnumMember
*)s
;
371 em
= new EnumMember(loc
, ident
, e
, t
);
375 void EnumMember::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
378 type
->toCBuffer(buf
, ident
, hgs
);
380 buf
->writestring(ident
->toChars());
383 buf
->writestring(" = ");
384 value
->toCBuffer(buf
, hgs
);
388 char *EnumMember::kind()
390 return "enum member";