Misleading error if the type in catch() is ambiguous
Dear All, I suspect there is a regression from g++ 4.4 in later versions. If the name of the class is ambiguous in a catch(), this fact is not reported. I had checked bz, but not found this particular case: http://gcc.gnu.org/bugzilla/buglist.cgi?quicksearch=ambiguous Attached a simple test case. The lines of the errors are: 31: ambiguous parent class 37: ambiguous type name for variable 43: ambiguous type name for caught exception I tested on an amd64 machine with Debian Wheezy, stock gcc-4.4, 4.5, 4.6 and 4.7 built from the svn trunk: $g++-4.4 -v Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.6-14' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.6 (Debian 4.4.6-14) $g++-4.4 -c test_gccexbug.cpp test_gccexbug.cpp:31: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17: error: candidates are: class ex2 test_gccexbug.cpp:11: error: class t::ex2 test_gccexbug.cpp:31: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17: error: candidates are: class ex2 test_gccexbug.cpp:11: error: class t::ex2 test_gccexbug.cpp: In function ‘void bar()’: test_gccexbug.cpp:37: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17: error: candidates are: class ex2 test_gccexbug.cpp:11: error: class t::ex2 test_gccexbug.cpp:37: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17: error: candidates are: class ex2 test_gccexbug.cpp:11: error: class t::ex2 test_gccexbug.cpp:37: error: expected ‘;’ before ‘x’ test_gccexbug.cpp:43: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17: error: candidates are: class ex2 test_gccexbug.cpp:11: error: class t::ex2 test_gccexbug.cpp:43: error: expected type-specifier before ‘ex2’ test_gccexbug.cpp:43: error: expected ‘)’ before ‘&’ token test_gccexbug.cpp:43: error: expected ‘{’ before ‘&’ token test_gccexbug.cpp:43: error: expected primary-expression before ‘)’ token test_gccexbug.cpp:43: error: expected ‘;’ before ‘)’ token Note: ambiguity errors are reported twice for lines 31 and 37 and once for line 43. $g++-4.5 -v Using built-in specs. COLLECT_GCC=g++-4.5 COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.5.3/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.5.3-9' --with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.5 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --enable-ld=default --with-plugin-ld=ld.gold --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.5.3 (Debian 4.5.3-9) $g++-4.5 -c test_gccexbug.cpp test_gccexbug.cpp:31:27: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17:1: error: candidates are: class ex2 test_gccexbug.cpp:11:1: error: class t::ex2 test_gccexbug.cpp: In function ‘void bar()’: test_gccexbug.cpp:37:7: error: reference to ‘ex2’ is ambiguous test_gccexbug.cpp:17:1: error: candidates are: class ex2 test_gccexbug.cpp:11:1: error: class t::ex2 test_gccexbug.cpp:37:11: error: expected ‘;’ before ‘x’ test_gccexbug.cpp:43:17: error: expected type-specifier before ‘ex2’ test_gccexbug.cpp:43:20: error: expected ‘)’ before ‘&’ token test_gccexbug.cpp:43:20: error: expected ‘{’ before ‘&’ token test_gccexbug.cpp:43:21: error: expected primary-expression before ‘)’ token test_gccexbug.cpp:43:21: error: expected ‘;’ before ‘)’ token Note: ambiguity is reported once for lines 31 and 37, and no ambiguity is reported for line 43. The error is misleading imho, because it suggests that the type name is not know instead of being ambiguous. I suspect that the fix that removed the duplicate ambiguity messages might have gone a bit too far in the case of the catch(), though I couldn't check this since I'm not familiar with the gcc source. gcc-4.6 and gcc-4.7 (built from the svn trunk, r182460) give the same error as gcc-4.5 above. Regards, Peter // te
Re: Misleading error if the type in catch() is ambiguous
I've submitted a bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51640 Regards, Peter
Re: Misleading error if the type in catch() is ambiguous
Hello, I pinpointed the commit that introduced the bug, see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51640 Regards, Peter
Missed optimization opportunity
Hello, I've come across an issue when working on a smart pointer implementation. Gcc does not seem to propagate constants enough, missing some optimization opportunities. I don't think that this issue is specific to smart pointers, so there might be other cases when gcc generates suboptimal code. Attached a simple test case. The smart pointer here is a unique pointer, always only a single instance holds a raw pointer to the resource. The deletion can be customized through a policy class. In main(), I allocate an int, then pass it through several smart pointers. At the end, the last smart pointer holds the raw pointer to the allocated memory. Compiled as: g++ -g -O3 -o gccoptbug.o -c gccoptbug.cpp g++ -o gccoptbug gccoptbug.o The generated code on AMD64 looks like this: 0x004004d0 <+0>:sub$0x8,%rsp 0x004004d4 <+4>:mov$0x4,%edi 0x004004d9 <+9>:callq 0x4004c0 <_Znwm@plt> ; operator new 0x004004de <+14>:mov%rax,%rdi 0x004004e1 <+17>:callq 0x4004a0 <_ZdlPv@plt> ; operator delete 0x004004e6 <+22>:xor%edi,%edi 0x004004e8 <+24>:callq 0x4004a0 <_ZdlPv@plt> 0x004004ed <+29>:xor%edi,%edi 0x004004ef <+31>:callq 0x4004a0 <_ZdlPv@plt> 0x004004f4 <+36>:xor%edi,%edi 0x004004f6 <+38>:callq 0x4004a0 <_ZdlPv@plt> 0x004004fb <+43>:xor%edi,%edi 0x004004fd <+45>:callq 0x4004a0 <_ZdlPv@plt> 0x00400502 <+50>:xor%eax,%eax 0x00400504 <+52>:add$0x8,%rsp 0x00400508 <+56>:retq The allocated memory is freed, then op delete is called four times with a 0 pointer. The dtor and the called deleter fn was inlined. So far so good. If I modify the deleter policy to call op delete only when the pointer is not zero (#if 1 at line 6), the generated code changes to: 0x004004d0 <+0>:sub$0x58,%rsp 0x004004d4 <+4>:mov$0x4,%edi 0x004004d9 <+9>:callq 0x4004c0 <_Znwm@plt> 0x004004de <+14>:lea0x40(%rsp),%rdi 0x004004e3 <+19>:mov%rax,0x40(%rsp) 0x004004e8 <+24>:movq $0x0,(%rsp) 0x004004f0 <+32>:movq $0x0,0x10(%rsp) 0x004004f9 <+41>:movq $0x0,0x20(%rsp) 0x00400502 <+50>:movq $0x0,0x30(%rsp) 0x0040050b <+59>:callq 0x400630 >::~Ptr()> 0x00400510 <+64>:lea0x30(%rsp),%rdi 0x00400515 <+69>:callq 0x400630 >::~Ptr()> 0x0040051a <+74>:lea0x20(%rsp),%rdi 0x0040051f <+79>:callq 0x400630 >::~Ptr()> 0x00400524 <+84>:lea0x10(%rsp),%rdi 0x00400529 <+89>:callq 0x400630 >::~Ptr()> 0x0040052e <+94>:mov%rsp,%rdi 0x00400531 <+97>:callq 0x400630 >::~Ptr()> 0x00400536 <+102>:xor%eax,%eax 0x00400538 <+104>:add$0x58,%rsp 0x0040053c <+108>:retq Instead of eliminating the calls to op delete, the actual smart ptr objects appear on the stack, and the dtor is not inlined anymore. gcc 4.4 and 4.5 optimizes as expected: 0x00400640 <+0>:sub$0x8,%rsp 0x00400644 <+4>:mov$0x4,%edi 0x00400649 <+9>:callq 0x400540 <_Znwm@plt> 0x0040064e <+14>:test %rax,%rax 0x00400651 <+17>:je 0x40065b 0x00400653 <+19>:mov%rax,%rdi 0x00400656 <+22>:callq 0x400510 <_ZdlPv@plt> 0x0040065b <+27>:xor%eax,%eax 0x0040065d <+29>:add$0x8,%rsp 0x00400661 <+33>:retq 4.6 and 4.7 (r182889) generates the suboptimal code as above. I've checked bugzilla, and #46076 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46076) is related, I guess. There, Jan Hubicka 2010-10-19 03:20:48 UTC writes that main() is optimized for size. To check this, I've added foo() to the test case, and it is optimized correctly w/ 4.6 and 4.7. Moreover, -Os produces the same foo() and main() functions. However, the size optimized version is more than 3 times as large as the other one. Is this normal? Regards, Peter template struct Deleter { static void Delete(T* p_) { #if 0 // if enabled, Delete() is not inlined if (p_) #endif delete p_; } }; template > class Ptr { public: Ptr() : m_ptr(0) { } Ptr(T* p_) : m_ptr(p_) { } Ptr(const Ptr& p_) : m_ptr(p_.Forget()) { } ~Ptr() { D::Delete(m_ptr); } T* Forget() const { T* s = m_ptr; m_ptr = 0; return s; } private: mutable T* m_ptr; }; int main() { typedef Ptr MyPtr; MyPtr p0 = new int; MyPtr p1 = p0; MyPtr p2 = p1; MyPtr p3 = p2; MyPtr p4 = p3; }
multiple destructor calls of static objects
Hello, I ran into a bug with 4.6, when implementing a custom rtti framework, on an Amd64 Debian Wheezy box. It seems that at certain optimization levels, dtors of static objects are called multiple times. Attached a test case. It will print 'DEADBEEF' when the bug is hit. Searched bugzilla for "multiple destructor call", but found nothing relevant. The bug appears with only 4.6.x, and only at -O2, 3 and s. Tested with: * gcc-4.4.7 20111231 (prerelease) (GCC), compiled from source * gcc-4.5.3, stock debian wheezy * gcc-4.6.2, stock debian wheezy * gcc-4.6.3 20120120 (prerelease) (GCC), compiled from source * gcc-4.7.0 20120104 (experimental) (GCC), compiled from source Should I file a bugreport and / or search for the commit that introduced the bug? Regards, Peter #include struct Info { Info(int v_ = 0) : alive(1), var(v_) { printf("%p Info(%d)\n", this, v_); } ~Info() { if (alive) { printf("%p ~Info(%d)\n", this, var); alive = 0; } else { printf("%p ~Info(%d) : DEADBEEF!\n", this, var); } } int alive; int var; }; template inline const Info& foo() { static Info info; return info; } template<> inline const Info& foo() __attribute__((constructor)); template<> inline const Info& foo() { static Info info(1); return info; } template<> inline const Info& foo() __attribute__((constructor)); template<> inline const Info& foo() { static Info info(2); return info; } int main() { printf("> main()\n"); // if both #if's are 1, the dtors will be called multiple times // if compiled w/ gcc 4.6, -Os, -O2 or -O3. // -O0 and -O1 are OK #if 1 foo(); foo(); foo(); #endif #if 1 foo(); foo(); foo(); #endif printf("< main()\n"); return 0; }
Misleading error message with templated c++ code
Hello, compiling the following: ---8<---8<---8<---8<--- template struct Base { typename T::Typevar; }; template struct Derived : Base > { typedef U Type; }; void foo() { Derived i; } ---8<---8<---8<---8<--- gives the error gcctempl.cpp: In instantiation of ‘struct Base >’: gcctempl.cpp:7:8: required from ‘struct Derived’ gcctempl.cpp:13:15: required from here gcctempl.cpp:4:19: error: no type named ‘Type’ in ‘struct Derived’ on all tested gcc versions (4.4, 4.5, 4.6,4.7). There is definitely a type called 'Type' in struct 'Derived'. I'm not sure, the above code might be ill-formed, but then I'd like to see a specific error message. Regards, Peter
array subscript is below array bounds : false positive?
Hello, I've run into this strange warning when compiling w/ optimization: gcc-4.3 -O2 -Werror -Wall -c -o t.o t.c cc1: warnings being treated as errors t.c: In function ‘foo’: t.c:25: error: array subscript is below array bounds gcc-4.4 gives the same warning/error, however, gcc 4.1 and 4.2 compiles the source. gcc-4.1 -v says: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --with-tune=generic --enable-checking=release x86_64-linux-gnu Thread model: posix gcc version 4.1.3 20080704 (prerelease) (Debian 4.1.2-27) gcc-4.2 -v says: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.2.4 (Debian 4.2.4-6) gcc-4.3 -v says: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.4-2' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.3.4 (Debian 4.3.4-2) gcc-4.4 -v says: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.1-1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-objc-gc --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.1 (Debian 4.4.1-1) t.c is : >8>8>8>8>8>8>8>8>8>8 #define ASSERT(x) if (x) { } else { __asm__("int $0x03"); } #define SIZE5 char hnd[SIZE]; char flg[SIZE]; char crd(); int idx(char); void set(int i, char v); #if 1 void set(int i, char v) { ASSERT(i >=0 && i < SIZE); flg[i] = v; } #endif void foo() { char c = crd(); int i = idx(0); ASSERT(i != -1); hnd[i] = c; // array subscript is below array bounds set(i, 1); } >8>8>8>8>8>8>8>8>8>8 Suppose that idx(c) returns the position of c in an array, an the return value of -1 means that c is not in the array. The assertion checks that. The funny thing is, if I change the source a bit, the warning goes away: 1) set '#if 1' to '#if 0' so that only the prototype of set() is visible 2) comment out the ASSERT() int set() 3) comment out ASSERT() just before the marked line 4) comment out set(i, 1) just after the marked line The warning is not present under -O2. Is this warning legal? Cheers, Peter
Compiler error w/ templates and default argument value
Hello All, I've run into this: 8<8<8< template class B { protected: static const int i = 42; }; template class D : protected B { public: D(int n_ = B::i); // line 12 }; 8<8<8< gcc-4.1 and 4.3 give the same error message: t.cpp:12: error: expected ‘,’ or ‘...’ before ‘>’ token t.cpp:12: error: wrong number of template arguments (1, should be 2) t.cpp:2: error: provided for ‘template class B’ t.cpp:12: error: default argument missing for parameter 2 of ‘DA>::D(int, A)’ If I write D(int n_ = (B::i) ), then it compiles. Imho it should compile w/o the extra parentheses. VC++ 2008 Express compiled it. Wanted to test gcc 4.4, too, but I wasn't able to compile the 20081003 snapshot (/usr/include/gnu/stubs.h:7:27: error: gnu/stubs-32.h: No such file or directory). I have a debian lenny/amd64 system. Regards, P
Possible optimizer bug?
Hello all, I've run today into an infinite loop when compiled a test suite w/ optimizations. The original tests were to do some loops with all the nonnegative values of some integral types. Instead of hardwiring the max values, I thought testing for overflow into the negative domain is ok. Here is the source to reproduce the bug: 8<8<8<8< #include #include int f(int(*ff)(int)) { int8_t i = 0; /* the real loop counter */ int ii = 0; /* loop counter for the test */ do { if (ff(ii)) { /* test ii through a fn ptr call */ printf("ouch!\n"); /* too many loops */ return ii; } ++ii; } while (++i > 0); /* * the loop should stop when i overflows from 0x7f to * 0x80 (ie -128) : 128 iterations * if optimizations are enabled, it won't stop. */ return 0; } extern int g_tr; int foo(int i) { return i > g_tr; } int main(void) { f(&foo); return 0; } int g_tr = 0x200; 8<8<8<8< The call through the function pointer to test the loop counter is only for disabling inlining. If i put everything into f(), it just prints "ouch" and returns 0x201, the loop is optimized away completely. The expected behaviour is present (stopping after 128 iterations) if compiled w/ -O0 or -O1, however, -O2 and above, and -Os result in an infinite loop. The disassembly has an unconditional jump instruction after incrementing the loop counter. Tested on: Debian Lenny (i386 and amd64), gcc 4.1, 4.2 and 4.3. Compile as: $ gcc -g -O2 t.c then run as $ ./a.out Is the above code considered illegal, or is it an issue with the optimizer? Regards, Peter
Failed access check
Hello, clang gave an error on a code that compiled with gcc so far. The reduced test case is: 8<8<8<8<--- class V; struct E { E(const V& v_); char* c; V* v; int i; }; class V { private: union { char* c; struct { V* v; int i; }; }; }; E::E(const V& v_) : c(v_.c), // line 25 v(v_.v), i(v_.i) { } 8<8<8<8<--- Tried with gcc 4.4, 4.5, 4.6, 4.7, 4.8, all gave the same error: gcc-4.8 -c gccaccessbug.cpp -Wall -Wextra gccaccessbug.cpp: In constructor ‘E::E(const V&)’: gccaccessbug.cpp:16:9: error: ‘char* Vc’ is private gccaccessbug.cpp:25:7: error: within this context Line 25 is where E::c is initialized, V::c is private so the error is due. However, V::v and V::i are also private, but no diagnostic is given. If I comment out 'c(v_.c)', the source compiles w/o error. Should I file a bug report? Checked BZ for 'access control', but found nothing relevant, only bugs related to templated code. Regards, Peter
Re: Failed access check
On 04/23/2012 08:20 PM, Jonathan Wakely wrote: On 23 April 2012 18:48, Ian Lance Taylor wrote: "Peter A. Felvegi" writes: Should I file a bug report? Yes, please. Thanks. Please check it's not http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24926 first Hello, it seems to be the same issue, quite dated, though. Regards, Peter
Insufficient access check for private static member in base class
Hello, I've bumped into the following: 8<8<8<8< class Base { static int foo; }; #if 0 class Deriv : public Base { public: int Foo() { return foo; } }; #endif template class DerivT : public Base { public: int Foo() { return foo; } }; void bar() { DerivT dt; dt.Foo(); } 8<8<8<8< All versions I've tried (4.4, 4.5, 4.6, 4.7) compiles the code. clang gives proper diagnostic stating that Base::foo is private. If base::foo is not static, gcc catches the error, too: gccacbug.cpp: In member function ‘int DerivT::Foo() [with T = void]’: gccacbug.cpp:25: instantiated from here gccacbug.cpp:4: error: ‘int Base::foo’ is private gccacbug.cpp:19: error: within this context If I enable the non-templated Deriv class, I get an error (twice): gccacbug.cpp: In member function ‘int Deriv::Foo()’: gccacbug.cpp:3:13: error: ‘int Base::foo’ is private gccacbug.cpp:10:21: error: within this context gccacbug.cpp:3:13: error: ‘int Base::foo’ is private gccacbug.cpp:10:21: error: within this context Searching bugzilla for 'static member access' didn't give any results. Should I file a bug report? Regards, Peter
error: call of overloaded ‘foo(int)’ is ambiguous (0 vs null ptr)
Hello, I'm not sure whether this is standard behaviour or not; nonetheless I was quite surprised: 8<8<8< void foo(long); void foo(const char*); void bar() { foo(0); foo(0+0); // ! foo(1-1); // ! foo(1); } 8<8<8< The first call to foo() in bar() is ambiguous, all right (integral or ptr), but the next two (marked w/ !) ? Shouldn't the compiler know that 0+0 or 1-1, etc can't be a null pointer? I tried all minor versions from 4.4 to 4.8. Somewhat connected question: if I use |-Wzero-as-null-pointer-constant to detect cases where 0 means null pointer, shouldn't there be a switch that forbids conversion from 0 to null ptr? I have a class that has operator() overloaded for size_t and for const char* (access elements by index or by name). All is well, except for the index 0: the call would be ambiguous. I tried to trick this with 0+0, etc, hence the whole post. 0.0 works, though. Any better ideas? Explicit cast? Supposing that I eliminated all 0's that meant null ptr, using the switch could eliminate this kind of ambiguity, and I could use 0 where I mean 0, without any trickery. Regards, Peter |
Code optimization: warning for code that hangs
Hello, I bumped into a strange bug today: the program hang at a point, inspecting the disassembly revealed that it was a single jmp instruction which jumped onto itself. Most of the code from the C++ function was missing. The bug occurs at -O2 or -O3, -O1 generates correct code. The function itself didn't change recently, but some referenced classes did; earlier the code was correct even at -O3. It turned out that during maintenance, an infinite recursion creeped in. At -O1, the program crashed with SIGSEGV as expected due to exhausting the stack. Details: The original structure looked like this: struct J; struct S { J& m_root; S(J& j) : m_root(j) {} void Dump(Printer&); }; struct J { S m_root; J() : m_root(*this) {} S& GetRoot() { return m_root; } void Dump(Printer& p) { m_root.Dump(p); } }; An S is embedded in J, and J::Dump() is forwarded to it. Then, some minor changes occured: instead of embedding S, inheritance was used: struct J : S { // m_root removed J() : S(*this); // GetRoot() removed void Dump(Printer& p) { m_root.Dump(p); } }; Accidentally, J::Dump() was not removed, and by the incident that both S and J had an m_root member in the first version, m_root.Dump(p) called itself in an infinite recursion. Here is the test case: 8<---8<8<---8<8<---8<8<---8<--- struct J; struct S { J& j; S(J& j_) : j(j_) { } voidF() { } }; struct J : S { J() : S(*this) { } voidF() { j.F(); } }; void foo() { J j; j.F(); } int main() { foo(); } 8<---8<8<---8<8<---8<8<---8<--- The generated code at -O3 is: (gdb) disassemble foo Dump of assembler code for function foo(): 0x00400470 <+0>:jmp0x400470 End of assembler dump. -O1 is interesting: (gdb) disassemble foo Dump of assembler code for function foo(): 0x0040046c <+0>:subrsp,0x18 0x00400470 <+4>:learax,[rsp] 0x00400474 <+8>:movQWORD PTR [rsp],rax 0x00400478 <+12>:movrdi,rsp 0x0040047b <+15>:call 0x400498 0x00400480 <+20>:addrsp,0x18 0x00400484 <+24>:ret End of assembler dump. So far so good, but J::F() is strange: Dump of assembler code for function J::F(): 0x00400498 <+0>:subrsp,0x8 0x0040049c <+4>:movrax,QWORD PTR [rdi] 0x0040049f <+7>:movrax,QWORD PTR [rax] 0x004004a2 <+10>:movrax,QWORD PTR [rax] 0x004004a5 <+13>:movrax,QWORD PTR [rax] 0x004004a8 <+16>:movrax,QWORD PTR [rax] 0x004004ab <+19>:movrax,QWORD PTR [rax] 0x004004ae <+22>:movrax,QWORD PTR [rax] 0x004004b1 <+25>:movrax,QWORD PTR [rax] 0x004004b4 <+28>:movrdi,QWORD PTR [rax] 0x004004b7 <+31>:call 0x400498 0x004004bc <+36>:addrsp,0x8 0x004004c0 <+40>:ret End of assembler dump. What are those mov rax,QWORD PTR [rax]'s ? My question is: wouldn't it be possible to print a warning when a jmp to itself or trivial infinite recursion is generated? The code compiled fine w/ -Wall -Wextra -Werror w/ 4.6 and 4.7. Cheers, Peter
Re: Code optimization: warning for code that hangs
Hello, So far so good, but J::F() is strange: Dump of assembler code for function J::F(): 0x00400498 <+0>:subrsp,0x8 0x0040049c <+4>:movrax,QWORD PTR [rdi] 0x0040049f <+7>:movrax,QWORD PTR [rax] 0x004004a2 <+10>:movrax,QWORD PTR [rax] 0x004004a5 <+13>:movrax,QWORD PTR [rax] 0x004004a8 <+16>:movrax,QWORD PTR [rax] 0x004004ab <+19>:movrax,QWORD PTR [rax] 0x004004ae <+22>:movrax,QWORD PTR [rax] 0x004004b1 <+25>:movrax,QWORD PTR [rax] 0x004004b4 <+28>:movrdi,QWORD PTR [rax] 0x004004b7 <+31>:call 0x400498 0x004004bc <+36>:addrsp,0x8 0x004004c0 <+40>:ret End of assembler dump. What are those mov rax,QWORD PTR [rax]'s ? No comments on this part? Shouldn't the optimizer eliminated a few of those loads? Regards, Peter
Regression: incorrect line numbers in debug info since 4.5+
Hello, I found out while single stepping a new template function in gdb that gcc generates bad/inaccurate line numbers in the debug info. Optimization was turned off, but the execution jumped strangely, see below. gcc-4.4 and the current clang produced the expected results, gcc 4.5, 4.6, 4.7, 4.8 all had problems. The code was factored out from a proof-of-concept hack. Here is the trace that was produced in gdb by single stepping the program with 'n'. The program was compiled w/ gcc 4.8.0 git commit e7ae865c: COLLECT_GCC=gcc-4.8.0 COLLECT_LTO_WRAPPER=/home/usr-local/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ./configure --enable-languages=c,c++ --program-suffix=-4.8.0 Thread model: posix gcc version 4.8.0 20120605 (experimental) (GCC) g++-4.8.0 -g -O0 -Wall -Wextra -o dbginfobug.o -c dbginfobug.cpp g++-4.8.0 -g -o dbginfobug dbginfobug.o 11 while (C c = *f++) { 12 if (c == '$') { 56 if (o < e) { 57 *o = c; 59 ++o; // the first anomaly: the line printed is AFTER the loop, while we're still in the loop // this happens only with 4.8, after each iteration 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') { 56 if (o < e) { 57 *o = c; 59 ++o; 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); ... 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') { 13 C c2 = *f; 14 if (c2 == '$') { 18 unsigned ai = gai; 19 if (c2 == '{') { 20 ++f; 21 C c3 = *f; 22 if (c3 >= '0' && c3 <= '9') { 23 ai = 0; 24 while (C c4 = *f) { 25 if (c4 < '0' || c4 > '9') { 28 ai *= 10; 29 ai += c4 - '0'; 30 ++f; 24 while (C c4 = *f) { 25 if (c4 < '0' || c4 > '9') { // doesn't stop on the break with 4.8, stops with earlier versions // !!! we should be after the closing brace of the loop, yet we're still inside 30 ++f; (gdb) p c4 // this is quite a gotcha: c4 of type C is not in the scope anymore, but some constant // of type mynumber creeps in the scope from libm. // this wasn't too helpful understanding what's going on... $16 = {i = {1431655765, -1079683755}, x = -0.041664} (gdb) p f $17 = 0x400a18 "}\n" 36 C x = *f++; // f was not incremented (correctly), despite it stood on the line ++f (gdb) p f $18 = 0x400a18 "}\n" 37 if (x == '}') { // now it stops on this break. what's the difference compared to the above if() where it didn't stop? 38 break; 62 printf("RESULT (%zu chars): '%s'\n", o - buf, buf); 11 while (C c = *f++) { 12 if (c == '$') { I attached the cpp source, and also the preprocessed version, if it makes any difference. I couldn't find anything similar in bz, please let me know whether this is a new issue and I will file a bugreport. Regards, Peter #include #include template void do_print(C* buf, size_t siz, const C* fmt) { const C* f = fmt; C* o = buf; C* e = buf + siz; unsigned gai = 0; while (C c = *f++) { if (c == '$') { C c2 = *f; if (c2 == '$') { ++f; goto lit; } unsigned ai = gai; if (c2 == '{') { ++f; C c3 = *f; if (c3 >= '0' && c3 <= '9') { ai = 0; while (C c4 = *f) { if (c4 < '0' || c4 > '9') { break; } ai *= 10; ai += c4 - '0'; ++f; } } else { ++gai; } do { C x = *f++; if (x == '}') { break; } if (x == 0) { fprintf(stderr, "ERROR: no closing brace\n"); return; } if (x == 'f') { break; } else { fprintf(stderr, "ERROR: invalid format specifier char '%c'\n", x); return; } } while (1); } else { ++gai; } } else { lit: if (o < e) { *o = c; } ++o; } } printf("RESULT (%zu chars): '%s'\n", o - buf, buf); } void fo
Re: Regression: incorrect line numbers in debug info since 4.5+
Hello, Which version of GDB? As documented at http://gcc.gnu.org/gcc-4.5/changes.html GCC now generates unwind info also for epilogues. DWARF debuginfo generated by GCC now uses more features of DWARF3 than before, and also some DWARF4 features. GDB older than 7.0 is not able to handle either of these, so to debug GCC 4.5 generated binaries or libraries GDB 7.0 or later is needed. You can disable use of DWARF4 features with the -gdwarf-3 -gstrict-dwarf options, or use -gdwarf-2 -gstrict-dwarf to restrict GCC to just DWARF2, but epilogue unwind info is emitted unconditionally whenever unwind info is emitted. I was using 7.4.1, under Debian Wheezy, amd64. Tried the dwarf 2 options, but then I wasn't even able to step into the template function from foo(): when hitting step on the function name, the next line was the fn closing brace, in asm it jumped from preparing the reg args to the leaveq after the call. When stepped inside the fn via si, the first 'next' attempt failed gdb saying that the fn contained no line number info, and stopped at the outer leaveq as before. With dwarf-3 and 4, the already reported buggy behaviour occured when single stepping the function. Regards, Peter
Re: Regression: incorrect line numbers in debug info since 4.5+
The bug is at: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53770 Regards, Peter
Regression/bug in 4.7 regarding typedef in templated class
Hello, after upgrading gcc one of my classes failed to compile. Stock Debian/Wheezy 4.4, 4.5, 4.6 compiled the code, also compiled a version of 4.7.0 that was built by me from sources some time ago. Clang 3.0-6 also compiled, but stock 4.7.1-7, the head of 4.7 (4.7.3 d51dc77f, r192839) and the head of master (4.8.0 1a2798ac, r192875) didn't. Reduced the code to a test case: 8<8<8<8<8<8<8< class Id { public: Id(); Id(char a, char b); explicitId(int v); Id(const char* id_); }; template class Foo { public: // typedef ID IdType; void Bar(const ID& id_); typedef ID IdType; }; template void Foo::Bar(const IdType& id_) //void Foo::Bar(const ID& id_) { } void foo() { Foo f; f.Bar("hello"); } 8<8<8<8<8<8<8< $ g++ -c gcctypedef.cpp gcctypedef.cpp: In function ‘void foo()’: gcctypedef.cpp:29:15: error: no matching function for call to ‘Foo::Bar(const char [6])’ gcctypedef.cpp:29:15: note: candidate is: gcctypedef.cpp:21:6: note: void Foo::Bar(const IdType&) [with ID = Id; Foo::IdType = Id] gcctypedef.cpp:21:6: note: no known conversion for argument 1 from ‘const char [6]’ to ‘Id&’ 4.8 gives the same error, but in prettier, more verbose format. If the typedef in class Foo is _before_ the Bar fn declaration, gcc compiles the code. If instead of the typedef (IdType) the original type (ID) is used in the argument of the Bar fn at the definition, gcc compiles the code. I git bisect'd the commit that introduced the regression/bug: commit 44f861fca343148a1b0720105ec2b7f14bbcc849 Author: jason Date: Wed Feb 8 09:52:11 2012 + PR c++/52035 * pt.c (tsubst): Strip uninstantiated typedef. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184000 138bc75d-0d04-0410-961f-82ee72b054a4 I didn't find anything relevant in Bugzilla when searching for 'typedef template'. Should I file a bug report? Kind regards, Peter
Copy constructor access check while initializing a reference
hello, i've found this in the known non-bugs list (http://gcc.gnu.org/bugs.html#known), after running into the issue. gcc 3.4-4.2 gives a compile error, but 4.3 compiles it. is this a regression, or the rules were relaxed somewhat (c++0x?) ? i checked the changelog, but couldn't find any relevant entries there. could someone explain the rationale behind this extra access check, please? i'm puzzled, since the copy ctor is not needed and is not called from the generated code. regards, p signature.asc Description: OpenPGP digital signature
va_list bug?
hello, please try the little program at the end. my naive assumption was that it will print "hello world" two times. if compiled with gcc 3.4, 4.1, 4.2 or 4.3 for i386, it will print "hello world" two times all right. however, if compiled with 3.3, 3.4, 4.1 or 4.3 for amd64, the second time it will print "hello @[EMAIL PROTECTED]" (garbage). it seems that the gp_offset field of the va struct gets modified by someone, so the second vprintf prints garbage: vp (fmt=0x400672 "hello %s\n", args=0x7fff0e83aec0) at v.c:6 6 vprintf(fmt, args); (gdb) display *args 1: *args = {gp_offset = 8, fp_offset = 48, overflow_arg_area = 0x7fff0e83afa0, reg_save_area = 0x7fff0e83aee0} (gdb) n hello world 7 vprintf(fmt, args); 1: *args = {gp_offset = 16, fp_offset = 48, overflow_arg_area = 0x7fff0e83afa0, reg_save_area = 0x7fff0e83aee0} i don't know whether this is a gcc issue or a libc issue, but i suspect that it's a bug. please clarify. i have a debian etch amd64 system, glibc is 2.3.6. searching for "gcc glibc variadic argument bug" didn't give any relevant pages. regards, peter 8<8<8<8<8<8<8<8<8< #include #include void vp(const char* fmt, va_list args) { vprintf(fmt, args); vprintf(fmt, args); } void p(const char* fmt, ...) { va_list args; va_start(args, fmt); vp(fmt, args); va_end(args); } int main() { p("hello %s\n", "world"); } signature.asc Description: OpenPGP digital signature
can't reinterpret_cast to/from the same type
hello, i don't know if it's a bug, please clarify: rc.cpp: --8<-- void f() { int x = 0; int y = reinterpret_cast(x); } --8<-- gcc -v: Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) gcc -c rc.cpp: rc.cpp: In function ‘void f()’: rc.cpp:4: error: invalid cast from type ‘int’ to type ‘int’ i suspected that one could cast from int to int. google hasn't found any relevant pages for 'gcc reinterpret cast bug' regards, peter
function overloading and variadic arguments
hello, today i've spent a few hours debugging... consider the following code: >8>8>8>8>8>8 // test.cpp #include #include int prn(const char* fmt_); int prn(const char* fmt_, ...) __attribute__((format(printf, 1, 2))); int prn(const char* fmt_, va_list args_); int prn(const char* fmt_) { return 0; } int prn(const char* fmt_, ...) { va_list args; va_start(args, fmt_); int r = prn(fmt_, args); va_end(args); return r; } int prn(const char* fmt_, va_list args_) { char out[4096]; return vsnprintf(out, sizeof(out), fmt_, args_); } int main(int argc_, char** argv_) { int s0 = prn("%s %s", "hello", "world"); int s1 = prn("hello %s", "world"); int s2 = prn("hello %s", argv_[0]); int s3 = prn("hello %d", 42); return 0; } >8>8>8>8>8>8 it turns out, that when initializing s1, the function with the va_list second arg is called, not the variadic version, which results in a sigsegv. tried gcc-2.95, 3.3, 4.1 and 4.2, with -Wall -W[extra]. 4.2 warns about the deprecated conversion from string constant to char* (which needs some interpretation), but the others are silent about the issue. a warning would be nice, if the compiler detects that there's an ambiguity: passing an argument that would fit the variadic and the va_list (or any other type) argument versions of the functions, too. the solution is to name the functions differently, but unfortunately pinning down the source of the bug took me quite some time (the original code was more complex of course ;) i'd like to hear your comments. regards, p
Re: function overloading and variadic arguments
>> i'd like to hear your comments. > > Is va_list a typedef for char* on your system, then? What ever happened to > it being an alias for __builtin_va_list via __gnuc_va_list? i don't know what happened, but it seems like a char*. my system is a debian i636 etch, here are compiler versions: $ gcc-4.3-exp -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: ./configure --program-suffix=-4.3-exp Thread model: posix gcc version 4.3.0 20070914 (experimental) (GCC) gives 'warning: deprecated conversion from string constant to ‘char*’' $ gcc-4.2 -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: ./configure --program-suffix=-4.2 Thread model: posix gcc version 4.2.1 gives the same warning $ gcc-4.1 -v Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) no warning $ gcc-3.3 -v Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/specs Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --enable-__cxa_atexit --with-system-zlib --enable-nls --without-included-gettext --enable-clocale=gnu --enable-debug i486-linux-gnu Thread model: posix gcc version 3.3.6 (Debian 1:3.3.6-15) no warning regards, p
ctor style cast vs c style cast
hello all, today i've run into this: if i cast a double value to an unsigned int using the C style cast when passing it to printf, it's fine. however, if i use the ctor style cast, i get a compile error. in theory, these two should do the same: create a temporary unsigned int, and assign the double to it after conversion, just the syntax is different. made a little test, see attachment. plain int's are ok, but when qualified with signed/unsigned the error occurs. i can't judge whether this is an error or not, please clarify. $ gcc -v Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release x86_64-linux-gnu Thread model: posix gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) regards, p void f(int i) { } void g(unsigned int j) { } class X { public: X(double); }; void t() { // named variables with ctor syntax : all ok int i1(1.0); signed int i2(1.0); unsigned int i3(1.0); const int ci1(1.0); const signed int ci2(1.0); const unsigned int ci3(1.0); // unnamed temporaries with ctor syntax int(1.0); signed int(1.0); // error unsigned int(1.0); // error const int(1.0); // error const signed int(1.0); // error const unsigned int(1.0); // error // unnamed temporaries with C style cast (signed int)(1.0); (unsigned int)(1.0); (const signed int)(1.0); (const unsigned int)(1.0); // named variable and unnamed temporary of class X X x(1.0); X(1.0); const X cx(1.0); const X(1.0); // new ctor style casts f(int(1.0)); f(signed int(1.0)); // error g(unsigned int(1.0)); // error // old c style casts f((int)1.0); f((signed int)1.0); g((unsigned int)1.0); } signature.asc Description: OpenPGP digital signature