Skip to content

Commit

Permalink
fix Issue 2456 - "cannot put catch statement inside finally block", m…
Browse files Browse the repository at this point in the history
…issing line number
  • Loading branch information
9rnsr committed May 23, 2014
1 parent bb9fd7e commit 3819cee
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/statement.c
Expand Up @@ -4396,6 +4396,11 @@ void Catch::semantic(Scope *sc)
//printf("Catch::semantic(%s)\n", ident->toChars());

#ifndef IN_GCC
if (sc->os && sc->os->tok != TOKon_scope_failure)
{
// If enclosing is scope(success) or scope(exit), this will be placed in finally block.
error(loc, "cannot put catch statement inside %s", Token::toChars(sc->os->tok));
}
if (sc->tf)
{
/* This is because the _d_local_unwind() gets the stack munged
Expand Down Expand Up @@ -4425,7 +4430,8 @@ void Catch::semantic(Scope *sc)
if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL)))
{
if (type != Type::terror)
{ error(loc, "can only catch class objects derived from Throwable, not '%s'", type->toChars());
{
error(loc, "can only catch class objects derived from Throwable, not '%s'", type->toChars());
type = Type::terror;
}
}
Expand Down Expand Up @@ -4521,6 +4527,26 @@ Statement *OnScopeStatement::syntaxCopy()

Statement *OnScopeStatement::semantic(Scope *sc)
{
#ifndef IN_GCC
if (tok != TOKon_scope_exit)
{
// scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
// so the generated catch block cannot be placed in finally block.
// See also Catch::semantic.
if (sc->os && sc->os->tok != TOKon_scope_failure)
{
// If enclosing is scope(success) or scope(exit), this will be placed in finally block.
error("cannot put %s statement inside %s", Token::toChars(tok), Token::toChars(sc->os->tok));
return new ErrorStatement();
}
if (sc->tf)
{
error("cannot put %s statement inside finally block", Token::toChars(tok));
return new ErrorStatement();
}
}
#endif

sc = sc->push();
sc->tf = NULL;
sc->os = this;
Expand Down
110 changes: 110 additions & 0 deletions test/fail_compilation/fail2456.d
@@ -0,0 +1,110 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail2456.d(14): Error: cannot put scope(success) statement inside finally block
---
*/
void test_success()
{
try
{
}
finally
{
scope(success) {} // NG
}
}

/*
TEST_OUTPUT:
---
fail_compilation/fail2456.d(31): Error: cannot put scope(failure) statement inside finally block
---
*/
void test_failure()
{
try
{
}
finally
{
scope(failure) {} // NG
}
}

/*
TEST_OUTPUT:
---
---
*/
void test_exit()
{
try
{
}
finally
{
scope(exit) {} // OK
}
}

/*
TEST_OUTPUT:
---
fail_compilation/fail2456.d(64): Error: cannot put scope(success) statement inside scope(success)
fail_compilation/fail2456.d(65): Error: cannot put scope(failure) statement inside scope(success)
fail_compilation/fail2456.d(78): Error: cannot put scope(success) statement inside scope(exit)
fail_compilation/fail2456.d(79): Error: cannot put scope(failure) statement inside scope(exit)
---
*/
void test2456a()
{
scope(success)
{
scope(success) {} // NG
scope(failure) {} // NG
scope(exit) {} // OK
}

scope(failure)
{
scope(success) {} // OK
scope(failure) {} // OK
scope(exit) {} // OK
}

scope(exit)
{
scope(success) {} // NG
scope(failure) {} // NG
scope(exit) {} // OK
}
}

/*
TEST_OUTPUT:
---
fail_compilation/fail2456.d(96): Error: cannot put catch statement inside scope(success)
fail_compilation/fail2456.d(108): Error: cannot put catch statement inside scope(exit)
---
*/
void test2456b()
{
scope(success)
{
try {}
catch {} // NG
}

scope(failure)
{
try {}
catch {} // OK
}

scope(exit)
{
try {}
catch {} // NG
}
}

0 comments on commit 3819cee

Please sign in to comment.