[cfe-dev] lifetime of a variable when goto jumps back past its declaration

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Wed Jul 20 12:01:00 PDT 2016


On Wed, Jul 20, 2016 at 11:24 AM, Akira Hatanaka <ahatanak at gmail.com> wrote:

> I have a couple of questions regarding lifetime of objects in c and c++.
>
> When I compile the following code and execute it, I get different results
> depending on the optimization level I specify on the command line.
>
> $ cat t1.c
> #include <stdio.h>
> int main(int ac, char** av) {
>   int *p = 0;
>  label1:
>   if (p) {
>     printf("%d\n", *p);
>     return 0;
>   }
>
>   int i = 999;
>   if (ac != 2) {
>     p = &i;
>     goto label1;
>   }
>   return -1;
> }
>
> $ clang t1.c -O0 && ./a.out
> 999
>
> $ clang t1.c -O1 && ./a.out
> 1
>
> It looks like the difference is caused by the lifetime start/end marker
> inserted at -O1. clang inserts lifetime.start at the variable
> initialization and lifetime.end before the jump to label1. Because the
> goto's destination label1 is not in the lifetime range of variable "i", the
> content of "i" gets altered when printf is executed.
>
> This seems like a mis-compile according to the C standard:
>
> "For such an object that does not have a variable length array type, its
> lifetime extends from entry into the block with which it is associated
> until execution of that block ends in any way."
>
> The block with which "i" is associated is the whole function, so "i"
> shouldn't be destroyed when the goto jumps back past its declaration.
>
> Is my understanding correct? I discussed this with a couple of people and
> we all agreed that this looks like an UB as a C code.
>

This seems to contradict what you just said. In C, this example appears to
have defined behavior, and we're miscompiling it.


> What if the code is compiled as a c++ code? Is it still UB?
>

In C++, I'm confident that this is intended to be undefined behavior, but
the standard does not appear to clearly specify that. I've filed a core
issue.

If the variable in question had a non-trivial destructor, it would probably
> be UB. In n3337 6.7, there is a c++ code snippet that shows a goto jumping
> back past the declaration of a variable of type class "X", and it states
> that the variable's destructor gets called when it goes out of scope.
> However, I'm not sure what the rules are for variables that are POD types.
> The standard says in 6.6 Jump Statements that the object gets destructed in
> such cases:
>
> Transfer out of a loop, out of a block, or back past an initialized
> variable with automatic storage duration involves the destruction of
> objects with automatic storage duration that are in scope at the point
> transferred from but not at the point transferred to.
>
> Does "destructed" simply mean a destructor is called? Or it means the
> content of the object is destroyed regardless of whether or nor it's a POD?
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160720/6716a463/attachment.html>


More information about the cfe-dev mailing list