Skip to content

Commit feb9f22

Browse files
committed
Sol1
1 parent 62a48a5 commit feb9f22

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

compiler/src/dmd/enumsem.d

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
236236
if (EnumMember em = s.isEnumMember())
237237
em.dsymbolSemantic(em._scope);
238238
});
239+
240+
// Don't set to PASS.semanticdone here, semantic2 will complete the analysis
241+
// and set it to PASS.semantic2done
242+
if (!sc.inCfile) // C enum remains incomplete until members are done
243+
ed.semanticRun = PASS.semantic;
239244
//printf("ed.defaultval = %lld\n", ed.defaultval);
240245

241246
//if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars());
@@ -542,7 +547,7 @@ void enumMemberSemantic(Scope* sc, EnumMember em)
542547
emax = emax.ctfeInterpret();
543548

544549
// check that (eprev != emax)
545-
Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
550+
Expression e = new EqualExp(EXP.equal, em.ed.loc, eprev, emax);
546551
e = e.expressionSemantic(sc);
547552
e = e.ctfeInterpret();
548553
if (global.endGagging(errors))
@@ -553,7 +558,7 @@ void enumMemberSemantic(Scope* sc, EnumMember em)
553558
Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
554559
e2 = e2.expressionSemantic(sc);
555560
e2 = e2.ctfeInterpret();
556-
e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
561+
e2 = new EqualExp(EXP.equal, em.ed.loc, eprev, e2);
557562
e2 = e2.expressionSemantic(sc);
558563
e2 = e2.ctfeInterpret();
559564
}

compiler/src/dmd/semantic2.d

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ private extern(C++) final class Semantic2Visitor : Visitor
123123
staticAssertFail(sa, sc);
124124
}
125125

126+
override void visit(EnumDeclaration ed)
127+
{
128+
//printf("EnumDeclaration::semantic2(%s) %s\n", sc.stc & STCfinal ? "final" : "", ed.toChars());
129+
if (ed.semanticRun >= PASS.semantic2done)
130+
return;
131+
ed.semanticRun = PASS.semantic2;
132+
133+
if (!ed.members)
134+
return;
135+
136+
// Process all enum members to compute their values
137+
for (size_t i = 0; i < ed.members.length; i++)
138+
{
139+
EnumMember em = (*ed.members)[i].isEnumMember();
140+
if (em && em.semanticRun < PASS.semanticdone)
141+
em.dsymbolSemantic(em._scope);
142+
}
143+
144+
// Now that all member values are calculated, we can mark the enum as semantic2done
145+
ed.semanticRun = PASS.semantic2done;
146+
}
147+
126148
override void visit(TemplateInstance tempinst)
127149
{
128150
if (tempinst.semanticRun >= PASS.semantic2)

compiler/src/dmd/statementsem.d

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,15 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
19591959
ed = ds.isEnumDeclaration(); // typedef'ed enum
19601960
if (!ed && te && ((ds = te.toDsymbol(sc)) !is null))
19611961
ed = ds.isEnumDeclaration();
1962+
1963+
// Check if enum semantic analysis is not yet complete
1964+
if (ed && ed.semanticRun < PASS.semantic2done)
1965+
{
1966+
error(ss.loc, "cannot use `final switch` on enum `%s` while it is being defined", ed.toChars());
1967+
sc.pop();
1968+
return setError();
1969+
}
1970+
19621971
if (ed && ss.cases.length < ed.members.length)
19631972
{
19641973
int missingMembers = 0;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
TEST_OUTPUT:
3+
---
4+
fail_compilation/fix20867.d(14): Error: cannot use `final switch` on enum `E` while it is being defined
5+
---
6+
*/
7+
8+
// Test case from Issue #20867
9+
enum E
10+
{
11+
a = 3,
12+
b = () {
13+
E e;
14+
final switch (e) // This should error out instead of segfaulting
15+
{
16+
case E.a: break;
17+
}
18+
return 4;
19+
} ()
20+
}

0 commit comments

Comments
 (0)