PR libstdc++/87308 adjust regex used in std::any pretty printer
[official-gcc.git] / gcc / d / dmd / denum.c
blob56652f219c9b055c270a2916bfd8ce7aa0072fc8
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 */
11 #include "root/dsystem.h"
12 #include "root/root.h"
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"
24 Expression *semantic(Expression *e, Scope *sc);
26 /********************************* EnumDeclaration ****************************/
28 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
29 : ScopeDsymbol(id)
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;
46 Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
48 assert(!s);
49 EnumDeclaration *ed = new EnumDeclaration(loc, ident,
50 memtype ? memtype->syntaxCopy() : NULL);
51 return ScopeDsymbol::syntaxCopy(ed);
54 void EnumDeclaration::setScope(Scope *sc)
56 if (semanticRun > PASSinit)
57 return;
58 ScopeDsymbol::setScope(sc);
61 void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
63 /* Anonymous enum members get added to enclosing scope.
65 ScopeDsymbol *scopesym = isAnonymous() ? sds : this;
67 if (!isAnonymous())
69 ScopeDsymbol::addMember(sc, sds);
71 if (!symtab)
72 symtab = new DsymbolTable();
75 if (members)
77 for (size_t i = 0; i < members->dim; i++)
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);
85 added = true;
89 void EnumDeclaration::semantic(Scope *sc)
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)
97 assert(memtype);
98 ::error(loc, "circular reference to enum base type %s", memtype->toChars());
99 errors = true;
100 semanticRun = PASSsemanticdone;
101 return;
103 unsigned dprogress_save = Module::dprogress;
105 Scope *scx = NULL;
106 if (_scope)
108 sc = _scope;
109 scx = _scope; // save so we don't make redundant copies
110 _scope = NULL;
113 parent = sc->parent;
114 type = type->semantic(loc, sc);
116 protection = sc->protection;
117 if (sc->stc & STCdeprecated)
118 isdeprecated = true;
119 userAttribDecl = sc->userAttribDecl;
121 semanticRun = PASSsemantic;
123 if (!members && !memtype) // enum ident;
125 semanticRun = PASSsemanticdone;
126 return;
129 if (!symtab)
130 symtab = new DsymbolTable();
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;
141 if (memtype)
143 memtype = memtype->semantic(loc, sc);
145 /* Check to see if memtype is forward referenced
147 if (memtype->ty == Tenum)
149 EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
150 if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
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;
162 if (memtype->ty == Tvoid)
164 error("base type must not be void");
165 memtype = Type::terror;
167 if (memtype->ty == Terror)
169 errors = true;
170 if (members)
172 for (size_t i = 0; i < members->dim; i++)
174 Dsymbol *s = (*members)[i];
175 s->errors = true; // poison all the members
178 semanticRun = PASSsemanticdone;
179 return;
183 semanticRun = PASSsemanticdone;
185 if (!members) // enum ident : memtype;
186 return;
188 if (members->dim == 0)
190 error("enum %s must have at least one member", toChars());
191 errors = true;
192 return;
195 Module::dprogress++;
197 Scope *sce;
198 if (isAnonymous())
199 sce = sc;
200 else
202 sce = sc->push(this);
203 sce->parent = this;
205 sce = sce->startCTFE();
206 sce->setNoFree(); // needed for getMaxMinValue()
208 /* Each enum member gets the sce scope
210 for (size_t i = 0; i < members->dim; i++)
212 EnumMember *em = (*members)[i]->isEnumMember();
213 if (em)
214 em->_scope = sce;
217 if (!added)
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
223 ScopeDsymbol *scopesym = NULL;
224 if (isAnonymous())
226 /* Anonymous enum members get added to enclosing scope.
228 for (Scope *sct = sce; 1; sct = sct->enclosing)
230 assert(sct);
231 if (sct->scopesym)
233 scopesym = sct->scopesym;
234 if (!sct->scopesym->symtab)
235 sct->scopesym->symtab = new DsymbolTable();
236 break;
240 else
242 // Otherwise enum members are in the EnumDeclaration's symbol table
243 scopesym = this;
246 for (size_t i = 0; i < members->dim; i++)
248 EnumMember *em = (*members)[i]->isEnumMember();
249 if (em)
251 em->ed = this;
252 em->addMember(sc, scopesym);
257 for (size_t i = 0; i < members->dim; i++)
259 EnumMember *em = (*members)[i]->isEnumMember();
260 if (em)
261 em->semantic(em->_scope);
263 //printf("defaultval = %lld\n", defaultval);
265 //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
266 //printf("members = %s\n", members->toChars());
269 /******************************
270 * Get the value of the .max/.min property as an Expression
271 * Input:
272 * id Id::max or Id::min
275 Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
277 //printf("EnumDeclaration::getMaxValue()\n");
278 bool first = true;
280 Expression **pval = (id == Id::max) ? &maxval : &minval;
282 if (inuse)
284 error(loc, "recursive definition of .%s property", id->toChars());
285 goto Lerrors;
287 if (*pval)
288 goto Ldone;
290 if (_scope)
291 semantic(_scope);
292 if (errors)
293 goto Lerrors;
294 if (semanticRun == PASSinit || !members)
296 if (isSpecial())
298 /* Allow these special enums to not need a member list
300 return memtype->getProperty(loc, id, 0);
303 error("is forward referenced looking for .%s", id->toChars());
304 goto Lerrors;
306 if (!(memtype && memtype->isintegral()))
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;
314 for (size_t i = 0; i < members->dim; i++)
316 EnumMember *em = (*members)[i]->isEnumMember();
317 if (!em)
318 continue;
319 if (em->errors)
320 goto Lerrors;
322 Expression *e = em->value();
323 if (first)
325 *pval = e;
326 first = false;
328 else
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.
336 /* Compute:
337 * if (e > maxval)
338 * maxval = e;
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;
349 Ldone:
351 Expression *e = *pval;
352 if (e->op != TOKerror)
354 e = e->copy();
355 e->loc = loc;
357 return e;
360 Lerrors:
361 *pval = new ErrorExp();
362 return *pval;
365 /****************
366 * Determine if enum is a 'special' one.
367 * Returns:
368 * true if special
370 bool EnumDeclaration::isSpecial() const
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;
379 Expression *EnumDeclaration::getDefaultValue(Loc loc)
381 //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
382 if (defaultval)
383 return defaultval;
385 if (_scope)
386 semantic(_scope);
387 if (errors)
388 goto Lerrors;
389 if (semanticRun == PASSinit || !members)
391 if (isSpecial())
393 /* Allow these special enums to not need a member list
395 return memtype->defaultInit(loc);
398 error(loc, "forward reference of %s.init", toChars());
399 goto Lerrors;
402 for (size_t i = 0; i < members->dim; i++)
404 EnumMember *em = (*members)[i]->isEnumMember();
405 if (em)
407 defaultval = em->value();
408 return defaultval;
412 Lerrors:
413 defaultval = new ErrorExp();
414 return defaultval;
417 Type *EnumDeclaration::getMemtype(Loc loc)
419 if (loc.linnum == 0)
420 loc = this->loc;
421 if (_scope)
423 /* Enum is forward referenced. We don't need to resolve the whole thing,
424 * just the base type
426 if (memtype)
427 memtype = memtype->semantic(loc, _scope);
428 else
430 if (!isAnonymous() && members)
431 memtype = Type::tint32;
434 if (!memtype)
436 if (!isAnonymous() && members)
437 memtype = Type::tint32;
438 else
440 error(loc, "is forward referenced looking for base type");
441 return Type::terror;
444 return memtype;
447 bool EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
449 if (isAnonymous())
450 return Dsymbol::oneMembers(members, ps, ident);
451 return Dsymbol::oneMember(ps, ident);
454 Type *EnumDeclaration::getType()
456 return type;
459 const char *EnumDeclaration::kind() const
461 return "enum";
464 bool EnumDeclaration::isDeprecated()
466 return isdeprecated;
469 Prot EnumDeclaration::prot()
471 return protection;
474 Dsymbol *EnumDeclaration::search(const Loc &loc, Identifier *ident, int flags)
476 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
477 if (_scope)
479 // Try one last time to resolve this enum
480 semantic(_scope);
483 if (!members || !symtab || _scope)
485 error("is forward referenced when looking for '%s'", ident->toChars());
486 //*(char*)0=0;
487 return NULL;
490 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
491 return s;
494 /********************************* EnumMember ****************************/
496 EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType)
497 : VarDeclaration(loc, NULL, id ? id : Id::empty, new ExpInitializer(loc, value))
499 this->ed = NULL;
500 this->origValue = value;
501 this->origType = origType;
504 Expression *&EnumMember::value()
506 return ((ExpInitializer*)_init)->exp;
509 Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
511 assert(!s);
512 return new EnumMember(loc, ident,
513 value() ? value()->syntaxCopy() : NULL,
514 origType ? origType->syntaxCopy() : NULL);
517 const char *EnumMember::kind() const
519 return "enum member";
522 void EnumMember::semantic(Scope *sc)
524 //printf("EnumMember::semantic() %s\n", toChars());
525 if (errors || semanticRun >= PASSsemanticdone)
526 return;
527 if (semanticRun == PASSsemantic)
529 error("circular reference to enum member");
530 Lerrors:
531 errors = true;
532 semanticRun = PASSsemanticdone;
533 return;
535 assert(ed);
536 ed->semantic(sc);
537 if (ed->errors)
538 goto Lerrors;
540 if (errors || semanticRun >= PASSsemanticdone)
541 return;
543 if (_scope)
544 sc = _scope;
545 if (!sc)
546 return;
548 semanticRun = PASSsemantic;
550 protection = ed->isAnonymous() ? ed->protection : Prot(PROTpublic);
551 linkage = LINKd;
552 storage_class = STCmanifest;
553 userAttribDecl = ed->isAnonymous() ? ed->userAttribDecl : NULL;
555 // The first enum member is special
556 bool first = (this == (*ed->members)[0]);
558 if (origType)
560 origType = origType->semantic(loc, sc);
561 type = origType;
562 assert(value()); // "type id;" is not a valid enum member declaration
565 if (value())
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())
576 ed->memtype = e->type;
577 if (ed->memtype->ty == Terror)
579 ed->errors = true;
580 goto Lerrors;
582 if (ed->memtype->ty != Terror)
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.
588 for (size_t i = 0; i < ed->members->dim; i++)
590 EnumMember *em = (*ed->members)[i]->isEnumMember();
591 if (!em || em == this || em->semanticRun < PASSsemanticdone || em->origType)
592 continue;
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;
603 if (ed->errors)
605 ed->memtype = Type::terror;
606 goto Lerrors;
611 if (ed->memtype && !origType)
613 e = e->implicitCastTo(sc, ed->memtype);
614 e = e->ctfeInterpret();
616 // save origValue for better json output
617 origValue = e;
619 if (!ed->isAnonymous())
621 e = e->castTo(sc, ed->type);
622 e = e->ctfeInterpret();
625 else if (origType)
627 e = e->implicitCastTo(sc, origType);
628 e = e->ctfeInterpret();
629 assert(ed->isAnonymous());
631 // save origValue for better json output
632 origValue = e;
634 value() = e;
636 else if (first)
638 Type *t;
639 if (ed->memtype)
640 t = ed->memtype;
641 else
643 t = Type::tint32;
644 if (!ed->isAnonymous())
645 ed->memtype = t;
647 Expression *e = new IntegerExp(loc, 0, Type::tint32);
648 e = e->implicitCastTo(sc, t);
649 e = e->ctfeInterpret();
651 // save origValue for better json output
652 origValue = e;
654 if (!ed->isAnonymous())
656 e = e->castTo(sc, ed->type);
657 e = e->ctfeInterpret();
659 value() = e;
661 else
663 /* Find the previous enum member,
664 * and set this to be the previous value + 1
666 EnumMember *emprev = NULL;
667 for (size_t i = 0; i < ed->members->dim; i++)
669 EnumMember *em = (*ed->members)[i]->isEnumMember();
670 if (em)
672 if (em == this)
673 break;
674 emprev = em;
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;
683 Expression *eprev = emprev->value();
684 Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;
686 Expression *emax = tprev->getProperty(ed->loc, Id::max, 0);
687 emax = ::semantic(emax, sc);
688 emax = emax->ctfeInterpret();
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())
698 error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
699 goto Lerrors;
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();
708 // save origValue (without cast) for better json output
709 if (e->op != TOKerror) // avoid duplicate diagnostics
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();
717 if (e->op == TOKerror)
718 goto Lerrors;
719 if (e->type->isfloating())
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())
727 error("has inexact value, due to loss of precision");
728 goto Lerrors;
731 value() = e;
733 if (!origType)
734 type = value()->type;
736 assert(origValue);
737 semanticRun = PASSsemanticdone;
740 Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
742 semantic(sc);
743 if (errors)
744 return new ErrorExp();
745 Expression *e = new VarExp(loc, this);
746 return ::semantic(e, sc);