$ cat >test.cpp #include <typeinfo> #include <iostream> using std::cerr; using std::endl; bool operator== (std::type_info const* pa, std::type_info const& b) { return *pa == b; } struct A { virtual ~A () {} }; struct APtr { APtr (A* p) : p_ (p) { } A& operator* () const { return *p_; } private: A* p_; }; int main () { APtr ap (new A); for(bool cont__ = true; cont__;) { cerr << "outer: cont__ " << cont__ << endl; for(std::type_info const* const exp__ ((&typeid (*ap))); cont__; cont__ = false) { cerr << "inner: cont__ " << cont__ << endl; if(cont__ && exp__ == (typeid (int)) && (cont__ = false, true)) { cerr << "condition" << endl; } } } } $ g++ --version g++ (GCC) 3.3.2 (Debian) $ g++ ./test.cpp $ ./a.out outer: cont__ 1 inner: cont__ 1 $ g++ -O ./test.cpp $ ./a.out # will result in infinite loop outer: cont__ 1 inner: cont__ 1 inner: cont__ 1 inner: cont__ 1 inner: cont__ 1 inner: cont__ 1 inner: cont__ 1 ^C $
Here is the smallest I could get it, also it is a regression from 3.0.4: //#define __GXX_MERGED_TYPEINFO_NAMES #include <typeinfo> extern "C" void exit(int); bool operator== (std::type_info const* pa, std::type_info const& b) { return *pa == b; } struct A { virtual ~A () {} }; struct APtr { APtr (A* p) : p_ (p) { } A& operator* () const { return *p_; } private: A* p_; }; void f(void){exit(1);} int main () { APtr ap (new A); for(bool cont__ = true; cont__;) { for(std::type_info const* const exp__ ((&typeid (*ap))); cont__; cont__ = false) { if(cont__ && exp__ == (typeid (int))) { f(); } } } }
A slightly smaller test case: #include <typeinfo> #include <iostream> struct A { virtual ~A () {} }; struct APtr { APtr (A* p) : p_ (p) { } A& operator* () const { return *p_; } A* p_; }; int main () { APtr ap (new A); std::type_info const* const exp = &typeid (*ap); for (bool cont = true; cont; cont = false) { std::cout << "inner: cont " << cont << std::endl; if (exp) ; } }
Created attachment 5268 [details] Self-contained testcase.
This is a C++ problem I think. It appears that the 'A' object is constructed twice (or that two instances are constructed if this is the intended behaviour), the first time for APtr ap (new A); and the second time for if (exp) The first instance is never used, only the second one through 'typeid'. The problem is the following: because A has a vtable, a 'jump' instruction is emitted inside the constructor to another insn of this constructor. Now the 'jump' inside the *second* constructor points to the insn which is targeted by the 'jump' inside the *first* constructor, that is the 'label' of the first constructor was reused for the second constructor. After that, all hell breaks loose.
On tree-ssa, the optimization phases delete the store to cont for some reason!
Subject: Bug 12815 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2004-01-06 00:52:12 Modified files: gcc/cp : ChangeLog class.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/rtti: typeid4.C Log message: PR c++/12816 * class.c (build_vtbl_ref_1): Do not unconditionally mark vtable references as constant. PR c++/12815 * g++.dg/rtti/typeid4.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3856&r2=1.3857 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/class.c.diff?cvsroot=gcc&r1=1.591&r2=1.592 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3339&r2=1.3340 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/rtti/typeid4.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 12815 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2004-01-06 00:52:38 Modified files: gcc/cp : ChangeLog Log message: PR c++/12815 * class.c (build_vtbl_ref_1): Do not unconditionally mark vtable references as constant. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3857&r2=1.3858
Fixed in GCC 3.4.
Subject: Bug 12815 CVSROOT: /cvs/gcc Module name: gcc Changes by: jason@gcc.gnu.org 2004-01-13 00:01:47 Modified files: gcc/cp : ChangeLog class.c Log message: PR c++/12815 * class.c (build_base_path): Do not mark vtable references as TREE_CONSTANT. (build_vtbl_ref_1): Likewise. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3872&r2=1.3873 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/class.c.diff?cvsroot=gcc&r1=1.594&r2=1.595
fixed also for 3.3.3