diff --git a/src/ddmd/backend/rtlsym.d b/src/ddmd/backend/rtlsym.d index 2e7faef1ac62..3d9f470329fd 100644 --- a/src/ddmd/backend/rtlsym.d +++ b/src/ddmd/backend/rtlsym.d @@ -53,9 +53,9 @@ enum RTLSYM_MONITOREXIT, RTLSYM_CRITICALENTER, RTLSYM_CRITICALEXIT, - RTLSYM_SWITCH_STRING, - RTLSYM_SWITCH_USTRING, - RTLSYM_SWITCH_DSTRING, + RTLSYM_SWITCH_STRING, // unused + RTLSYM_SWITCH_USTRING, // unused + RTLSYM_SWITCH_DSTRING, // unused RTLSYM_DSWITCHERR, RTLSYM_DHIDDENFUNC, RTLSYM_NEWCLASS, @@ -104,11 +104,11 @@ enum RTLSYM_ARRAYCAST, RTLSYM_ARRAYEQ, RTLSYM_ARRAYEQ2, - RTLSYM_ARRAYCMP, - RTLSYM_ARRAYCMP2, - RTLSYM_ARRAYCMPCHAR, - RTLSYM_OBJ_EQ, - RTLSYM_OBJ_CMP, + RTLSYM_ARRAYCMP, // unused + RTLSYM_ARRAYCMP2, // unused + RTLSYM_ARRAYCMPCHAR, // unused + RTLSYM_OBJ_EQ, // unused + RTLSYM_OBJ_CMP, // unused RTLSYM_EXCEPT_HANDLER2, RTLSYM_EXCEPT_HANDLER3, diff --git a/src/ddmd/id.d b/src/ddmd/id.d index bd72e7fe7102..6fa545518c0e 100644 --- a/src/ddmd/id.d +++ b/src/ddmd/id.d @@ -315,6 +315,7 @@ immutable Msgtable[] msgtable = { "__cmp" }, { "__equals"}, { "__switch"}, + { "__switch_error"}, // varargs implementation { "va_start" }, diff --git a/src/ddmd/s2ir.d b/src/ddmd/s2ir.d index df7244e67dd4..b55ee1f26e45 100644 --- a/src/ddmd/s2ir.d +++ b/src/ddmd/s2ir.d @@ -689,21 +689,15 @@ extern (C++) class S2irVisitor : Visitor override void visit(SwitchErrorStatement s) { + // SwitchErrors are lowered to a CallExpression to object.__switch_error() in druntime + // We still need the call wrapped in SwitchErrorStatement to pass compiler error checks. + assert(s.exp !is null, "SwitchErrorStatement needs to have a valid Expression."); + Blockx *blx = irs.blx; - //printf("SwitchErrorStatement.toIR()\n"); - elem *e; - if (global.params.checkAction == CHECKACTION.C) - { - e = callCAssert(irs, s.loc, null, null, "no switch default"); - } - else - { - auto efilename = el_ptr(toSymbol(cast(Dsymbol)blx._module)); - auto elinnum = el_long(TYint, s.loc.linnum); - e = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_DSWITCHERR)), el_param(elinnum, efilename)); - } - block_appendexp(blx.curblock, e); + //printf("SwitchErrorStatement.toIR(), exp = %s\n", s.exp ? s.exp.toChars() : ""); + incUsage(irs, s.loc); + block_appendexp(blx.curblock, toElemDtor(s.exp, irs)); } /************************************** @@ -828,7 +822,7 @@ extern (C++) class S2irVisitor : Visitor //printf("ExpStatement.toIR(), exp = %s\n", s.exp ? s.exp.toChars() : ""); incUsage(irs, s.loc); if (s.exp) - block_appendexp(blx.curblock,toElemDtor(s.exp, irs)); + block_appendexp(blx.curblock, toElemDtor(s.exp, irs)); } /************************************** diff --git a/src/ddmd/statement.d b/src/ddmd/statement.d index 054d4e29d212..7dfe72d2980c 100644 --- a/src/ddmd/statement.d +++ b/src/ddmd/statement.d @@ -1834,11 +1834,19 @@ extern (C++) final class GotoCaseStatement : Statement */ extern (C++) final class SwitchErrorStatement : Statement { + Expression exp; + extern (D) this(Loc loc) { super(loc); } + final extern (D) this(Loc loc, Expression exp) + { + super(loc); + this.exp = exp; + } + override void accept(Visitor v) { v.visit(this); diff --git a/src/ddmd/statementsem.d b/src/ddmd/statementsem.d index a25785b7af07..4eba184e06d2 100644 --- a/src/ddmd/statementsem.d +++ b/src/ddmd/statementsem.d @@ -2484,13 +2484,26 @@ else if (!ss.isFinal && !ss._body.isErrorStatement()) ss.error("switch statement without a default; use `final switch` or add `default: assert(0);` or add `default: break;`"); - // Generate runtime error if the default is hit + // Generate runtime error if the default is hit auto a = new Statements(); CompoundStatement cs; Statement s; if (global.params.useSwitchError == CHECKENABLE.on) - s = new SwitchErrorStatement(ss.loc); + { + Expression sl = new IdentifierExp(ss.loc, Id.empty); + sl = new DotIdExp(ss.loc, sl, Id.object); + sl = new DotIdExp(ss.loc, sl, Id.__switch_error); + + Expressions* args = new Expressions(); + args.push(new StringExp(ss.loc, cast(char*) ss.loc.filename)); + args.push(new IntegerExp(ss.loc.linnum)); + + sl = new CallExp(ss.loc, sl, args); + sl.expressionSemantic(sc); + + s = new SwitchErrorStatement(ss.loc, sl); + } else s = new ExpStatement(ss.loc, new HaltExp(ss.loc));