1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/enum.c
9  */
10 
11 #include "root/dsystem.h"
12 #include "root/root.h"
13 
14 #include "errors.h"
15 #include "enum.h"
16 #include "mtype.h"
17 #include "scope.h"
18 #include "id.h"
19 #include "expression.h"
20 #include "module.h"
21 #include "declaration.h"
22 #include "init.h"
23 
24 Expression *semantic(Expression *e, Scope *sc);
25 
26 /********************************* EnumDeclaration ****************************/
27 
EnumDeclaration(Loc loc,Identifier * id,Type * memtype)28 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
29     : ScopeDsymbol(id)
30 {
31     //printf("EnumDeclaration() %s\n", toChars());
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     isdeprecated = false;
40     protection = Prot(PROTundefined);
41     parent = NULL;
42     added = false;
43     inuse = 0;
44 }
45 
syntaxCopy(Dsymbol * s)46 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
47 {
48     assert(!s);
49     EnumDeclaration *ed = new EnumDeclaration(loc, ident,
50         memtype ? memtype->syntaxCopy() : NULL);
51     return ScopeDsymbol::syntaxCopy(ed);
52 }
53 
setScope(Scope * sc)54 void EnumDeclaration::setScope(Scope *sc)
55 {
56     if (semanticRun > PASSinit)
57         return;
58     ScopeDsymbol::setScope(sc);
59 }
60 
addMember(Scope * sc,ScopeDsymbol * sds)61 void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
62 {
63     /* Anonymous enum members get added to enclosing scope.
64      */
65     ScopeDsymbol *scopesym = isAnonymous() ? sds : this;
66 
67     if (!isAnonymous())
68     {
69         ScopeDsymbol::addMember(sc, sds);
70 
71         if (!symtab)
72             symtab = new DsymbolTable();
73     }
74 
75     if (members)
76     {
77         for (size_t i = 0; i < members->dim; i++)
78         {
79             EnumMember *em = (*members)[i]->isEnumMember();
80             em->ed = this;
81             //printf("add %s to scope %s\n", em->toChars(), scopesym->toChars());
82             em->addMember(sc, isAnonymous() ? scopesym : this);
83         }
84     }
85     added = true;
86 }
87 
88 
semantic(Scope * sc)89 void EnumDeclaration::semantic(Scope *sc)
90 {
91     //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
92     //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
93     if (semanticRun >= PASSsemanticdone)
94         return;             // semantic() already completed
95     if (semanticRun == PASSsemantic)
96     {
97         assert(memtype);
98         ::error(loc, "circular reference to enum base type %s", memtype->toChars());
99         errors = true;
100         semanticRun = PASSsemanticdone;
101         return;
102     }
103     unsigned dprogress_save = Module::dprogress;
104 
105     Scope *scx = NULL;
106     if (_scope)
107     {
108         sc = _scope;
109         scx = _scope;            // save so we don't make redundant copies
110         _scope = NULL;
111     }
112 
113     if (!sc)
114         return;
115 
116     parent = sc->parent;
117     type = type->semantic(loc, sc);
118 
119     protection = sc->protection;
120     if (sc->stc & STCdeprecated)
121         isdeprecated = true;
122     userAttribDecl = sc->userAttribDecl;
123 
124     semanticRun = PASSsemantic;
125 
126     if (!members && !memtype)               // enum ident;
127     {
128         semanticRun = PASSsemanticdone;
129         return;
130     }
131 
132     if (!symtab)
133         symtab = new DsymbolTable();
134 
135     /* The separate, and distinct, cases are:
136      *  1. enum { ... }
137      *  2. enum : memtype { ... }
138      *  3. enum ident { ... }
139      *  4. enum ident : memtype { ... }
140      *  5. enum ident : memtype;
141      *  6. enum ident;
142      */
143 
144     if (memtype)
145     {
146         memtype = memtype->semantic(loc, sc);
147 
148         /* Check to see if memtype is forward referenced
149          */
150         if (memtype->ty == Tenum)
151         {
152             EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
153             if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
154             {
155                 // memtype is forward referenced, so try again later
156                 _scope = scx ? scx : sc->copy();
157                 _scope->setNoFree();
158                 _scope->_module->addDeferredSemantic(this);
159                 Module::dprogress = dprogress_save;
160                 //printf("\tdeferring %s\n", toChars());
161                 semanticRun = PASSinit;
162                 return;
163             }
164         }
165         if (memtype->ty == Tvoid)
166         {
167             error("base type must not be void");
168             memtype = Type::terror;
169         }
170         if (memtype->ty == Terror)
171         {
172             errors = true;
173             if (members)
174             {
175                 for (size_t i = 0; i < members->dim; i++)
176                 {
177                     Dsymbol *s = (*members)[i];
178                     s->errors = true;               // poison all the members
179                 }
180             }
181             semanticRun = PASSsemanticdone;
182             return;
183         }
184     }
185 
186     semanticRun = PASSsemanticdone;
187 
188     if (!members)               // enum ident : memtype;
189         return;
190 
191     if (members->dim == 0)
192     {
193         error("enum %s must have at least one member", toChars());
194         errors = true;
195         return;
196     }
197 
198     Module::dprogress++;
199 
200     Scope *sce;
201     if (isAnonymous())
202         sce = sc;
203     else
204     {
205         sce = sc->push(this);
206         sce->parent = this;
207     }
208     sce = sce->startCTFE();
209     sce->setNoFree();                   // needed for getMaxMinValue()
210 
211     /* Each enum member gets the sce scope
212      */
213     for (size_t i = 0; i < members->dim; i++)
214     {
215         EnumMember *em = (*members)[i]->isEnumMember();
216         if (em)
217             em->_scope = sce;
218     }
219 
220     if (!added)
221     {
222         /* addMember() is not called when the EnumDeclaration appears as a function statement,
223          * so we have to do what addMember() does and install the enum members in the right symbol
224          * table
225          */
226         ScopeDsymbol *scopesym = NULL;
227         if (isAnonymous())
228         {
229             /* Anonymous enum members get added to enclosing scope.
230              */
231             for (Scope *sct = sce; 1; sct = sct->enclosing)
232             {
233                 assert(sct);
234                 if (sct->scopesym)
235                 {
236                     scopesym = sct->scopesym;
237                     if (!sct->scopesym->symtab)
238                         sct->scopesym->symtab = new DsymbolTable();
239                     break;
240                 }
241             }
242         }
243         else
244         {
245             // Otherwise enum members are in the EnumDeclaration's symbol table
246             scopesym = this;
247         }
248 
249         for (size_t i = 0; i < members->dim; i++)
250         {
251             EnumMember *em = (*members)[i]->isEnumMember();
252             if (em)
253             {
254                 em->ed = this;
255                 em->addMember(sc, scopesym);
256             }
257         }
258     }
259 
260     for (size_t i = 0; i < members->dim; i++)
261     {
262         EnumMember *em = (*members)[i]->isEnumMember();
263         if (em)
264             em->semantic(em->_scope);
265     }
266     //printf("defaultval = %lld\n", defaultval);
267 
268     //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
269     //printf("members = %s\n", members->toChars());
270 }
271 
272 /******************************
273  * Get the value of the .max/.min property as an Expression
274  * Input:
275  *      id      Id::max or Id::min
276  */
277 
getMaxMinValue(Loc loc,Identifier * id)278 Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
279 {
280     //printf("EnumDeclaration::getMaxValue()\n");
281     bool first = true;
282 
283     Expression **pval = (id == Id::max) ? &maxval : &minval;
284 
285     if (inuse)
286     {
287         error(loc, "recursive definition of .%s property", id->toChars());
288         goto Lerrors;
289     }
290     if (*pval)
291         goto Ldone;
292 
293     if (_scope)
294         semantic(_scope);
295     if (errors)
296         goto Lerrors;
297     if (semanticRun == PASSinit || !members)
298     {
299         if (isSpecial())
300         {
301             /* Allow these special enums to not need a member list
302              */
303             return memtype->getProperty(loc, id, 0);
304         }
305 
306         error("is forward referenced looking for .%s", id->toChars());
307         goto Lerrors;
308     }
309     if (!(memtype && memtype->isintegral()))
310     {
311         error(loc, "has no .%s property because base type %s is not an integral type",
312                 id->toChars(),
313                 memtype ? memtype->toChars() : "");
314         goto Lerrors;
315     }
316 
317     for (size_t i = 0; i < members->dim; i++)
318     {
319         EnumMember *em = (*members)[i]->isEnumMember();
320         if (!em)
321             continue;
322         if (em->errors)
323             goto Lerrors;
324 
325         Expression *e = em->value();
326         if (first)
327         {
328             *pval = e;
329             first = false;
330         }
331         else
332         {
333             /* In order to work successfully with UDTs,
334              * build expressions to do the comparisons,
335              * and let the semantic analyzer and constant
336              * folder give us the result.
337              */
338 
339             /* Compute:
340              *   if (e > maxval)
341              *      maxval = e;
342              */
343             Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
344             inuse++;
345             ec = ::semantic(ec, em->_scope);
346             inuse--;
347             ec = ec->ctfeInterpret();
348             if (ec->toInteger())
349                 *pval = e;
350         }
351     }
352 Ldone:
353   {
354     Expression *e = *pval;
355     if (e->op != TOKerror)
356     {
357         e = e->copy();
358         e->loc = loc;
359     }
360     return e;
361   }
362 
363 Lerrors:
364     *pval = new ErrorExp();
365     return *pval;
366 }
367 
368 /****************
369  * Determine if enum is a 'special' one.
370  * Returns:
371  *  true if special
372  */
isSpecial()373 bool EnumDeclaration::isSpecial() const
374 {
375     return (ident == Id::__c_long ||
376             ident == Id::__c_ulong ||
377             ident == Id::__c_longlong ||
378             ident == Id::__c_ulonglong ||
379             ident == Id::__c_long_double) && memtype;
380 }
381 
getDefaultValue(Loc loc)382 Expression *EnumDeclaration::getDefaultValue(Loc loc)
383 {
384     //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
385     if (defaultval)
386         return defaultval;
387 
388     if (_scope)
389         semantic(_scope);
390     if (errors)
391         goto Lerrors;
392     if (semanticRun == PASSinit || !members)
393     {
394         if (isSpecial())
395         {
396             /* Allow these special enums to not need a member list
397              */
398             return memtype->defaultInit(loc);
399         }
400 
401         error(loc, "forward reference of %s.init", toChars());
402         goto Lerrors;
403     }
404 
405     for (size_t i = 0; i < members->dim; i++)
406     {
407         EnumMember *em = (*members)[i]->isEnumMember();
408         if (em)
409         {
410             defaultval = em->value();
411             return defaultval;
412         }
413     }
414 
415 Lerrors:
416     defaultval = new ErrorExp();
417     return defaultval;
418 }
419 
getMemtype(Loc loc)420 Type *EnumDeclaration::getMemtype(Loc loc)
421 {
422     if (loc.linnum == 0)
423         loc = this->loc;
424     if (_scope)
425     {
426         /* Enum is forward referenced. We don't need to resolve the whole thing,
427          * just the base type
428          */
429         if (memtype)
430             memtype = memtype->semantic(loc, _scope);
431         else
432         {
433             if (!isAnonymous() && members)
434                 memtype = Type::tint32;
435         }
436     }
437     if (!memtype)
438     {
439         if (!isAnonymous() && members)
440             memtype = Type::tint32;
441         else
442         {
443             error(loc, "is forward referenced looking for base type");
444             return Type::terror;
445         }
446     }
447     return memtype;
448 }
449 
oneMember(Dsymbol ** ps,Identifier * ident)450 bool EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
451 {
452     if (isAnonymous())
453         return Dsymbol::oneMembers(members, ps, ident);
454     return Dsymbol::oneMember(ps, ident);
455 }
456 
getType()457 Type *EnumDeclaration::getType()
458 {
459     return type;
460 }
461 
kind()462 const char *EnumDeclaration::kind() const
463 {
464     return "enum";
465 }
466 
isDeprecated()467 bool EnumDeclaration::isDeprecated()
468 {
469     return isdeprecated;
470 }
471 
prot()472 Prot EnumDeclaration::prot()
473 {
474     return protection;
475 }
476 
search(const Loc & loc,Identifier * ident,int flags)477 Dsymbol *EnumDeclaration::search(const Loc &loc, Identifier *ident, int flags)
478 {
479     //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
480     if (_scope)
481     {
482         // Try one last time to resolve this enum
483         semantic(_scope);
484     }
485 
486     if (!members || !symtab || _scope)
487     {
488         error("is forward referenced when looking for '%s'", ident->toChars());
489         //*(char*)0=0;
490         return NULL;
491     }
492 
493     Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
494     return s;
495 }
496 
497 /********************************* EnumMember ****************************/
498 
EnumMember(Loc loc,Identifier * id,Expression * value,Type * origType)499 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType)
500     : VarDeclaration(loc, NULL, id ? id : Id::empty, new ExpInitializer(loc, value))
501 {
502     this->ed = NULL;
503     this->origValue = value;
504     this->origType = origType;
505 }
506 
value()507 Expression *&EnumMember::value()
508 {
509     return ((ExpInitializer*)_init)->exp;
510 }
511 
syntaxCopy(Dsymbol * s)512 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
513 {
514     assert(!s);
515     return new EnumMember(loc, ident,
516         value() ? value()->syntaxCopy() : NULL,
517         origType ? origType->syntaxCopy() : NULL);
518 }
519 
kind()520 const char *EnumMember::kind() const
521 {
522     return "enum member";
523 }
524 
semantic(Scope * sc)525 void EnumMember::semantic(Scope *sc)
526 {
527     //printf("EnumMember::semantic() %s\n", toChars());
528     if (errors || semanticRun >= PASSsemanticdone)
529         return;
530     if (semanticRun == PASSsemantic)
531     {
532         error("circular reference to enum member");
533     Lerrors:
534         errors = true;
535         semanticRun = PASSsemanticdone;
536         return;
537     }
538     assert(ed);
539     ed->semantic(sc);
540     if (ed->errors)
541         goto Lerrors;
542 
543     if (errors || semanticRun >= PASSsemanticdone)
544         return;
545 
546     if (_scope)
547         sc = _scope;
548     if (!sc)
549         return;
550 
551     semanticRun = PASSsemantic;
552 
553     protection = ed->isAnonymous() ? ed->protection : Prot(PROTpublic);
554     linkage = LINKd;
555     storage_class = STCmanifest;
556     userAttribDecl = ed->isAnonymous() ? ed->userAttribDecl : NULL;
557 
558     // The first enum member is special
559     bool first = (this == (*ed->members)[0]);
560 
561     if (origType)
562     {
563         origType = origType->semantic(loc, sc);
564         type = origType;
565         assert(value());          // "type id;" is not a valid enum member declaration
566     }
567 
568     if (value())
569     {
570         Expression *e = value();
571         assert(e->dyncast() == DYNCAST_EXPRESSION);
572         e = ::semantic(e, sc);
573         e = resolveProperties(sc, e);
574         e = e->ctfeInterpret();
575         if (e->op == TOKerror)
576             goto Lerrors;
577         if (first && !ed->memtype && !ed->isAnonymous())
578         {
579             ed->memtype = e->type;
580             if (ed->memtype->ty == Terror)
581             {
582                 ed->errors = true;
583                 goto Lerrors;
584             }
585             if (ed->memtype->ty != Terror)
586             {
587                 /* Bugzilla 11746: All of named enum members should have same type
588                  * with the first member. If the following members were referenced
589                  * during the first member semantic, their types should be unified.
590                  */
591                 for (size_t i = 0; i < ed->members->dim; i++)
592                 {
593                     EnumMember *em = (*ed->members)[i]->isEnumMember();
594                     if (!em || em == this || em->semanticRun < PASSsemanticdone || em->origType)
595                         continue;
596 
597                     //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
598                     Expression *ev = em->value();
599                     ev = ev->implicitCastTo(sc, ed->memtype);
600                     ev = ev->ctfeInterpret();
601                     ev = ev->castTo(sc, ed->type);
602                     if (ev->op == TOKerror)
603                         ed->errors = true;
604                     em->value() = ev;
605                 }
606                 if (ed->errors)
607                 {
608                     ed->memtype = Type::terror;
609                     goto Lerrors;
610                 }
611             }
612         }
613 
614         if (ed->memtype && !origType)
615         {
616             e = e->implicitCastTo(sc, ed->memtype);
617             e = e->ctfeInterpret();
618 
619             // save origValue for better json output
620             origValue = e;
621 
622             if (!ed->isAnonymous())
623             {
624                 e = e->castTo(sc, ed->type);
625                 e = e->ctfeInterpret();
626             }
627         }
628         else if (origType)
629         {
630             e = e->implicitCastTo(sc, origType);
631             e = e->ctfeInterpret();
632             assert(ed->isAnonymous());
633 
634             // save origValue for better json output
635             origValue = e;
636         }
637         value() = e;
638     }
639     else if (first)
640     {
641         Type *t;
642         if (ed->memtype)
643             t = ed->memtype;
644         else
645         {
646             t = Type::tint32;
647             if (!ed->isAnonymous())
648                 ed->memtype = t;
649         }
650         Expression *e = new IntegerExp(loc, 0, Type::tint32);
651         e = e->implicitCastTo(sc, t);
652         e = e->ctfeInterpret();
653 
654         // save origValue for better json output
655         origValue = e;
656 
657         if (!ed->isAnonymous())
658         {
659             e = e->castTo(sc, ed->type);
660             e = e->ctfeInterpret();
661         }
662         value() = e;
663     }
664     else
665     {
666         /* Find the previous enum member,
667          * and set this to be the previous value + 1
668          */
669         EnumMember *emprev = NULL;
670         for (size_t i = 0; i < ed->members->dim; i++)
671         {
672             EnumMember *em = (*ed->members)[i]->isEnumMember();
673             if (em)
674             {
675                 if (em == this)
676                     break;
677                 emprev = em;
678             }
679         }
680         assert(emprev);
681         if (emprev->semanticRun < PASSsemanticdone)    // if forward reference
682             emprev->semantic(emprev->_scope);    // resolve it
683         if (emprev->errors)
684             goto Lerrors;
685 
686         Expression *eprev = emprev->value();
687         Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;
688 
689         Expression *emax = tprev->getProperty(ed->loc, Id::max, 0);
690         emax = ::semantic(emax, sc);
691         emax = emax->ctfeInterpret();
692 
693         // Set value to (eprev + 1).
694         // But first check that (eprev != emax)
695         assert(eprev);
696         Expression *e = new EqualExp(TOKequal, loc, eprev, emax);
697         e = ::semantic(e, sc);
698         e = e->ctfeInterpret();
699         if (e->toInteger())
700         {
701             error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
702             goto Lerrors;
703         }
704 
705         // Now set e to (eprev + 1)
706         e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32));
707         e = ::semantic(e, sc);
708         e = e->castTo(sc, eprev->type);
709         e = e->ctfeInterpret();
710 
711         // save origValue (without cast) for better json output
712         if (e->op != TOKerror)  // avoid duplicate diagnostics
713         {
714             assert(emprev->origValue);
715             origValue = new AddExp(loc, emprev->origValue, new IntegerExp(loc, 1, Type::tint32));
716             origValue = ::semantic(origValue, sc);
717             origValue = origValue->ctfeInterpret();
718         }
719 
720         if (e->op == TOKerror)
721             goto Lerrors;
722         if (e->type->isfloating())
723         {
724             // Check that e != eprev (not always true for floats)
725             Expression *etest = new EqualExp(TOKequal, loc, e, eprev);
726             etest = ::semantic(etest, sc);
727             etest = etest->ctfeInterpret();
728             if (etest->toInteger())
729             {
730                 error("has inexact value, due to loss of precision");
731                 goto Lerrors;
732             }
733         }
734         value() = e;
735     }
736     if (!origType)
737         type = value()->type;
738 
739     assert(origValue);
740     semanticRun = PASSsemanticdone;
741 }
742 
getVarExp(Loc loc,Scope * sc)743 Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
744 {
745     semantic(sc);
746     if (errors)
747         return new ErrorExp();
748     Expression *e = new VarExp(loc, this);
749     return ::semantic(e, sc);
750 }
751