mirror of
https://github.com/dlang/dmd.git
synced 2025-04-28 14:10:11 +03:00
Move ImportC enum semantic to importc.d (#21027)
Co-authored-by: Dennis Korpel <dennis@sarc.nl>
This commit is contained in:
parent
a7e2b2e17b
commit
62a48a55e3
2 changed files with 118 additions and 107 deletions
|
@ -81,7 +81,7 @@ import dmd.visitor;
|
||||||
|
|
||||||
|
|
||||||
/*********************************
|
/*********************************
|
||||||
* Perform semantic analysis on enum declaration `em`
|
* Perform semantic analysis on enum declaration `ed`
|
||||||
*/
|
*/
|
||||||
void enumSemantic(Scope* sc, EnumDeclaration ed)
|
void enumSemantic(Scope* sc, EnumDeclaration ed)
|
||||||
{
|
{
|
||||||
|
@ -229,112 +229,7 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
|
||||||
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
|
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
|
||||||
|
|
||||||
if (sc.inCfile)
|
if (sc.inCfile)
|
||||||
{
|
return cEnumSemantic(sc, ed);
|
||||||
/* C11 6.7.2.2
|
|
||||||
*/
|
|
||||||
Type commonType = ed.memtype;
|
|
||||||
if (!commonType)
|
|
||||||
commonType = Type.tint32;
|
|
||||||
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
|
|
||||||
|
|
||||||
// C11 6.7.2.2-2 value must be representable as an int.
|
|
||||||
// The sizemask represents all values that int will fit into,
|
|
||||||
// from 0..uint.max. We want to cover int.min..uint.max.
|
|
||||||
IntRange ir = IntRange.fromType(commonType);
|
|
||||||
|
|
||||||
void emSemantic(EnumMember em, ref ulong nextValue)
|
|
||||||
{
|
|
||||||
static void errorReturn(EnumMember em)
|
|
||||||
{
|
|
||||||
em.value = ErrorExp.get();
|
|
||||||
em.errors = true;
|
|
||||||
em.semanticRun = PASS.semanticdone;
|
|
||||||
}
|
|
||||||
|
|
||||||
em.semanticRun = PASS.semantic;
|
|
||||||
em.type = commonType;
|
|
||||||
em._linkage = LINK.c;
|
|
||||||
em.storage_class |= STC.manifest;
|
|
||||||
if (em.value)
|
|
||||||
{
|
|
||||||
Expression e = em.value;
|
|
||||||
assert(e.dyncast() == DYNCAST.expression);
|
|
||||||
|
|
||||||
/* To merge the type of e with commonType, add 0 of type commonType
|
|
||||||
*/
|
|
||||||
if (!ed.memtype)
|
|
||||||
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
|
|
||||||
|
|
||||||
e = e.expressionSemantic(sc);
|
|
||||||
e = resolveProperties(sc, e);
|
|
||||||
e = e.integralPromotions(sc);
|
|
||||||
e = e.ctfeInterpret();
|
|
||||||
if (e.op == EXP.error)
|
|
||||||
return errorReturn(em);
|
|
||||||
auto ie = e.isIntegerExp();
|
|
||||||
if (!ie)
|
|
||||||
{
|
|
||||||
// C11 6.7.2.2-2
|
|
||||||
.error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
|
|
||||||
return errorReturn(em);
|
|
||||||
}
|
|
||||||
if (ed.memtype && !ir.contains(getIntRange(ie)))
|
|
||||||
{
|
|
||||||
// C11 6.7.2.2-2
|
|
||||||
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
|
|
||||||
return errorReturn(em);
|
|
||||||
}
|
|
||||||
nextValue = ie.toInteger();
|
|
||||||
if (!ed.memtype)
|
|
||||||
commonType = e.type;
|
|
||||||
em.value = new IntegerExp(em.loc, nextValue, commonType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
|
|
||||||
bool first = (em == (*em.ed.members)[0]);
|
|
||||||
if (!first)
|
|
||||||
{
|
|
||||||
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
|
|
||||||
if (nextValue == max.toInteger())
|
|
||||||
{
|
|
||||||
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
|
|
||||||
return errorReturn(em);
|
|
||||||
}
|
|
||||||
nextValue += 1;
|
|
||||||
}
|
|
||||||
em.value = new IntegerExp(em.loc, nextValue, commonType);
|
|
||||||
}
|
|
||||||
em.type = commonType;
|
|
||||||
em.semanticRun = PASS.semanticdone;
|
|
||||||
}
|
|
||||||
|
|
||||||
ed.members.foreachDsymbol( (s)
|
|
||||||
{
|
|
||||||
if (EnumMember em = s.isEnumMember())
|
|
||||||
emSemantic(em, nextValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!ed.memtype)
|
|
||||||
{
|
|
||||||
// cast all members to commonType
|
|
||||||
ed.members.foreachDsymbol( (s)
|
|
||||||
{
|
|
||||||
if (EnumMember em = s.isEnumMember())
|
|
||||||
{
|
|
||||||
em.type = commonType;
|
|
||||||
// optimize out the cast so that other parts of the compiler can
|
|
||||||
// assume that an integral enum's members are `IntegerExp`s.
|
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=24504
|
|
||||||
em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ed.memtype = commonType;
|
|
||||||
ed.semanticRun = PASS.semanticdone;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ed.members.foreachDsymbol( (s)
|
ed.members.foreachDsymbol( (s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,16 +17,22 @@ import core.stdc.stdio;
|
||||||
|
|
||||||
import dmd.astenums;
|
import dmd.astenums;
|
||||||
import dmd.dcast;
|
import dmd.dcast;
|
||||||
|
import dmd.denum;
|
||||||
import dmd.declaration;
|
import dmd.declaration;
|
||||||
import dmd.dscope;
|
import dmd.dscope;
|
||||||
import dmd.dsymbol;
|
import dmd.dsymbol;
|
||||||
import dmd.dsymbolsem;
|
import dmd.dsymbolsem;
|
||||||
|
import dmd.dinterpret : ctfeInterpret;
|
||||||
import dmd.errors;
|
import dmd.errors;
|
||||||
import dmd.expression;
|
import dmd.expression;
|
||||||
import dmd.expressionsem;
|
import dmd.expressionsem;
|
||||||
import dmd.identifier;
|
import dmd.identifier;
|
||||||
|
import dmd.id : Id;
|
||||||
import dmd.init;
|
import dmd.init;
|
||||||
|
import dmd.intrange : IntRange;
|
||||||
import dmd.mtype;
|
import dmd.mtype;
|
||||||
|
import dmd.optimize : optimize;
|
||||||
|
import dmd.rootobject : DYNCAST;
|
||||||
import dmd.tokens;
|
import dmd.tokens;
|
||||||
import dmd.typesem;
|
import dmd.typesem;
|
||||||
|
|
||||||
|
@ -638,3 +644,113 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
|
||||||
|
|
||||||
return collision();
|
return collision();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
* ImportC-specific semantic analysis on enum declaration `ed`
|
||||||
|
*/
|
||||||
|
void cEnumSemantic(Scope* sc, EnumDeclaration ed)
|
||||||
|
{
|
||||||
|
// C11 6.7.2.2
|
||||||
|
Type commonType = ed.memtype;
|
||||||
|
if (!commonType)
|
||||||
|
commonType = Type.tint32;
|
||||||
|
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
|
||||||
|
|
||||||
|
// C11 6.7.2.2-2 value must be representable as an int.
|
||||||
|
// The sizemask represents all values that int will fit into,
|
||||||
|
// from 0..uint.max. We want to cover int.min..uint.max.
|
||||||
|
IntRange ir = IntRange.fromType(commonType);
|
||||||
|
|
||||||
|
void emSemantic(EnumMember em, ref ulong nextValue)
|
||||||
|
{
|
||||||
|
static void errorReturn(EnumMember em)
|
||||||
|
{
|
||||||
|
em.value = ErrorExp.get();
|
||||||
|
em.errors = true;
|
||||||
|
em.semanticRun = PASS.semanticdone;
|
||||||
|
}
|
||||||
|
|
||||||
|
em.semanticRun = PASS.semantic;
|
||||||
|
em.type = commonType;
|
||||||
|
em._linkage = LINK.c;
|
||||||
|
em.storage_class |= STC.manifest;
|
||||||
|
if (em.value)
|
||||||
|
{
|
||||||
|
Expression e = em.value;
|
||||||
|
assert(e.dyncast() == DYNCAST.expression);
|
||||||
|
|
||||||
|
/* To merge the type of e with commonType, add 0 of type commonType
|
||||||
|
*/
|
||||||
|
if (!ed.memtype)
|
||||||
|
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
|
||||||
|
|
||||||
|
e = e.expressionSemantic(sc);
|
||||||
|
e = resolveProperties(sc, e);
|
||||||
|
e = e.integralPromotions(sc);
|
||||||
|
e = e.ctfeInterpret();
|
||||||
|
if (e.op == EXP.error)
|
||||||
|
return errorReturn(em);
|
||||||
|
auto ie = e.isIntegerExp();
|
||||||
|
if (!ie)
|
||||||
|
{
|
||||||
|
// C11 6.7.2.2-2
|
||||||
|
.error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
|
||||||
|
return errorReturn(em);
|
||||||
|
}
|
||||||
|
if (ed.memtype && !ir.contains(getIntRange(ie)))
|
||||||
|
{
|
||||||
|
// C11 6.7.2.2-2
|
||||||
|
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
|
||||||
|
return errorReturn(em);
|
||||||
|
}
|
||||||
|
nextValue = ie.toInteger();
|
||||||
|
if (!ed.memtype)
|
||||||
|
commonType = e.type;
|
||||||
|
em.value = new IntegerExp(em.loc, nextValue, commonType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
|
||||||
|
bool first = (em == (*em.ed.members)[0]);
|
||||||
|
if (!first)
|
||||||
|
{
|
||||||
|
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
|
||||||
|
if (nextValue == max.toInteger())
|
||||||
|
{
|
||||||
|
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
|
||||||
|
return errorReturn(em);
|
||||||
|
}
|
||||||
|
nextValue += 1;
|
||||||
|
}
|
||||||
|
em.value = new IntegerExp(em.loc, nextValue, commonType);
|
||||||
|
}
|
||||||
|
em.type = commonType;
|
||||||
|
em.semanticRun = PASS.semanticdone;
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.members.foreachDsymbol( (s)
|
||||||
|
{
|
||||||
|
if (EnumMember em = s.isEnumMember())
|
||||||
|
emSemantic(em, nextValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ed.memtype)
|
||||||
|
{
|
||||||
|
// cast all members to commonType
|
||||||
|
ed.members.foreachDsymbol( (s)
|
||||||
|
{
|
||||||
|
if (EnumMember em = s.isEnumMember())
|
||||||
|
{
|
||||||
|
em.type = commonType;
|
||||||
|
// optimize out the cast so that other parts of the compiler can
|
||||||
|
// assume that an integral enum's members are `IntegerExp`s.
|
||||||
|
// https://issues.dlang.org/show_bug.cgi?id=24504
|
||||||
|
em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.memtype = commonType;
|
||||||
|
ed.semanticRun = PASS.semanticdone;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue