Thread overview
goto skipping declarations
6 days ago
claptrap
5 days ago
Dennis
3 days ago
Walter Bright
3 days ago
Walter Bright
2 days ago
Derek Fawcus
3 days ago
Walter Bright
6 days ago

void foo(bool x)
{
goto END;
uint what;
END:
}

> >

onlineapp.d(15): Error: goto skips declaration of variable onlineapp.foo.what
goto END;
^

void foo(bool x)
{
{
goto END;
uint what;
}
END:
}

runs fine.

I think it's correct behaviour, if the goto is jumping out of its scope, its OK to skip declarations in that scope, since they cant be accessed outside it.

But the documentation doesn't specify this behaviour. It just says...

"It is illegal for a GotoStatement to be used to skip initializations."

it should say something like "It is illegal for a GotoStatement to be used to skip initializations within its containing scope."

5 days ago

On Tuesday, 16 September 2025 at 04:57:33 UTC, claptrap wrote:

>

But the documentation doesn't specify this behaviour. It just says...

Thanks for reporting, I've created an issue for it: https://github.com/dlang/dlang.org/issues/4310

If you find more spec improvements, please post them there as well.

3 days ago
The compiler errs on the side of conservatism with this. It's worth filing a bug report for, but would be a low priority.
3 days ago
gcc does not produce an error:

```c
int foo(int x)
{
        goto END;
        int what;
    END: return what;
}
```

so D is still doing better! D gives an error. (ImportC does not give an error, on purpose!)
3 days ago
https://x.com/WalterBright/status/1968830567191036334
3 days ago

On Friday, 19 September 2025 at 00:02:53 UTC, Walter Bright wrote:

>

gcc does not produce an error:

int foo(int x)
{
        goto END;
        int what;
    END: return what;
}

so D is still doing better! D gives an error. (ImportC does not give an error, on purpose!)

int foo(int x) {
      goto END;
      int what = 0;
    END:
      return what;
    }

Does yield an error:

<source>: In function 'int foo(int)':
<source>:5:5: error: jump to label 'END'
    5 |     END:
      |     ^~~
<source>:3:12: note:   from here
    3 |       goto END;
      |            ^~~
<source>:4:11: note:   crosses initialization of 'int what'
    4 |       int what = 0;
      |           ^~~~
Compiler returned: 1

So the skipping of initialization is technically caught, it's just that D default initializes and C does not.

Let's try D code that doesn't initialize:

int foo(int x) {
      goto END;
      int what = void;
    END:
      return what;
    }

Same error. I still like the D mechanism better, as it's very likely you didn't mean to do this, and it's generally better to avoid this problem.

-Steve

2 days ago

On Friday, 19 September 2025 at 02:03:57 UTC, Steven Schveighoffer wrote:

>

On Friday, 19 September 2025 at 00:02:53 UTC, Walter Bright wrote:

>

gcc does not produce an error:

Yup, and has done for a while - one just needs to enable the errors (it is a bit sad that '-Wall' stopped having things added, so creating '-Wextra'):

$ gcc-11 -Wall -Wextra -Werror -c skip.c
skip.c: In function ‘foo’:
skip.c:1:13: error: unused parameter ‘x’ [-Werror=unused-parameter]
    1 | int foo(int x) {
      |         ~~~~^
skip.c:5:14: error: ‘what’ is used uninitialized [-Werror=uninitialized]
    5 |       return what;
      |              ^~~~
cc1: all warnings being treated as errors

The complaint about 'what' happens with '-Wall' alone. If one used gcc-12 and later, it also states where 'what' is declared.