For a variable declared in the initializer of a for loop, the destructor of the object runs prior to the first iteration of the loop. This is incorrect -- the dtor should run only when exiting the loop's scope.
Created attachment 5579 [details] testcase $ c++ -v Reading specs from /usr/gcc-ssa/lib/gcc/i686-pc-linux-gnu/3.5-tree-ssa/specs Configured with: ../gcc/configure --prefix=/usr/gcc-ssa --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --enable-languages=c,c++ --host=i686-pc-linux-gnu Thread model: posix gcc version 3.5-tree-ssa 20040125 (merged 20040102) $ c++ -o test_loop test_loop.cpp $ ./test_loop A ctor A dtor iteration 0 A ctor A dtor iteration 1 A ctor A dtor expected output: A ctor iteration 0 A ctor A dtor iteration 1 A ctor A dtor A dtor No optimization flags are needed in order to reproduce this bug.
Confirmed. The problem is here: struct A a; __comp_ctor (&a, i); try { } finally { __comp_dtor (&a); }
Confirmed indeed. And just to make sure that we don't have any copy constructors running: ------------------- #include <stdio.h> struct A { A(int val) : mValue(val) { printf("A ctor\n"); } A(const A&a) : mValue(a.mValue) { printf("A copy ctor\n"); } ~A() { printf("A dtor\n"); } int mValue; }; int main() { int i = 0; for (A a = A(i); a.mValue != 2; a = A(++i)) { printf("iteration %d\n", i); } } ------------------------- When run this never produces the "A copy ctor" output. This may well be the cause of some memory corruption people have seen in their codes when using tree-ssa. W.
This testcase is even simpler: #include <stdio.h> class A { public: A() { printf("A ctor\n"); } ~A() { printf("A dtor\n"); } }; int main(int argc, char **argv) { int i = 0; for (A a; i < 2; ++i) { printf("iteration %d\n", i); } return 0; } which outputs: A ctor A dtor iteration 0 iteration 1 instead of: A ctor iteration 0 iteration 1 A dtor
Okay this is a problem with the expanders from C++ front-end trees to gimple. Jason I know that you are the person who did gimplify for the C++ front. It looks like for's are being expanded wrong.
The example in comment #4 is not a very good one, since the variable "a" is only live in the first part of the for-statement. It could thus legitimitaly be destroyed even before the first iteration. That wasn't the case with the first example, though. W.
I can't even see how to begin fixing this. The precise semantic meaning of CLEANUP_EXPR eludes me. Jason, it's all yours.
Subject: Bug 13865 CVSROOT: /cvs/gcc Module name: gcc Branch: tree-ssa-20020619-branch Changes by: jason@gcc.gnu.org 2004-01-30 04:34:45 Modified files: gcc : ChangeLog.tree-ssa c-simplify.c Log message: PR c++/13865 * c-simplify.c (gimplify_for_stmt): Reorganize to fix cleanups. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.tree-ssa.diff?cvsroot=gcc&only_with_tag=tree-ssa-20020619-branch&r1=1.1.2.1138&r2=1.1.2.1139 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-simplify.c.diff?cvsroot=gcc&only_with_tag=tree-ssa-20020619-branch&r1=1.1.4.89&r2=1.1.4.90
Subject: Bug 13865 CVSROOT: /cvs/gcc Module name: gcc Changes by: jason@gcc.gnu.org 2004-01-30 04:35:27 Added files: gcc/testsuite/g++.dg/init: for1.C Log message: PR c++/13865 * c-simplify.c (gimplify_for_stmt): Reorganize to fix cleanups. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/init/for1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed by Jason's patch: http://gcc.gnu.org/ml/gcc-patches/2004-01/msg03358.html