[cfe-dev] lifetime of a variable when goto jumps back past its declaration
John McCall via cfe-dev
cfe-dev at lists.llvm.org
Wed Jul 20 12:41:29 PDT 2016
> On Jul 20, 2016, at 12:13 PM, Akira Hatanaka <ahatanak at gmail.com> wrote:
> On Wed, Jul 20, 2016 at 12:01 PM, Richard Smith <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk>> wrote:
> On Wed, Jul 20, 2016 at 11:24 AM, Akira Hatanaka <ahatanak at gmail.com <mailto: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.
I agree with this analysis.
John.
>
> 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/7ee0e772/attachment.html>
More information about the cfe-dev
mailing list