Skip to content

Commit

Permalink
fix Issue 15150 - Public selective import causes conflict
Browse files Browse the repository at this point in the history
By making `EnumMember` to the subclass of `VarDeclaration`, the symbol itself can be representation of the enum member name.
  • Loading branch information
9rnsr committed Oct 5, 2015
1 parent 8875575 commit 9e1e61d
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 64 deletions.
2 changes: 1 addition & 1 deletion src/declaration.d
Expand Up @@ -1898,7 +1898,7 @@ public:
sem = Semantic2Done;
}

override final const(char)* kind()
override const(char)* kind()
{
return "variable";
}
Expand Down
60 changes: 27 additions & 33 deletions src/denum.d
Expand Up @@ -8,6 +8,7 @@

module ddmd.denum;

import core.stdc.stdio;
import ddmd.access;
import ddmd.backend;
import ddmd.declaration;
Expand Down Expand Up @@ -97,7 +98,7 @@ public:
EnumMember em = (*members)[i].isEnumMember();
em.ed = this;
//printf("add %s to scope %s\n", em->toChars(), scopesym->toChars());
em.addMember(sc, scopesym);
em.addMember(sc, isAnonymous() ? scopesym : this);
}
}
added = true;
Expand Down Expand Up @@ -499,39 +500,36 @@ public:

/***********************************************************
*/
extern (C++) final class EnumMember : Dsymbol
extern (C++) final class EnumMember : VarDeclaration
{
public:
/* Can take the following forms:
* 1. id
* 2. id = value
* 3. type id = value
*/
Expression value;
@property ref value() { return (cast(ExpInitializer)_init).exp; }

// A cast() is injected to 'value' after semantic(),
// but 'origValue' will preserve the original value,
// or previous value + 1 if none was specified.
Expression origValue;

Type type;
Type origType;

EnumDeclaration ed;
VarDeclaration vd;

extern (D) this(Loc loc, Identifier id, Expression value, Type type)
extern (D) this(Loc loc, Identifier id, Expression value, Type origType)
{
super(id);
this.value = value;
super(loc, null, id ? id : Id.empty, new ExpInitializer(loc, value));
this.origValue = value;
this.type = type;
this.loc = loc;
this.origType = origType;
}

override Dsymbol syntaxCopy(Dsymbol s)
{
assert(!s);
return new EnumMember(loc, ident, value ? value.syntaxCopy() : null, type ? type.syntaxCopy() : null);
return new EnumMember(loc, ident, value ? value.syntaxCopy() : null, origType ? origType.syntaxCopy() : null);
}

override const(char)* kind()
Expand Down Expand Up @@ -559,16 +557,22 @@ public:
if (errors || semanticRun >= PASSsemanticdone)
return;

semanticRun = PASSsemantic;
if (_scope)
sc = _scope;

protection = ed.isAnonymous() ? ed.protection : Prot(PROTpublic);
storage_class = STCmanifest;
userAttribDecl = ed.isAnonymous() ? ed.userAttribDecl : null;

semanticRun = PASSsemantic;

// The first enum member is special
bool first = (this == (*ed.members)[0]);

if (type)
if (origType)
{
type = type.semantic(loc, sc);
origType = origType.semantic(loc, sc);
type = origType;
assert(value); // "type id;" is not a valid enum member declaration
}

Expand Down Expand Up @@ -598,10 +602,10 @@ public:
for (size_t i = 0; i < ed.members.dim; i++)
{
EnumMember em = (*ed.members)[i].isEnumMember();
if (!em || em == this || em.semanticRun < PASSsemanticdone || em.type)
if (!em || em == this || em.semanticRun < PASSsemanticdone || em.origType)
continue;

//printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
//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();
Expand All @@ -618,7 +622,7 @@ public:
}
}

if (ed.memtype && !type)
if (ed.memtype && !origType)
{
e = e.implicitCastTo(sc, ed.memtype);
e = e.ctfeInterpret();
Expand All @@ -629,9 +633,9 @@ public:
if (!ed.isAnonymous())
e = e.castTo(sc, ed.type);
}
else if (type)
else if (origType)
{
e = e.implicitCastTo(sc, type);
e = e.implicitCastTo(sc, origType);
e = e.ctfeInterpret();
assert(ed.isAnonymous());

Expand Down Expand Up @@ -703,6 +707,7 @@ public:
emprev.ed.toChars(), emprev.toChars(), ed.memtype.toChars());
goto Lerrors;
}

