Skip to content

Commit 62a48a5

Browse files
dkorpelDennis Korpel
and
Dennis Korpel
authored
Move ImportC enum semantic to importc.d (#21027)
Co-authored-by: Dennis Korpel <dennis@sarc.nl>
1 parent a7e2b2e commit 62a48a5

File tree

2 files changed

+118
-107
lines changed

2 files changed

+118
-107
lines changed

compiler/src/dmd/enumsem.d

+2-107
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ import dmd.visitor;
8181

8282

8383
/*********************************
84-
* Perform semantic analysis on enum declaration `em`
84+
* Perform semantic analysis on enum declaration `ed`
8585
*/
8686
void enumSemantic(Scope* sc, EnumDeclaration ed)
8787
{
@@ -229,112 +229,7 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
229229
addEnumMembersToSymtab(ed, sc, sc.getScopesym());
230230

231231
if (sc.inCfile)
232-
{
233-
/* C11 6.7.2.2
234-
*/
235-
Type commonType = ed.memtype;
236-
if (!commonType)
237-
commonType = Type.tint32;
238-
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
239-
240-
// C11 6.7.2.2-2 value must be representable as an int.
241-
// The sizemask represents all values that int will fit into,
242-
// from 0..uint.max. We want to cover int.min..uint.max.
243-
IntRange ir = IntRange.fromType(commonType);
244-
245-
void emSemantic(EnumMember em, ref ulong nextValue)
246-
{
247-
static void errorReturn(EnumMember em)
248-
{
249-
em.value = ErrorExp.get();
250-
em.errors = true;
251-
em.semanticRun = PASS.semanticdone;
252-
}
253-
254-
em.semanticRun = PASS.semantic;
255-
em.type = commonType;
256-
em._linkage = LINK.c;
257-
em.storage_class |= STC.manifest;
258-
if (em.value)
259-
{
260-
Expression e = em.value;
261-
assert(e.dyncast() == DYNCAST.expression);
262-
263-
/* To merge the type of e with commonType, add 0 of type commonType
264-
*/
265-
if (!ed.memtype)
266-
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
267-
268-
e = e.expressionSemantic(sc);
269-
e = resolveProperties(sc, e);
270-
e = e.integralPromotions(sc);
271-
e = e.ctfeInterpret();
272-
if (e.op == EXP.error)
273-
return errorReturn(em);
274-
auto ie = e.isIntegerExp();
275-
if (!ie)
276-
{
277-
// C11 6.7.2.2-2
278-
.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());
279-
return errorReturn(em);
280-
}
281-
if (ed.memtype && !ir.contains(getIntRange(ie)))
282-
{
283-
// C11 6.7.2.2-2
284-
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
285-
return errorReturn(em);
286-
}
287-
nextValue = ie.toInteger();
288-
if (!ed.memtype)
289-
commonType = e.type;
290-
em.value = new IntegerExp(em.loc, nextValue, commonType);
291-
}
292-
else
293-
{
294-
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
295-
bool first = (em == (*em.ed.members)[0]);
296-
if (!first)
297-
{
298-
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
299-
if (nextValue == max.toInteger())
300-
{
301-
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
302-
return errorReturn(em);
303-
}
304-
nextValue += 1;
305-
}
306-
em.value = new IntegerExp(em.loc, nextValue, commonType);
307-
}
308-
em.type = commonType;
309-
em.semanticRun = PASS.semanticdone;
310-
}
311-
312-
ed.members.foreachDsymbol( (s)
313-
{
314-
if (EnumMember em = s.isEnumMember())
315-
emSemantic(em, nextValue);
316-
});
317-
318-
if (!ed.memtype)
319-
{
320-
// cast all members to commonType
321-
ed.members.foreachDsymbol( (s)
322-
{
323-
if (EnumMember em = s.isEnumMember())
324-
{
325-
em.type = commonType;
326-
// optimize out the cast so that other parts of the compiler can
327-
// assume that an integral enum's members are `IntegerExp`s.
328-
// https://issues.dlang.org/show_bug.cgi?id=24504
329-
em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
330-
}
331-
});
332-
}
333-
334-
ed.memtype = commonType;
335-
ed.semanticRun = PASS.semanticdone;
336-
return;
337-
}
232+
return cEnumSemantic(sc, ed);
338233

339234
ed.members.foreachDsymbol( (s)
340235
{

compiler/src/dmd/importc.d

+116
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,22 @@ import core.stdc.stdio;
1717

1818
import dmd.astenums;
1919
import dmd.dcast;
20+
import dmd.denum;
2021
import dmd.declaration;
2122
import dmd.dscope;
2223
import dmd.dsymbol;
2324
import dmd.dsymbolsem;
25+
import dmd.dinterpret : ctfeInterpret;
2426
import dmd.errors;
2527
import dmd.expression;
2628
import dmd.expressionsem;
2729
import dmd.identifier;
30+
import dmd.id : Id;
2831
import dmd.init;
32+
import dmd.intrange : IntRange;
2933
import dmd.mtype;
34+
import dmd.optimize : optimize;
35+
import dmd.rootobject : DYNCAST;
3036
import dmd.tokens;
3137
import dmd.typesem;
3238

@@ -638,3 +644,113 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
638644

639645
return collision();
640646
}
647+
648+
/*********************************
649+
* ImportC-specific semantic analysis on enum declaration `ed`
650+
*/
651+
void cEnumSemantic(Scope* sc, EnumDeclaration ed)
652+
{
653+
// C11 6.7.2.2
654+
Type commonType = ed.memtype;
655+
if (!commonType)
656+
commonType = Type.tint32;
657+
ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
658+
659+
// C11 6.7.2.2-2 value must be representable as an int.
660+
// The sizemask represents all values that int will fit into,
661+
// from 0..uint.max. We want to cover int.min..uint.max.
662+
IntRange ir = IntRange.fromType(commonType);
663+
664+
void emSemantic(EnumMember em, ref ulong nextValue)
665+
{
666+
static void errorReturn(EnumMember em)
667+
{
668+
em.value = ErrorExp.get();
669+
em.errors = true;
670+
em.semanticRun = PASS.semanticdone;
671+
}
672+
673+
em.semanticRun = PASS.semantic;
674+
em.type = commonType;
675+
em._linkage = LINK.c;
676+
em.storage_class |= STC.manifest;
677+
if (em.value)
678+
{
679+
Expression e = em.value;
680+
assert(e.dyncast() == DYNCAST.expression);
681+
682+
/* To merge the type of e with commonType, add 0 of type commonType
683+
*/
684+
if (!ed.memtype)
685+
e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
686+
687+
e = e.expressionSemantic(sc);
688+
e = resolveProperties(sc, e);
689+
e = e.integralPromotions(sc);
690+
e = e.ctfeInterpret();
691+
if (e.op == EXP.error)
692+
return errorReturn(em);
693+
auto ie = e.isIntegerExp();
694+
if (!ie)
695+
{
696+
// C11 6.7.2.2-2
697+
.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());
698+
return errorReturn(em);
699+
}
700+
if (ed.memtype && !ir.contains(getIntRange(ie)))
701+
{
702+
// C11 6.7.2.2-2
703+
.error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
704+
return errorReturn(em);
705+
}
706+
nextValue = ie.toInteger();
707+
if (!ed.memtype)
708+
commonType = e.type;
709+
em.value = new IntegerExp(em.loc, nextValue, commonType);
710+
}
711+
else
712+
{
713+
// C11 6.7.2.2-3 add 1 to value of previous enumeration constant
714+
bool first = (em == (*em.ed.members)[0]);
715+
if (!first)
716+
{
717+
Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
718+
if (nextValue == max.toInteger())
719+
{
720+
.error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
721+
return errorReturn(em);
722+
}
723+
nextValue += 1;
724+
}
725+
em.value = new IntegerExp(em.loc, nextValue, commonType);
726+
}
727+
em.type = commonType;
728+
em.semanticRun = PASS.semanticdone;
729+
}
730+
731+
ed.members.foreachDsymbol( (s)
732+
{
733+
if (EnumMember em = s.isEnumMember())
734+
emSemantic(em, nextValue);
735+
});
736+
737+
if (!ed.memtype)
738+
{
739+
// cast all members to commonType
740+
ed.members.foreachDsymbol( (s)
741+
{
742+
if (EnumMember em = s.isEnumMember())
743+
{
744+
em.type = commonType;
745+
// optimize out the cast so that other parts of the compiler can
746+
// assume that an integral enum's members are `IntegerExp`s.
747+
// https://issues.dlang.org/show_bug.cgi?id=24504
748+
em.value = em.value.castTo(sc, commonType).optimize(WANTvalue);
749+
}
750+
});
751+
}
752+
753+
ed.memtype = commonType;
754+
ed.semanticRun = PASS.semanticdone;
755+
return;
756+
}

0 commit comments

Comments
 (0)