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