// Now set e to (eprev + 1)
e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type.tint32));
e = e.semantic(sc);
Expand Down Expand Up @@ -734,6 +739,8 @@ public:
}
value = e;
}
if (!origType)
type = value.type;

assert(origValue);
semanticRun = PASSsemanticdone;
Expand All @@ -744,20 +751,7 @@ public:
semantic(sc);
if (errors)
return new ErrorExp();
if (!vd)
{
assert(value);
vd = new VarDeclaration(loc, type, ident, new ExpInitializer(loc, value.copy()));

vd.storage_class = STCmanifest;
vd.semantic(sc);

vd.protection = ed.isAnonymous() ? ed.protection : Prot(PROTpublic);
vd.parent = ed.isAnonymous() ? ed.parent : ed;
vd.userAttribDecl = ed.isAnonymous() ? ed.userAttribDecl : null;
}
checkAccess(loc, sc, null, vd);
Expression e = new VarExp(loc, vd);
Expression e = new VarExp(loc, this);
return e.semantic(sc);
}

Expand Down
11 changes: 6 additions & 5 deletions src/enum.h
Expand Up @@ -18,6 +18,7 @@

#include "root.h"
#include "dsymbol.h"
#include "declaration.h"
#include "tokens.h"

class Identifier;
Expand Down Expand Up @@ -70,25 +71,25 @@ class EnumDeclaration : public ScopeDsymbol
};


class EnumMember : public Dsymbol
class EnumMember : public VarDeclaration
{
public:
/* Can take the following forms:
* 1. id
* 2. id = value
* 3. type id = value
*/
Expression *value;
Expression *&value();

// A cast() is injected to 'value' after semantic(),
// but 'origValue' will preserve the original value,
// or previous value + 1 if none was specified.
Expression *origValue;
Type *type;
Type *origType;

EnumDeclaration *ed;
VarDeclaration *vd;

EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType);
Dsymbol *syntaxCopy(Dsymbol *s);
const char *kind();
void semantic(Scope *sc);
Expand Down
2 changes: 1 addition & 1 deletion src/iasm.c
Expand Up @@ -2335,7 +2335,7 @@ static void asm_merge_symbol(OPND *o1, Dsymbol *s)
em = s->isEnumMember();
if (em)
{
o1->disp = em->value->toInteger();
o1->disp = em->value()->toInteger();
return;
}
o1->s = s; // a C identifier
Expand Down
4 changes: 2 additions & 2 deletions src/json.d
Expand Up @@ -745,8 +745,8 @@ public:
override void visit(EnumMember s)
{
objectStart();
jsonProperties(s);
property("type", "deco", s.type);
jsonProperties(cast(Dsymbol)s);
property("type", "deco", s.origType);
objectEnd();
}

Expand Down
39 changes: 23 additions & 16 deletions src/mtype.d
Expand Up @@ -7050,6 +7050,13 @@ public:
L2:
s = sm.toAlias();
}

