Is it allowed to jump to a label that's inside an inner scope or a sibling scope? If so, is it allowed to use variables declared in that scope?
Consider this code:
int cond(void);
void use(int);
void foo()
{
{
int y = 2;
label:
use(y);
}
{
int z = 3;
use(z);
/* jump to sibling scope: */ if(cond()) goto label;
}
/* jump to inner scope: */ if(cond()) goto label;
}
Are these goto
s legal?
If so, is y
guaranteed to exist when I jump to label
and to hold the last value assigned to it (2
)?
Or is the compiler allowed to assume y
won't be used after it goes out of scope, which means a single memory location may be used for both y
and z
?
If this code's behavior is undefined, how can I get GCC to emit a warning about it?
Labels are the only identifiers that have function scope: they can be used (in a goto statement) anywhere in the same function in which they appear.
A goto statement is allowed to jump within the scope of a variable length array, but not past any declarations of objects with variably modified types. The following example shows a goto statement that is used to jump out of a nested loop. This function could be written without using a goto statement.
The goto statement can be used to jump from anywhere to anywhere within a function.
"The GOTO statement is generally considered to be a poor programming practice that leads to unwieldy programs. Its use should be avoided."
From the C99 standard (emphasis mine):
6.2.4 Storage durations of objects
[6] For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration. ... If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.
6.8.6.1 The
goto
statement[1] The identifier in a
goto
statement shall name a label located somewhere in the enclosing function. Agoto
statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.[4] ... A
goto
statement is not allowed to jump past any declarations of objects with variably modified types.
y
is not a variably modified type, so, according to the standard, the jumps are legal.
y
is guaranteed to exist, however, the jumps skip the initialization (y = 2
), so the value of y
is indeterminate.
You can use -Wjump-misses-init
to get GCC to emit a warning like the following:
warning:
jump skips variable initialization [-Wjump-misses-init]
In C++, the jumps are not legal, C++ does not allow to skip the initialization of y
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With