Skip to content

Commit dafb58b

Browse files
authored
Fix: Prevent ICE on final switch forward referencing its enum (#21001)
* Fix: Prevent ICE on final switch forward referencing its enum * more simpler approach * moved the enum member analysis * Move enum number analysis to sementic2 * WhiteSpace Remove * Remove Redundant Code in enumsem
1 parent 49a7c10 commit dafb58b

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

compiler/src/dmd/enumsem.d

+4
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed)
240240

241241
//if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars());
242242
//printf("members = %s\n", members.toChars());
243+
244+
// Set semantic2done here to indicate all members have been processed
245+
// This prevents using the enum in a final switch while being defined
246+
ed.semanticRun = PASS.semantic2done;
243247
}
244248

245249
Expression getDefaultValue(EnumDeclaration ed, Loc loc)

compiler/src/dmd/statementsem.d

+10
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,16 @@ 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+
// Circular references
1964+
// Check if enum semantic analysis is not yet complete
1965+
if (ed && ed.semanticRun < PASS.semantic2done)
1966+
{
1967+
error(ss.loc, "cannot use `final switch` on enum `%s` while it is being defined", ed.toChars());
1968+
sc.pop();
1969+
return setError();
1970+
}
1971+
19621972
if (ed && ss.cases.length < ed.members.length)
19631973
{
19641974
int missingMembers = 0;
+20
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)