[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 11:24:50 PDT 2016


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.

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

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/b729bd55/attachment.html>


More information about the cfe-dev mailing list