[cfe-dev] lifetime of a variable when goto jumps back past its declaration
Akira Hatanaka via cfe-dev
cfe-dev at lists.llvm.org
Wed Jul 20 12:13:20 PDT 2016
On Wed, Jul 20, 2016 at 12:01 PM, Richard Smith <richard at metafoo.co.uk>
wrote:
> 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.
>
>
Ah right. It's not UB in C but I wasn't sure whether it's UB in C++.
> 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.
>
>
OK, this is a mis-compile only when it's compiled as a C code then.
> 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/b08f862e/attachment.html>
More information about the cfe-dev
mailing list