Jump to page: 1 2 3
Thread overview
November 05
Hi,

I posted this in another thread but without any response.

This code:

void main(){
     goto Q;
     int x;
     Q:
     writeln("a");
}

Gives me this error: "source_file.d(4): Error: goto skips declaration of variable source.main.x at source_file.d(5)"


Now, if I add a pair of brackets:

void main(){
     {
         goto Q;
         int x;
     }
     Q:
     writeln("a");
}

It works. So Is this a bug?

MatheusBN.
November 06
On Monday, 5 November 2018 at 23:54:59 UTC, MatheusBN wrote:
> Hi,
>
> I posted this in another thread but without any response.
>
> This code:
>
> void main(){
>      goto Q;
>      int x;
>      Q:
>      writeln("a");
> }
>
> Gives me this error: "source_file.d(4): Error: goto skips declaration of variable source.main.x at source_file.d(5)"
>
>
> Now, if I add a pair of brackets:
>
> void main(){
>      {
>          goto Q;
>          int x;
>      }
>      Q:
>      writeln("a");
> }
>
> It works. So Is this a bug?


No, it's not. Consider replacing that int with a type that has a destructor:

struct S { ~this() { /* ... */ } }

void main(){
     goto Q;
     S x;
     Q:
     writeln("a");
} // <---

Now, what should happen at that closing paren is a destructor call, x.__dtor. However, goto jumps over initialization of 'x', which would lead to calling a destructor on an uninitialized value. That's why the compiler disallows such skips.

But here it's fine:

void main(){
     {
         goto Q;
         S x;
     } // <---
     Q:
     writeln("a");
}

because goto jumps over both initialization *and* destruction, i.e. neither would even be performed.

I'm guessing you misunderstood the author of that other thread. What he's saying is that code similar to the *second* version fails. That's what all the commotion is about over there. This simple example obviously works, yet in his more complicated code base something goes wrong.
November 05
On Monday, November 5, 2018 4:54:59 PM MST MatheusBN via Digitalmars-d-learn wrote:
> Hi,
>
> I posted this in another thread but without any response.
>
> This code:
>
> void main(){
>       goto Q;
>       int x;
>       Q:
>       writeln("a");
> }
>
> Gives me this error: "source_file.d(4): Error: goto skips
> declaration of variable source.main.x at source_file.d(5)"
>
>
> Now, if I add a pair of brackets:
>
> void main(){
>       {
>           goto Q;
>           int x;
>       }
>       Q:
>       writeln("a");
> }
>
> It works. So Is this a bug?

All the spec says on the matter is that

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

https://dlang.org/spec/statement.html#goto-statement

In the first case, x exists at the label Q, and its initialization was skipped, so it's clearly illegal. However, in the second case, because of the braces, x does _not_ exist at the label Q, so its initialization was not skipped, so I don't see why it wouldn't be legal based on what the spec says, and I don't see any reason to make it illegal. Conceptually, it's doing exactly what you'd get with a break if the braces were for a loop. However, it is true that the spec could (and probably should) be more specific on the matter.

- Jonathan M Davis



November 06
On Tuesday, 6 November 2018 at 00:14:26 UTC, Jonathan M Davis wrote:
> On Monday, November 5, 2018 4:54:59 PM MST MatheusBN via Digitalmars-d-learn wrote:
>> Hi,
>>
>> I posted this in another thread but without any response.
>>
>> This code:
>>
>> void main(){
>>       goto Q;
>>       int x;
>>       Q:
>>       writeln("a");
>> }
>>
>> Gives me this error: "source_file.d(4): Error: goto skips
>> declaration of variable source.main.x at source_file.d(5)"
>>
>>
>> Now, if I add a pair of brackets:
>>
>> void main(){
>>       {
>>           goto Q;
>>           int x;
>>       }
>>       Q:
>>       writeln("a");
>> }
>>
>> It works. So Is this a bug?
>
> All the spec says on the matter is that
>
> "It is illegal for a GotoStatement to be used to skip initializations."
>
> https://dlang.org/spec/statement.html#goto-statement
>
> In the first case, x exists at the label Q, and its initialization was skipped, so it's clearly illegal. However, in the second case, because of the braces, x does _not_ exist

Just to be clear, when you say "x exists at the label Q", you mean at the same scope, right?

That's interesting but a bit confusing isn't?

And I found a bit strange that in such code, since "x" is never used, why it isn't skipped.

I know it's another language but in C at least in GCC there is no error over such code, so that's my confusion.

Thanks,

MatheusBN.
November 06
On Tuesday, 6 November 2018 at 00:13:52 UTC, Stanislav Blinov wrote:
> But here it's fine:
>
> void main(){
>      {
>          goto Q;
>          S x;
>      } // <---
>      Q:
>      writeln("a");
> }
>
> because goto jumps over both initialization *and* destruction, i.e. neither would even be performed.

I see but at same time I found a bit confusing, because in this case we're just adding a new scope to fix the issue, and like I said to Jonathan, I thought that "x" wouldn't be initialized since it is never used.

Thanks,

