0

Say I have the following code:

int foo () {
    int const x = 0;
    return x;
}

Is the compiler allowed to move x to the global scope?

What about in the following scenaro? Can res2 vary depending on opimizations?

std::set<int const *> addrs;

int foo () {
    int const x = 0;
    addrs.insert(&x);
    return addrs.size();
}

void bar () {
    int res1 = foo();
    int res2 = foo();
}
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • 1
    I would imagine the compiler would replace the first one with `0` every time it is called. – chris Jan 23 '13 at 01:06
  • No, the compiler cannot move x to the global scope. But I don't think that's exactly what you mean. – Benjamin Lindley Jan 23 '13 at 01:06
  • what is the question concerning the second example? – Andy Prowl Jan 23 '13 at 01:08
  • 1
    A compiler will convert your code into an intermediate, where scope means something different then in the front-end form. The question makes no sense. – Mikhail Jan 23 '13 at 01:20
  • @VladLazarenko not really a dupe. (at least not of that question) Note that there *is* a catch to this question which makes it mildly interesting - the UB in the second part. – Luchian Grigore Jan 23 '13 at 01:22
  • Perhaps you're mixing up scope with storage location. Sure, the compiler could keep it in static storage (such as `section .rodata` or `.bss` as if it has been `static const int x = 0;`) instead of materializing it on the stack every call. Of course, you can't depend on this, it's still UB to deref a pointer to an object that's gone out of scope, but yes it might produce different results (symptoms of such a bug) in practice. – Peter Cordes Sep 02 '23 at 22:00

1 Answers1

2

No, the compiler can't move it in global scope, because the variable isn't declared at global scope. Scope isn't the same thing as storage. Scope denotes where the variable can be accessed from - moving it to the global scope would mean that it can be accessed from anywhere, which isn't the case here.

The second part of the program exhibits undefined behavior. addrs contains dangling pointers after the function exits. Because std::set compares the existing pointers on insertion, this is illegal. So I'd say yes, res2 can vary, but because of the UB, not the reason you suspect.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I think it doesn't exhibit UB unless one of those pointers are dereferenced. –  Jan 23 '13 at 01:29
  • @VladLazarenko it does. You can't compare pointers outside of an array (or one past the end). Moreover, operations other than assignment on invalid pointers are illegal (including copying) - it's counter-intuitive, I know, but true. – Luchian Grigore Jan 23 '13 at 01:31
  • 2
    @LuchianGrigore: You can compare unrelated pointers using `std::less` rather than `<`, and therefore you can store them in a set. But your second reason (the pointers being invalid) is enough to make the behaviour undefined. – Mike Seymour Jan 23 '13 at 01:36