struct A { ~this() {} }
void test(int x)
{
{
A a;
goto END;
}
A b;
END:
}
Error: cannot `goto` into `try` block
I know that behind the scenes the code above will end in two imbricated try/finally blocks because of RAII, but:
- the error message is misleading, there is no finally block in the original code;
- this is a legal goto equivalent with a return which should be allowed, it's not like jumping in a middle of another scope (which also shows the same misleading error message).
Comment #1 by razvan.nitu1305 — 2021-03-16T12:25:41Z
Actually, the goto is not legal because it skips the declaration of b. For example, this does not compile:
struct A { /*~this() {}*/ }
void test(int x)
{
{
A a;
goto END;
}
A b;
END:
}
onlineapp.d(7): Error: goto skips declaration of variable onlineapp.test.b at onlineapp.d(9)
Commenting b makes the code compile both with and without the destructor. It seems that the error message somehow gets swallowed.
Comment #2 by rumbu — 2021-03-18T20:12:47Z
The error message is not swallowed because the code is lowered in a 'try {goto} finally', therefore there is no b declaration to jump over in the same scope as goto after lowering.
If you replace the goto with a simple return, it is allowed. Skipping b declaration is perfectly legit as long as b destructor is skipped, that's how the return instruction will be lowered:
void test(int x)
{
A a = 0;
try
{
return;
}
finally
a.~this();
A b = 0;
b.~this();
}
The problem is that the original code is lowered to:
void test(int x)
{
A a = 0;
try
{
goto END;
}
finally
a.~this();
A b = 0;
END:
b.~this();
}
instead of the correct lowering:
void test(int x)
{
A a = 0;
try
{
goto END;
}
finally
a.~this();
A b = 0;
b.~this();
END:
}
By the way, the C++ compiler (MSVC) lowers the same code like this, which is fine:
void test(int x)
{
{
A a = {};
~a;
goto END:
}
A b = {};
~b;
END:;
}
Comment #3 by nick — 2023-02-06T17:35:02Z
run.dlang.io gives:
2.075.1 to 2.087.1: Failure with output: onlineapp.d(7): Error: `goto` skips declaration of variable `onlineapp.test.b` at onlineapp.d(9)
Since 2.088.1: Failure with output: onlineapp.d(7): Error: cannot `goto` into `try` block
Possibly related to Issue 20096:
https://github.com/dlang/dmd/pull/10266
Comment #4 by robert.schadek — 2024-12-13T19:15:05Z