Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[enh] fix issue 10965 - Allow alias initializer as enum member to avoid counter reset #2529

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ void EnumDeclaration::semantic(Scope *sc)
}
else if (first)
{
Lfirst:
if (memtype)
t = memtype;
else
Expand All @@ -303,6 +304,9 @@ void EnumDeclaration::semantic(Scope *sc)
}
else
{
if (!elast)
goto Lfirst;

// Lazily evaluate enum.max
if (!emax)
{
Expand Down Expand Up @@ -336,7 +340,8 @@ void EnumDeclaration::semantic(Scope *sc)
error("enum member %s has inexact value, due to loss of precision", em->toChars());
}
}
elast = e;
if (!em->isAlias)
elast = e;
em->value = e;

// Add to symbol table only after evaluating 'value'
Expand Down Expand Up @@ -480,10 +485,11 @@ Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)

/********************************* EnumMember ****************************/

EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
EnumMember::EnumMember(Loc loc, bool isAlias, Identifier *id, Expression *value, Type *type)
: Dsymbol(id)
{
this->ed = NULL;
this->isAlias = isAlias;
this->value = value;
this->type = type;
this->loc = loc;
Expand All @@ -508,7 +514,7 @@ Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
em->type = t;
}
else
em = new EnumMember(loc, ident, e, t);
em = new EnumMember(loc, isAlias, ident, e, t);
return em;
}

Expand Down
3 changes: 2 additions & 1 deletion src/enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ class EnumMember : public Dsymbol
{
public:
EnumDeclaration *ed;
bool isAlias;
Expression *value;
Type *type;
VarDeclaration *vd;

EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
EnumMember(Loc loc, bool isAlias, Identifier *id, Expression *value, Type *type);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
Expand Down
3 changes: 2 additions & 1 deletion src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,7 @@ EnumDeclaration *Parser::parseEnum()

Type *type = NULL;
Identifier *ident;
bool isAlias = token.value == TOKalias ? nextToken(), true : false;
Token *tp = peek(&token);
if (token.value == TOKidentifier &&
(tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly))
Expand Down Expand Up @@ -1657,7 +1658,7 @@ EnumDeclaration *Parser::parseEnum()
error("if type, there must be an initializer");
}

EnumMember *em = new EnumMember(loc, ident, value, type);
EnumMember *em = new EnumMember(loc, isAlias, ident, value, type);
e->members->push(em);

if (token.value == TOKrcurly)
Expand Down
33 changes: 33 additions & 0 deletions test/compilable/test10965.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
enum E1
{
alias a,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a little more than what the enhancement request is about, it's also a very special case compared to what alias usually does, I think we shouldn't go this far.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this, too. So initializers are needed for alias members?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're supposed to refer to existing members, e.g. alias b = a;.

Anyway, it's kind of fast to implement this already, since I've just filed the enhancement. Maybe a NG discussion should be made first to get a go-ahead.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I've posted to the newsgroups. I don't have high hopes that it will be accepted. However Issue 9395 is something that can easily pass through. If you want to have a go at it, you might want to see Pull 463 for a reference.

b,
c = 2,
alias d = c,
e,
}

static assert(E1.a == 0);
static assert(E1.b == 0);
static assert(E1.c == 2);
static assert(E1.d == 2);
static assert(E1.e == 3);

enum E2
{
a,
b,
alias c = a,
d,
alias e = a,
f,
}

static assert(E2.a == 0);
static assert(E2.b == 1);
static assert(E2.c == 0);
static assert(E2.d == 2);
static assert(E2.e == 0);
static assert(E2.f == 3);

void main() { }