From 3819ceeeecbe6d7daab94a3ab27d84c7eab6e372 Mon Sep 17 00:00:00 2001 From: k-hara Date: Wed, 21 May 2014 22:26:02 +0900 Subject: [PATCH] fix Issue 2456 - "cannot put catch statement inside finally block", missing line number --- src/statement.c | 28 +++++++- test/fail_compilation/fail2456.d | 110 +++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 test/fail_compilation/fail2456.d diff --git a/src/statement.c b/src/statement.c index cc048d591413..3f8be2b96a4b 100644 --- a/src/statement.c +++ b/src/statement.c @@ -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 @@ -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; } } @@ -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; diff --git a/test/fail_compilation/fail2456.d b/test/fail_compilation/fail2456.d new file mode 100644 index 000000000000..0dce9294a3c6 --- /dev/null +++ b/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 + } +}