Skip to content

Commit

Permalink
[-v2] check for case fall-through
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Jun 26, 2014
1 parent cf4f837 commit 6d277c0
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
50 changes: 47 additions & 3 deletions src/statement.c
Expand Up @@ -218,6 +218,10 @@ int Statement::blockExit(bool mustNotThrow)
return BEany;
}

Statement *Statement::last()
{
return this;
}

/****************************************
* If this statement has code that needs to run in a finally clause
Expand Down Expand Up @@ -622,6 +626,22 @@ ReturnStatement *CompoundStatement::isReturnStatement()
return rs;
}

Statement *CompoundStatement::last()
{
Statement *s = NULL;

for (size_t i = statements->dim; i; --i)
{ s = (*statements)[i - 1];
if (s)
{
s = s->last();
if (s)
break;
}
}
return s;
}

void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
for (size_t i = 0; i < statements->dim; i++)
Expand All @@ -635,12 +655,35 @@ int CompoundStatement::blockExit(bool mustNotThrow)
{
//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
int result = BEfallthru;
Statement *slast = NULL;
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (*statements)[i];
if (s)
{
//printf("result = x%x\n", result);
//printf("%s\n", s->toChars());
//printf("result = x%x\n", result);
//printf("%s\n", s->toChars());
if (global.params.Dversion >= 3 && // sc->module && sc->module->isRoot() && /* doesn't have sc */
result & BEfallthru && slast)
{
slast = slast->last();
if (slast && (slast->isCaseStatement() || slast->isDefaultStatement()) &&
(s->isCaseStatement() || s->isDefaultStatement()))
{
// Allow if last case/default was empty
CaseStatement *sc = slast->isCaseStatement();
DefaultStatement *sd = slast->isDefaultStatement();
if (sc && (!sc->statement->hasCode() || sc->statement->isCaseStatement()))
;
else if (sd && (!sd->statement->hasCode() || sd->statement->isCaseStatement()))
;
else
{
const char *gototype = s->isCaseStatement() ? "case" : "default";
s->warning("switch case fallthrough not allowed in D2, insert 'goto %s;'", gototype);
}
}
}

if (!(result & BEfallthru) && !s->comeFrom())
{
if (s->blockExit(mustNotThrow) != BEhalt && s->hasCode())
Expand All @@ -651,6 +694,7 @@ int CompoundStatement::blockExit(bool mustNotThrow)
result &= ~BEfallthru;
result |= s->blockExit(mustNotThrow);
}
slast = s;
}
}
return result;
Expand Down Expand Up @@ -2615,7 +2659,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
if (global.params.Dversion >= 3 &&
sc->module && sc->module->isRoot()
)
warning("switch statement without a default is not allowed in D2; add 'default: assert(0);' or add 'default: break;'");
warning("switch statement without a default is not allowed in D2; add 'default: assert(0);'");
else
warning("switch statement has no default");

Expand Down
2 changes: 2 additions & 0 deletions src/statement.h
Expand Up @@ -116,6 +116,7 @@ struct Statement : Object
virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
virtual Statements *flatten(Scope *sc);
virtual Expression *interpret(InterState *istate);
virtual Statement *last();
virtual bool apply(sapply_fp_t fp, void *param);

virtual int inlineCost(InlineCostState *ics);
Expand Down Expand Up @@ -194,6 +195,7 @@ struct CompoundStatement : Statement
bool hasCodeImpl();
Statements *flatten(Scope *sc);
ReturnStatement *isReturnStatement();
Statement *last();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);

Expand Down

0 comments on commit 6d277c0

Please sign in to comment.