Move ImportC enum semantic to importc.d (#21027)

Co-authored-by: Dennis Korpel <dennis@sarc.nl>
This commit is contained in:
Dennis 2025-03-18 14:54:40 +01:00 committed by GitHub
parent a7e2b2e17b
commit 62a48a55e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 118 additions and 107 deletions

View file

@ -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)
{

View file

@ -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;
}