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 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 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 54 void EnumDeclaration::setScope(Scope *sc) 55 { 56 if (semanticRun > PASSinit) 57 return; 58 ScopeDsymbol::setScope(sc); 59 } 60 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 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 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 */ 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 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 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 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 457 Type *EnumDeclaration::getType() 458 { 459 return type; 460 } 461 462 const char *EnumDeclaration::kind() const 463 { 464 return "enum"; 465 } 466 467 bool EnumDeclaration::isDeprecated() 468 { 469 return isdeprecated; 470 } 471 472 Prot EnumDeclaration::prot() 473 { 474 return protection; 475 } 476 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 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 507 Expression *&EnumMember::value() 508 { 509 return ((ExpInitializer*)_init)->exp; 510 } 511 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 520 const char *EnumMember::kind() const 521 { 522 return "enum member"; 523 } 524 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 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