if (auto em = s.isEnumMember())
{
// It's not a type, it's an expression
*pe = em.getVarExp(loc, sc);
return;
}
if (VarDeclaration v = s.isVarDeclaration())
{
/* This is mostly same with DsymbolExp::semantic(), but we cannot use it
Expand Down Expand Up @@ -7088,12 +7095,6 @@ public:
return;
}
}
if (EnumMember em = s.isEnumMember())
{
// It's not a type, it's an expression
*pe = em.getVarExp(loc, sc);
return;
}
L1:
Type t = s.getType();
if (!t)
Expand Down Expand Up @@ -7265,6 +7266,8 @@ public:
resolve(loc, sc, &e, &t, &s);
if (t && t.ty != Tident)
s = t.toDsymbol(sc);
if (e)
s = getDsymbol(e);
return s;
}

Expand Down Expand Up @@ -7834,6 +7837,12 @@ public:
if (!s.isFuncDeclaration()) // because of overloading
s.checkDeprecated(e.loc, sc);
s = s.toAlias();

if (auto em = s.isEnumMember())
{
return em.getVarExp(e.loc, sc);
}

VarDeclaration v = s.isVarDeclaration();
if (v && (!v.type || !v.type.deco))
{
Expand All @@ -7860,11 +7869,7 @@ public:
{
return new TypeExp(e.loc, s.getType());
}
EnumMember em = s.isEnumMember();
if (em)
{
return em.getVarExp(e.loc, sc);
}

TemplateMixin tm = s.isTemplateMixin();
if (tm)
{
Expand Down Expand Up @@ -8690,6 +8695,12 @@ public:
if (!s.isFuncDeclaration()) // because of overloading
s.checkDeprecated(e.loc, sc);
s = s.toAlias();

if (auto em = s.isEnumMember())
{
return em.getVarExp(e.loc, sc);
}

VarDeclaration v = s.isVarDeclaration();
if (v && (!v.type || !v.type.deco))
{
Expand All @@ -8716,11 +8727,7 @@ public:
{
return new TypeExp(e.loc, s.getType());
}
EnumMember em = s.isEnumMember();
if (em)
{
return em.getVarExp(e.loc, sc);
}

TemplateMixin tm = s.isTemplateMixin();
if (tm)
{
Expand Down
4 changes: 2 additions & 2 deletions src/tocvdebug.c
Expand Up @@ -159,7 +159,7 @@ unsigned cv4_Denum(EnumDeclaration *e)
{ EnumMember *sf = (*e->members)[i]->isEnumMember();
if (sf)
{
dinteger_t value = sf->value->toInteger();
dinteger_t value = sf->value()->toInteger();
unsigned fnamelen1 = fnamelen;

// store only member's simple name
Expand Down Expand Up @@ -233,7 +233,7 @@ unsigned cv4_Denum(EnumDeclaration *e)
if (fieldi > nfields)
break; // chop off the rest

dinteger_t value = sf->value->toInteger();
dinteger_t value = sf->value()->toInteger();
TOWORD(dt->data + j,(config.fulltypes == CV8) ? LF_ENUMERATE_V3 : LF_ENUMERATE);
unsigned attribute = 0;
TOWORD(dt->data + j + 2,attribute);
Expand Down
2 changes: 1 addition & 1 deletion src/visitor.d
Expand Up @@ -380,7 +380,7 @@ public:

void visit(EnumMember s)
{
visit(cast(Dsymbol)s);
visit(cast(VarDeclaration)s);
}

void visit(Import s)
Expand Down
2 changes: 1 addition & 1 deletion src/visitor.h
Expand Up @@ -371,7 +371,7 @@ class Visitor
virtual void visit(StaticAssert *s) { visit((Dsymbol *)s); }
virtual void visit(DebugSymbol *s) { visit((Dsymbol *)s); }
virtual void visit(VersionSymbol *s) { visit((Dsymbol *)s); }
virtual void visit(EnumMember *s) { visit((Dsymbol *)s); }
virtual void visit(EnumMember *s) { visit((VarDeclaration *)s); }
virtual void visit(Import *s) { visit((Dsymbol *)s); }
virtual void visit(OverloadSet *s) { visit((Dsymbol *)s); }
virtual void visit(LabelDsymbol *s) { visit((Dsymbol *)s); }
Expand Down
6 changes: 6 additions & 0 deletions test/compilable/imports/test15150a.d
@@ -0,0 +1,6 @@
module imports.test15150a;

enum
{
x
}
3 changes: 3 additions & 0 deletions test/compilable/imports/test15150b.d
@@ -0,0 +1,3 @@
module imports.test15150b;

import imports.test15150a : x;
8 changes: 8 additions & 0 deletions test/compilable/test15150.d
@@ -0,0 +1,8 @@
// PERMUTE_ARGS:

module test15150;

import imports.test15150a;
import imports.test15150b;

enum y = x;
4 changes: 2 additions & 2 deletions test/fail_compilation/fail10528.d
Expand Up @@ -3,8 +3,8 @@ TEST_OUTPUT:
---
fail_compilation/fail10528.d(19): Error: module fail10528 variable a10528.a is private
fail_compilation/fail10528.d(20): Error: variable a10528.a is not accessible from module fail10528
fail_compilation/fail10528.d(22): Error: variable a10528.b is not accessible from module fail10528
fail_compilation/fail10528.d(23): Error: variable a10528.b is not accessible from module fail10528
fail_compilation/fail10528.d(22): Error: module fail10528 enum member a10528.b is private
fail_compilation/fail10528.d(23): Error: enum member a10528.b is not accessible from module fail10528
fail_compilation/fail10528.d(25): Error: variable a10528.S.c is not accessible from module fail10528
fail_compilation/fail10528.d(26): Error: variable a10528.S.c is not accessible from module fail10528
fail_compilation/fail10528.d(28): Error: variable a10528.C.d is not accessible from module fail10528
Expand Down

0 comments on commit 9e1e61d

Please sign in to comment.