aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/denum.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/denum.c')
-rw-r--r--gcc/d/dmd/denum.c431
1 files changed, 9 insertions, 422 deletions
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index d15d94a..ca1d3bb 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -1,6 +1,6 @@
/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
@@ -22,8 +22,6 @@
#include "declaration.h"
#include "init.h"
-Expression *semantic(Expression *e, Scope *sc);
-
/********************************* EnumDeclaration ****************************/
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
@@ -86,190 +84,6 @@ void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
added = true;
}
-
-void EnumDeclaration::semantic(Scope *sc)
-{
- //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
- //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
- if (semanticRun >= PASSsemanticdone)
- return; // semantic() already completed
- if (semanticRun == PASSsemantic)
- {
- assert(memtype);
- ::error(loc, "circular reference to enum base type %s", memtype->toChars());
- errors = true;
- semanticRun = PASSsemanticdone;
- return;
- }
- unsigned dprogress_save = Module::dprogress;
-
- Scope *scx = NULL;
- if (_scope)
- {
- sc = _scope;
- scx = _scope; // save so we don't make redundant copies
- _scope = NULL;
- }
-
- if (!sc)
- return;
-
- parent = sc->parent;
- type = type->semantic(loc, sc);
-
- protection = sc->protection;
- if (sc->stc & STCdeprecated)
- isdeprecated = true;
- userAttribDecl = sc->userAttribDecl;
-
- semanticRun = PASSsemantic;
-
- if (!members && !memtype) // enum ident;
- {
- semanticRun = PASSsemanticdone;
- return;
- }
-
- if (!symtab)
- symtab = new DsymbolTable();
-
- /* The separate, and distinct, cases are:
- * 1. enum { ... }
- * 2. enum : memtype { ... }
- * 3. enum ident { ... }
- * 4. enum ident : memtype { ... }
- * 5. enum ident : memtype;
- * 6. enum ident;
- */
-
- if (memtype)
- {
- memtype = memtype->semantic(loc, sc);
-
- /* Check to see if memtype is forward referenced
- */
- if (memtype->ty == Tenum)
- {
- EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
- if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
- {
- // memtype is forward referenced, so try again later
- _scope = scx ? scx : sc->copy();
- _scope->setNoFree();
- _scope->_module->addDeferredSemantic(this);
- Module::dprogress = dprogress_save;
- //printf("\tdeferring %s\n", toChars());
- semanticRun = PASSinit;
- return;
- }
- }
- if (memtype->ty == Tvoid)
- {
- error("base type must not be void");
- memtype = Type::terror;
- }
- if (memtype->ty == Terror)
- {
- errors = true;
- if (members)
- {
- for (size_t i = 0; i < members->length; i++)
- {
- Dsymbol *s = (*members)[i];
- s->errors = true; // poison all the members
- }
- }
- semanticRun = PASSsemanticdone;
- return;
- }
- }
-
- semanticRun = PASSsemanticdone;
-
- if (!members) // enum ident : memtype;
- return;
-
- if (members->length == 0)
- {
- error("enum %s must have at least one member", toChars());
- errors = true;
- return;
- }
-
- Module::dprogress++;
-
- Scope *sce;
- if (isAnonymous())
- sce = sc;
- else
- {
- sce = sc->push(this);
- sce->parent = this;
- }
- sce = sce->startCTFE();
- sce->setNoFree(); // needed for getMaxMinValue()
-
- /* Each enum member gets the sce scope
- */
- for (size_t i = 0; i < members->length; i++)
- {
- EnumMember *em = (*members)[i]->isEnumMember();
- if (em)
- em->_scope = sce;
- }
-
- if (!added)
- {
- /* addMember() is not called when the EnumDeclaration appears as a function statement,
- * so we have to do what addMember() does and install the enum members in the right symbol
- * table
- */
- ScopeDsymbol *scopesym = NULL;
- if (isAnonymous())
- {
- /* Anonymous enum members get added to enclosing scope.
- */
- for (Scope *sct = sce; 1; sct = sct->enclosing)
- {
- assert(sct);
- if (sct->scopesym)
- {
- scopesym = sct->scopesym;
- if (!sct->scopesym->symtab)
- sct->scopesym->symtab = new DsymbolTable();
- break;
- }
- }
- }
- else
- {
- // Otherwise enum members are in the EnumDeclaration's symbol table
- scopesym = this;
- }
-
- for (size_t i = 0; i < members->length; i++)
- {
- EnumMember *em = (*members)[i]->isEnumMember();
- if (em)
- {
- em->ed = this;
- em->addMember(sc, scopesym);
- }
- }
- }
-
- for (size_t i = 0; i < members->length; i++)
- {
- EnumMember *em = (*members)[i]->isEnumMember();
- if (em)
- em->semantic(em->_scope);
- }
- //printf("defaultval = %lld\n", defaultval);
-
- //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
- //printf("members = %s\n", members->toChars());
-}
-
/******************************
* Get the value of the .max/.min property as an Expression
* Input:
@@ -292,7 +106,7 @@ Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
goto Ldone;
if (_scope)
- semantic(_scope);
+ dsymbolSemantic(this, _scope);
if (errors)
goto Lerrors;
if (semanticRun == PASSinit || !members)
@@ -343,7 +157,7 @@ Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
*/
Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
inuse++;
- ec = ::semantic(ec, em->_scope);
+ ec = expressionSemantic(ec, em->_scope);
inuse--;
ec = ec->ctfeInterpret();
if (ec->toInteger())
@@ -387,7 +201,7 @@ Expression *EnumDeclaration::getDefaultValue(Loc loc)
return defaultval;
if (_scope)
- semantic(_scope);
+ dsymbolSemantic(this, _scope);
if (errors)
goto Lerrors;
if (semanticRun == PASSinit || !members)
@@ -428,7 +242,7 @@ Type *EnumDeclaration::getMemtype(Loc loc)
* just the base type
*/
if (memtype)
- memtype = memtype->semantic(loc, _scope);
+ memtype = typeSemantic(memtype, loc, _scope);
else
{
if (!isAnonymous() && members)
@@ -481,12 +295,12 @@ Dsymbol *EnumDeclaration::search(const Loc &loc, Identifier *ident, int flags)
if (_scope)
{
// Try one last time to resolve this enum
- semantic(_scope);
+ dsymbolSemantic(this, _scope);
}
if (!members || !symtab || _scope)
{
- error("is forward referenced when looking for '%s'", ident->toChars());
+ error("is forward referenced when looking for `%s`", ident->toChars());
//*(char*)0=0;
return NULL;
}
@@ -535,236 +349,9 @@ const char *EnumMember::kind() const
return "enum member";
}
-void EnumMember::semantic(Scope *sc)
-{
- //printf("EnumMember::semantic() %s\n", toChars());
- if (errors || semanticRun >= PASSsemanticdone)
- return;
- if (semanticRun == PASSsemantic)
- {
- error("circular reference to enum member");
- Lerrors:
- errors = true;
- semanticRun = PASSsemanticdone;
- return;
- }
- assert(ed);
-
- ed->semantic(sc);
- if (ed->errors)
- goto Lerrors;
-
- if (errors || semanticRun >= PASSsemanticdone)
- return;
-
- if (_scope)
- sc = _scope;
- if (!sc)
- return;
-
- semanticRun = PASSsemantic;
-
- protection = ed->isAnonymous() ? ed->protection : Prot(Prot::public_);
- linkage = LINKd;
- storage_class |= STCmanifest;
-
- // https://issues.dlang.org/show_bug.cgi?id=9701
- if (ed->isAnonymous())
- {
- if (userAttribDecl)
- userAttribDecl->userAttribDecl = ed->userAttribDecl;
- else
- userAttribDecl = ed->userAttribDecl;
- }
-
- // The first enum member is special
- bool first = (this == (*ed->members)[0]);
-
- if (origType)
- {
- origType = origType->semantic(loc, sc);
- type = origType;
- assert(value()); // "type id;" is not a valid enum member declaration
- }
-
- if (value())
- {
- Expression *e = value();
- assert(e->dyncast() == DYNCAST_EXPRESSION);
- e = ::semantic(e, sc);
- e = resolveProperties(sc, e);
- e = e->ctfeInterpret();
- if (e->op == TOKerror)
- goto Lerrors;
- if (first && !ed->memtype && !ed->isAnonymous())
- {
- ed->memtype = e->type;
- if (ed->memtype->ty == Terror)
- {
- ed->errors = true;
- goto Lerrors;
- }
- if (ed->memtype->ty != Terror)
- {
- /* Bugzilla 11746: All of named enum members should have same type
- * with the first member. If the following members were referenced
- * during the first member semantic, their types should be unified.
- */
- for (size_t i = 0; i < ed->members->length; i++)
- {
- EnumMember *em = (*ed->members)[i]->isEnumMember();
- if (!em || em == this || em->semanticRun < PASSsemanticdone || em->origType)
- continue;
-
- //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
- Expression *ev = em->value();
- ev = ev->implicitCastTo(sc, ed->memtype);
- ev = ev->ctfeInterpret();
- ev = ev->castTo(sc, ed->type);
- if (ev->op == TOKerror)
- ed->errors = true;
- em->value() = ev;
- }
- if (ed->errors)
- {
- ed->memtype = Type::terror;
- goto Lerrors;
- }
- }
- }
-
- if (ed->memtype && !origType)
- {
- e = e->implicitCastTo(sc, ed->memtype);
- e = e->ctfeInterpret();
-
- // save origValue for better json output
- origValue = e;
-
- if (!ed->isAnonymous())
- {
- e = e->castTo(sc, ed->type);
- e = e->ctfeInterpret();
- }
- }
- else if (origType)
- {
- e = e->implicitCastTo(sc, origType);
- e = e->ctfeInterpret();
- assert(ed->isAnonymous());
-
- // save origValue for better json output
- origValue = e;
- }
- value() = e;
- }
- else if (first)
- {
- Type *t;
- if (ed->memtype)
- t = ed->memtype;
- else
- {
- t = Type::tint32;
- if (!ed->isAnonymous())
- ed->memtype = t;
- }
- Expression *e = new IntegerExp(loc, 0, Type::tint32);
- e = e->implicitCastTo(sc, t);
- e = e->ctfeInterpret();
-
- // save origValue for better json output
- origValue = e;
-
- if (!ed->isAnonymous())
- {
- e = e->castTo(sc, ed->type);
- e = e->ctfeInterpret();
- }
- value() = e;
- }
- else
- {
- /* Find the previous enum member,
- * and set this to be the previous value + 1
- */
- EnumMember *emprev = NULL;
- for (size_t i = 0; i < ed->members->length; i++)
- {
- EnumMember *em = (*ed->members)[i]->isEnumMember();
- if (em)
- {
- if (em == this)
- break;
- emprev = em;
- }
- }
- assert(emprev);
- if (emprev->semanticRun < PASSsemanticdone) // if forward reference
- emprev->semantic(emprev->_scope); // resolve it
- if (emprev->errors)
- goto Lerrors;
-
- Expression *eprev = emprev->value();
- Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;
-
- Expression *emax = tprev->getProperty(ed->loc, Id::max, 0);
- emax = ::semantic(emax, sc);
- emax = emax->ctfeInterpret();
-
- // Set value to (eprev + 1).
- // But first check that (eprev != emax)
- assert(eprev);
- Expression *e = new EqualExp(TOKequal, loc, eprev, emax);
- e = ::semantic(e, sc);
- e = e->ctfeInterpret();
- if (e->toInteger())
- {
- error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
- goto Lerrors;
- }
-
- // Now set e to (eprev + 1)
- e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32));
- e = ::semantic(e, sc);
- e = e->castTo(sc, eprev->type);
- e = e->ctfeInterpret();
-
- // save origValue (without cast) for better json output
- if (e->op != TOKerror) // avoid duplicate diagnostics
- {
- assert(emprev->origValue);
- origValue = new AddExp(loc, emprev->origValue, new IntegerExp(loc, 1, Type::tint32));
- origValue = ::semantic(origValue, sc);
- origValue = origValue->ctfeInterpret();
- }
-
- if (e->op == TOKerror)
- goto Lerrors;
- if (e->type->isfloating())
- {
- // Check that e != eprev (not always true for floats)
- Expression *etest = new EqualExp(TOKequal, loc, e, eprev);
- etest = ::semantic(etest, sc);
- etest = etest->ctfeInterpret();
- if (etest->toInteger())
- {
- error("has inexact value, due to loss of precision");
- goto Lerrors;
- }
- }
- value() = e;
- }
- if (!origType)
- type = value()->type;
-
- assert(origValue);
- semanticRun = PASSsemanticdone;
-}
-
Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
{
- semantic(sc);
+ dsymbolSemantic(this, sc);
if (errors)
return new ErrorExp();
checkDisabled(loc, sc);
@@ -776,5 +363,5 @@ Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
if (errors)
return new ErrorExp();
Expression *e = new VarExp(loc, this);
- return ::semantic(e, sc);
+ return expressionSemantic(e, sc);
}