From b2e601bd743de76c2ab06cf21cc008f5a38c084a Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 28 Mar 2009 14:39:16 +0100 Subject: [PATCH] Add back some enclosing scope-exit information to the frontend to produce proper error messages inside switch statements. --- dmd/statement.c | 25 +++++++++++++++++++++++++ dmd/statement.h | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/dmd/statement.c b/dmd/statement.c index e3da99b6..d440ca7e 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -2238,6 +2238,8 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b) sdefault = NULL; cases = NULL; hasNoDefault = 0; + // LDC + enclosingScopeExit = NULL; } Statement *SwitchStatement::syntaxCopy() @@ -2252,6 +2254,9 @@ Statement *SwitchStatement::semantic(Scope *sc) //printf("SwitchStatement::semantic(%p)\n", this); assert(!cases); // ensure semantic() is only run once + // LDC + enclosingScopeExit = sc->enclosingScopeExit; + condition = condition->semantic(sc); condition = resolveProperties(sc, condition); if (condition->type->isString()) @@ -2404,6 +2409,8 @@ CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) cblock = NULL; bodyBB = NULL; llvmIdx = NULL; + // LDC + enclosingScopeExit = NULL; } Statement *CaseStatement::syntaxCopy() @@ -2416,6 +2423,14 @@ Statement *CaseStatement::semantic(Scope *sc) { SwitchStatement *sw = sc->sw; //printf("CaseStatement::semantic() %s\n", toChars()); + + // LDC + enclosingScopeExit = sc->enclosingScopeExit; + if (enclosingScopeExit != sw->enclosingScopeExit) + { + error("case must be inside the same try, synchronized or volatile level as switch"); + } + exp = exp->semantic(sc); if (sw) { @@ -2500,6 +2515,8 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s) + cblock = NULL; #endif bodyBB = NULL; + // LDC + enclosingScopeExit = NULL; } Statement *DefaultStatement::syntaxCopy() @@ -2511,6 +2528,7 @@ Statement *DefaultStatement::syntaxCopy() Statement *DefaultStatement::semantic(Scope *sc) { //printf("DefaultStatement::semantic()\n"); + if (sc->sw) { if (sc->sw->sdefault) @@ -2518,6 +2536,13 @@ Statement *DefaultStatement::semantic(Scope *sc) error("switch statement already has a default"); } sc->sw->sdefault = this; + + // LDC + enclosingScopeExit = sc->enclosingScopeExit; + if (enclosingScopeExit != sc->sw->enclosingScopeExit) + { + error("default must be inside the same try, synchronized or volatile level as switch"); + } } else error("default not in switch statement"); diff --git a/dmd/statement.h b/dmd/statement.h index 72157a56..43e7224b 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -469,6 +469,9 @@ struct SwitchStatement : Statement Array gotoCases; // array of unresolved GotoCaseStatement's Array *cases; // array of CaseStatement's int hasNoDefault; // !=0 if no default statement + + // LDC + Statement *enclosingScopeExit; SwitchStatement(Loc loc, Expression *c, Statement *b); Statement *syntaxCopy(); @@ -491,6 +494,9 @@ struct CaseStatement : Statement int index; // which case it is (since we sort this) block *cblock; // back end: label for the block + // LDC + Statement *enclosingScopeExit; + CaseStatement(Loc loc, Expression *exp, Statement *s); Statement *syntaxCopy(); Statement *semantic(Scope *sc); @@ -519,6 +525,9 @@ struct DefaultStatement : Statement block *cblock; // back end: label for the block #endif + // LDC + Statement *enclosingScopeExit; + DefaultStatement(Loc loc, Statement *s); Statement *syntaxCopy(); Statement *semantic(Scope *sc);