mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +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)
|
||||
{
|
||||
|
@ -229,112 +229,7 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
|
|||
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
|
||||
|
||||
if (sc.inCfile)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
return cEnumSemantic(sc, ed);
|
||||
|
||||
ed.members.foreachDsymbol( (s)
|
||||
{
|
||||
|
|
|
@ -17,16 +17,22 @@ import core.stdc.stdio;
|
|||
|
||||
import dmd.astenums;
|
||||
import dmd.dcast;
|
||||
import dmd.denum;
|
||||
import dmd.declaration;
|
||||
import dmd.dscope;
|
||||
import dmd.dsymbol;
|
||||
import dmd.dsymbolsem;
|
||||
import dmd.dinterpret : ctfeInterpret;
|
||||
import dmd.errors;
|
||||
import dmd.expression;
|
||||
import dmd.expressionsem;
|
||||
import dmd.identifier;
|
||||
import dmd.id : Id;
|
||||
import dmd.init;
|
||||
import dmd.intrange : IntRange;
|
||||
import dmd.mtype;
|
||||
import dmd.optimize : optimize;
|
||||
import dmd.rootobject : DYNCAST;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem;
|
||||
|
||||
|
@ -638,3 +644,113 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
|
|||
|
||||
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