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