public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/37722]  New: destructors not called on computed goto
@ 2008-10-02 20:46 cburger at sunysb dot edu
  2008-10-02 21:23 ` [Bug middle-end/37722] " pinskia at gcc dot gnu dot org
  2009-05-09  8:17 ` scovich at gmail dot com
  0 siblings, 2 replies; 3+ messages in thread
From: cburger at sunysb dot edu @ 2008-10-02 20:46 UTC (permalink / raw)
  To: gcc-bugs

#include <iostream>

struct foo {
    foo() { std::cout << "foo constructed\n"; }
   ~foo() { std::cout << "foo destructed\n"; }
};

enum opcode { NOP, FOO, DONE };

void exec0(const opcode* o) {
    loop: switch (*o) {
        case NOP:          ++o; goto loop;
        case FOO: { foo f; ++o; goto loop; } // f destructed
        case DONE:  return;
    }
}

void exec1(const opcode* o) {
    static void* label[] = { &&NOP, &&FOO, &&DONE };
    goto *label[*o];
    NOP:          ++o;   goto *label[*o];
    FOO: { foo f; ++o;   goto *label[*o]; } // f not destructed
//  FOO: { foo f; ++o; } goto *label[*o];   // work-around
    DONE:  return;
}

int main() {
    const opcode program[] = { NOP, FOO, NOP, NOP, DONE };
    exec0(program);
    exec1(program);
    return 0;
}

Output:
foo constructed
foo destructed
foo constructed

Tested with: 4.3.2, 4.2.4, 4.1.3, 3.4.6
Optimization level makes no difference.
Intel icpc 10.1, 9.1 show the same problem.


-- 
           Summary: destructors not called on computed goto
           Product: gcc
           Version: 4.3.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: cburger at sunysb dot edu
 GCC build triplet: x86_64-linux-gnu
  GCC host triplet: x86_64-linux-gnu
GCC target triplet: x86_64-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37722


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug middle-end/37722] destructors not called on computed goto
  2008-10-02 20:46 [Bug c++/37722] New: destructors not called on computed goto cburger at sunysb dot edu
@ 2008-10-02 21:23 ` pinskia at gcc dot gnu dot org
  2009-05-09  8:17 ` scovich at gmail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2008-10-02 21:23 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #1 from pinskia at gcc dot gnu dot org  2008-10-02 21:22 -------
EH lowering for some reason does not copy the finally part of the try before
the goto.  This also happens with 3.3.


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|c++                         |middle-end
           Keywords|                            |wrong-code
      Known to fail|                            |3.3 4.4.0 4.0.1


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37722


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug middle-end/37722] destructors not called on computed goto
  2008-10-02 20:46 [Bug c++/37722] New: destructors not called on computed goto cburger at sunysb dot edu
  2008-10-02 21:23 ` [Bug middle-end/37722] " pinskia at gcc dot gnu dot org
@ 2009-05-09  8:17 ` scovich at gmail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: scovich at gmail dot com @ 2009-05-09  8:17 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #2 from scovich at gmail dot com  2009-05-09 08:16 -------
Computed gotos can easily make it impossible for the compiler to call
constructors and destructors consistently. This is a major gotcha of computed
gotos for people who have used normal gotos in C++ and expect destructors to be
handled properly. Consider this program, for instance:

#include <stdio.h>
template<int i>
struct foo {
    foo() { printf("%s<%d>\n", __FUNCTION__, i); }
    ~foo() { printf("%s<%d>\n", __FUNCTION__, i); }
};
enum {RETRY, INSIDE, OUTSIDE, EVIL};
int bar(int idx) {
    static void* const gotos[] = {&&RETRY, &&INSIDE, &&OUTSIDE, &&EVIL};
    bool first = true;
    {
    RETRY:
        foo<1> f1;
        if(first) {
            first = false;
            goto *gotos[idx];
        }
    INSIDE:
        return 1;
    }
    if(0) {
        foo<2> f2;
    EVIL:
        return 2;
    }
 OUTSIDE:
    return 0;
}
int main() {
    for(int i=RETRY; i <= EVIL; i++)
        printf("%d\n", bar(i));
    return 0;
}

Not only does it let you jump out of a block without calling destructors, it
lets you jump into one without calling constructors:

$ g++-4.4.0 -Wall -O3 scratch.cpp && ./a.out
foo<1>
foo<1>
~foo<1>
1
foo<1>
~foo<1>
1
foo<1>
0
foo<1>
~foo<2>
2

Ideally, the compiler could analyze possible destinations of the goto
(best-effort, of course) and emit suitable diagnostics:

scratch.cpp:16: warning: computed goto bypasses destructor of 'foo<1> f1'
scratch.cpp:13: warning:   declared here

scratch.cpp:23: warning: possible jump to label 'EVIL'
scratch.cpp:16: warning:   from here
scratch.cpp:22: warning:   crosses initialization of 'foo<2> f2'

In this particular example the compiler should be able to figure out that no
labels reach a live f1 and call its destructor properly. If it's not feasible
to analyze the possible destinations of the computed goto, regular control flow
analysis should at least be able to identify potentially dangerous labels and
gotos, e.g.:

scratch.cpp:16: warning: computed goto may bypass destructor of 'foo<1> f1'
scratch.cpp:13: warning:   declared here

scratch.cpp:23: warning: jump to label 'EVIL'
scratch.cpp:8:  warning:   using a computed goto
scratch.cpp:22: warning:   may cross initialization of 'foo<2> f2'


-- 

scovich at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |scovich at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37722


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-05-09  8:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-02 20:46 [Bug c++/37722] New: destructors not called on computed goto cburger at sunysb dot edu
2008-10-02 21:23 ` [Bug middle-end/37722] " pinskia at gcc dot gnu dot org
2009-05-09  8:17 ` scovich at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).