MatheusBN.
November 06
On Tuesday, 6 November 2018 at 00:38:01 UTC, MatheusBN wrote:
> On Tuesday, 6 November 2018 at 00:13:52 UTC, Stanislav Blinov wrote:
>> But here it's fine:
>>
>> void main(){
>>      {
>>          goto Q;
>>          S x;
>>      } // <---
>>      Q:
>>      writeln("a");
>> }
>>
>> because goto jumps over both initialization *and* destruction, i.e. neither would even be performed.
>
> I see but at same time I found a bit confusing, because in this case we're just adding a new scope to fix the issue, and like I said to Jonathan, I thought that "x" wouldn't be initialized since it is never used.

It's not as simple as that, that's why I specifically showed the destructor case. Even if you don't see any explicit use, it doesn't mean the compiler doesn't see an implicit one.



November 06
On Tue, 06 Nov 2018 00:33:56 +0000, MatheusBN wrote:
> Just to be clear, when you say "x exists at the label Q", you mean at the same scope, right?

The same or an outer scope. It's also invalid to write:

goto Y;
{
  int x;
  {
    Y:
  }
}

> That's interesting but a bit confusing isn't?
> 
> And I found a bit strange that in such code, since "x" is never used, why it isn't skipped.

Because simple rules are usually easier to understand and implement.

> I know it's another language but in C at least in GCC there is no error over such code, so that's my confusion.

Because C is a horribly unsafe language, far beyond necessary to have a low-level systems language.

In C++, if you skip over `int i = 10;` it's an error, but not if you skip over `int i;`.

Similarly, if you skip over a class variable declaration without an explicit initialization expression, if the class has a constructor or destructor, it's an error.

In D, every variable of every type is initialized unless you opt out. The compiler *could* let you skip over declarations that are void-initialized, but there isn't a huge reason to do so.
November 05
On Monday, November 5, 2018 5:33:56 PM MST MatheusBN via Digitalmars-d-learn wrote:
> On Tuesday, 6 November 2018 at 00:14:26 UTC, Jonathan M Davis
>
> wrote:
> > On Monday, November 5, 2018 4:54:59 PM MST MatheusBN via
> >
> > Digitalmars-d-learn wrote:
> >> Hi,
> >>
> >> I posted this in another thread but without any response.
> >>
> >> This code:
> >>
> >> void main(){
> >>
> >>       goto Q;
> >>       int x;
> >>       Q:
> >>       writeln("a");
> >>
> >> }
> >>
> >> Gives me this error: "source_file.d(4): Error: goto skips
> >> declaration of variable source.main.x at source_file.d(5)"
> >>
> >>
> >> Now, if I add a pair of brackets:
> >>
> >> void main(){
> >>
> >>       {
> >>
> >>           goto Q;
> >>           int x;
> >>
> >>       }
> >>       Q:
> >>       writeln("a");
> >>
> >> }
> >>
> >> It works. So Is this a bug?
> >
> > All the spec says on the matter is that
> >
> > "It is illegal for a GotoStatement to be used to skip initializations."
> >
> > https://dlang.org/spec/statement.html#goto-statement
> >
> > In the first case, x exists at the label Q, and its initialization was skipped, so it's clearly illegal. However, in the second case, because of the braces, x does _not_ exist
>
> Just to be clear, when you say "x exists at the label Q", you mean at the same scope, right?

The scope that x was at is over at the label Q. So, x doesn't exist at the label Q. It has no address at that point. It's not on the stack. It doesn't exist in any sense other than the fact that it happens to be in the source code above it. In fact, the line with x never even ran, so x _never_ existed.

> That's interesting but a bit confusing isn't?

I don't see why.

{
    goto Q;
    int x;
}
Q:

is basically the same thing as

while(1)
{
    break;
    int x;
}

The same thing happens in both cases.

> And I found a bit strange that in such code, since "x" is never used, why it isn't skipped.

It's skipped right over. The goto jumps out of the scope, and the line with

int x;

is never run. In fact, if you compile with -w or -wi, the compiler will give you a warning about unreachable code.

> I know it's another language but in C at least in GCC there is no error over such code, so that's my confusion.

C is a different language, and it's one that generally doesn't care much about safety. It allows all kinds of horrible things that cause bugs. The folks behind D (and the folks behind _most_ languages since C/C++) tend to prefer a greater degree of safety than C provides.

- Jonathan M Davis



November 06
On Tuesday, 6 November 2018 at 01:55:04 UTC, Jonathan M Davis wrote:
>> And I found a bit strange that in such code, since "x" is never used, why it isn't skipped.
>
> It's skipped right over. The goto jumps out of the scope, and the line with
>
> int x;
>
> is never run. In fact, if you compile with -w or -wi, the compiler will give you a warning about unreachable code.

That is exactly my point.

Since "x" it's skipped and never used, it shouldn't just be a warning (unreachable code) instead of an error?

I'm trying to understand why/when such code could give any problem.

On the other hand if the code were:

{
   goto Q:
   int x;

   Q:
   x = 10; // <- Now you are accessing an uninitialized variable.
}

Then I think an error would be ok.

MatheusBN.
November 06
On Tuesday, 6 November 2018 at 01:04:46 UTC, Stanislav Blinov wrote:
> ...Even if you don't see any explicit use, it doesn't mean the compiler doesn't see an implicit one.

Sorry I don't think that I follow that. How a compiler could see an use when it's not being used/invoked on a program like in that snipped?

MatheusBN.
« First   ‹ Prev
1 2 3