Closed Quuxplusone closed 14 years ago
Attached 13.cpp
(570 bytes, text/plain): 13.cpp
As I find out the program crashes dues to -inline optimization.
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./opt -inline -S -o after.s before.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./llc before.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gcc -lstdc++ before.s.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./llc after.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gcc -lstdc++ after.s.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
Segmentation fault
Attached before.s
(22817 bytes, text/plain): before.s
Attached before.s
(20328 bytes, text/plain): before.s
Attached after.s
(23406 bytes, text/plain): after.s
Attached after.s
(20921 bytes, text/plain): after.s
I've attached more simple example compiled with -fno-rtti and -fno-exceptions.
I've made an attempt to imitate external functions from libstdc++ to trace every external call and its arguments. To find out the difference between program before and after inliner. But I've failed to do this: the resulting program crashes and I don't understand why.
Do you have any suggestions how to find out what happened within inliner?
Is it possible to inline functions step by step? If it is, I can run program after every inlined function and check whether it works or not.
This is related to vbase initialization, I'll have a look at this.
Do you have any progress with bug? Is it bug in inliner? Will it be fixed before 2.7 release?
(In reply to comment #0)
> The following program (see attachment) crashes when it is compiled with -O2.
>
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -ggdb 13.cpp
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -O2 -ggdb 13.cpp
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gdb a.out
> (gdb) run
> Starting program: /home/ivan/d/llvm-build/Debug/bin/a.out
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007ffff733f719 in free () from /lib/libc.so.6
> (gdb) backtrace
> #0 0x00007ffff733f719 in free () from /lib/libc.so.6
> #1 0x00007ffff7b3656f in std::ios_base::~ios_base() () from
> /usr/lib/libstdc++.so.6
> #2 0x0000000000400eef in main () at 13.cpp:30
>
> If I remove inheritance from fake_base or
> If I remove fake_member member or
> If I compile without -O2
> the program doesn't crash.
>
> Ubuntu 9.10 x86-64.
>
> This bug occur when using boost::format.
>
> I continue my experiments to make more precise bug report.
>
Yeah right, sorry, I don't like firefox.
Can reproduce this, happens only on implicit dtor call (i.e. new/delete the
streamstuff and it does work (for me)).
Cheers anyway.
Marcus
_Bug 6526 has been marked as a duplicate of this bug._
Attached testcase.cc
(246 bytes, text/x-c++src): Testcase from duplicate bug entry
Attached testcase.cc
(101 bytes, text/x-c++src): Reduced testcase
I happens with
#include <sstream>
int main()
{
std::stringstream a;
std::stringstream b;
}
but not with
#include <sstream>
int main()
{
std::istringstream a;
std::istringstream b;
}
or
#include <sstream>
int main()
{
std::ostringstream a;
std::ostringstream b;
}
Reduced testcase:
#include <istream>
int main()
{
std::basic_iostream<char> a;
std::basic_iostream<char> b;
}
It seems to have something to do with multiple inheritance.
Compiling
#include <ios>
template<typename _CharT>
class D : public std::ios_base
{};
template<typename _CharT>
class A : virtual public D<_CharT>
{};
template<typename _CharT>
class B : virtual public D<_CharT>
{
};
template<typename _CharT>
class C : public A <_CharT>,
public B<_CharT>
{
};
int main()
{
C<char> a;
}
with clang++ -o bla bla.cc
fails with:
clang++ -o bla bla.cc
/tmp/cc-Rdw9GJ.o:(.rodata+0x54): undefined reference to `virtual thunk to
B<char>::~B()'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Further reduced:
class E
{
public:
struct _Words {};
_Words _M_word_zero;
virtual ~E() {}
};
template<typename _CharT>
class D : public E
{};
template<typename _CharT>
class A : virtual public D<_CharT>
{};
template<typename _CharT>
class B : virtual public D<_CharT>
{
};
template<typename _CharT>
class C : public A <_CharT>,
public B<_CharT>
{
};
int main()
{
C<char> a;
}
fails with:
/tmp/cc-5LKulY.o:(.rodata+0x54): undefined reference to `virtual thunk to
B<char>::~B()'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Reduced again:
class D {
public:
char c;
virtual ~D() {}
};
class A : virtual public D {};
class B : virtual public D {};
class C : public A, public B {};
int main()
{
C a;
}
Difference between g++ and clang++ generated .o files:
g++:
00000000 W _ZTv0_n12_N1BD0Ev
00000000 W _ZTv0_n12_N1BD1Ev
clang++:
U _ZTv0_n12_N1BD0Ev
00000000 W _ZTv0_n12_N1BD1Ev
It seems that one thunk is not generated.
Similarily:
struct A {
virtual void f();
};
int main()
{
A a;
}
gives:
/tmp/cc-tBz301.o: In function `A::A()':
a.cc:(.gnu.linkonce.t._ZN1AC2Ev+0x11): undefined reference to `vtable for A'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Shouldn't the error message be something like:
"warning: Unimplemented virtual method" and no error, since constructing should
work?
(In reply to comment #22)
> Shouldn't the error message be something like:
> "warning: Unimplemented virtual method" and no error, since constructing
should
> work?
I am not an expert, but I think no. As I know vtable is placed in object file
that define first non-inline virtual member function of class.
If there is no any non-inline virtual member function vtable is marked "inline"
and is placed in all object files.
(In reply to comment #23)
> (In reply to comment #22)
> > Shouldn't the error message be something like:
> > "warning: Unimplemented virtual method" and no error, since constructing
should
> > work?
>
> I am not an expert, but I think no. As I know vtable is placed in object file
> that define first non-inline virtual member function of class.
>
> If there is no any non-inline virtual member function vtable is marked
"inline"
> and is placed in all object files.
In your case vtable will be placed in object file that has definition of A::f.
_Bug 6669 has been marked as a duplicate of this bug._
(In reply to comment #20)
> Reduced again:
>
> class D {
> public:
> char c;
> virtual ~D() {}
> };
> class A : virtual public D {};
> class B : virtual public D {};
> class C : public A, public B {};
>
> int main()
> {
> C a;
> }
Works now (as of 99391).
(In reply to comment #22)
> Similarily:
>
> struct A {
> virtual void f();
> };
>
> int main()
> {
> A a;
> }
>
> gives:
>
> /tmp/cc-tBz301.o: In function `A::A()':
> a.cc:(.gnu.linkonce.t._ZN1AC2Ev+0x11): undefined reference to `vtable for A'
> collect2: ld returned 1 exit status
> clang: error: linker command failed with exit code 1 (use -v to see
invocation)
>
> Shouldn't the error message be something like:
> "warning: Unimplemented virtual method" and no error, since constructing
should
> work?
Works with clang++ -O2 and -O3, doesn't work with -O1 or without optimization,
also doesn't work with g++ regardless of optimization.
(In reply to comment #19)
> Further reduced:
>
> class E
> {
> public:
> struct _Words {};
> _Words _M_word_zero;
>
> virtual ~E() {}
> };
>
> template<typename _CharT>
> class D : public E
> {};
>
> template<typename _CharT>
> class A : virtual public D<_CharT>
> {};
>
> template<typename _CharT>
> class B : virtual public D<_CharT>
> {
> };
>
> template<typename _CharT>
> class C : public A <_CharT>,
> public B<_CharT>
> {
> };
>
> int main()
> {
> C<char> a;
> }
Works, too.
(In reply to comment #28)
> (In reply to comment #19)
> > Further reduced:
> >
> > class E
> > {
> > public:
> > struct _Words {};
> > _Words _M_word_zero;
> >
> > virtual ~E() {}
> > };
> >
> > template<typename _CharT>
> > class D : public E
> > {};
> >
> > template<typename _CharT>
> > class A : virtual public D<_CharT>
> > {};
> >
> > template<typename _CharT>
> > class B : virtual public D<_CharT>
> > {
> > };
> >
> > template<typename _CharT>
> > class C : public A <_CharT>,
> > public B<_CharT>
> > {
> > };
> >
> > int main()
> > {
> > C<char> a;
> > }
>
> Works, too.
Works regardless of optimization.
(In reply to comment #18)
> Compiling
>
> #include <ios>
>
> template<typename _CharT>
> class D : public std::ios_base
> {};
>
> template<typename _CharT>
> class A : virtual public D<_CharT>
> {};
>
> template<typename _CharT>
> class B : virtual public D<_CharT>
> {
> };
>
> template<typename _CharT>
> class C : public A <_CharT>,
> public B<_CharT>
> {
> };
>
> int main()
> {
> C<char> a;
> }
Works.
(In reply to comment #17)
> Reduced testcase:
>
> #include <istream>
>
> int main()
> {
> std::basic_iostream<char> a;
> std::basic_iostream<char> b;
> }
Works with -O1, fails with -O2:
*** glibc detected *** ./bla: free(): invalid pointer: 0x4011f7e0 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0x401d5ff1]
/lib/tls/i686/cmov/libc.so.6[0x401d76f2]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x401da7cd]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x400ec6f1]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0x400ec74d]
/usr/lib/libstdc++.so.6(_ZNSt6locale5_ImplD1Ev+0x7d)[0x4008ba8d]
/usr/lib/libstdc++.so.6(_ZNSt6localeD1Ev+0x4c)[0x4008c09c]
/usr/lib/libstdc++.so.6(_ZNSt8ios_baseD2Ev+0x61)[0x40089041]
./bla[0x8048d77]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x40181b56]
./bla[0x8048c21]
Attached bugpoint-reduced-simplified.ll
(42654 bytes, application/octet-stream): Testcase
(In reply to comment #32)
> Created an attachment (id=4578) [details]
> Testcase
>
> Testcase from
>
> #include <istream>
> int main()
> {
> std::basic_iostream<char> a;
> std::basic_iostream<char> b;
> }
>
> reduced with bugpoint that fails with "opt bugpoint-reduced-simplified.bc
> -simplifycfg -inline -o opted.bc".
> It doesn't fail with only -simplifycfg or -inline.
Gcc doesn't like the C++ file:
/usr/include/c++/4.4/istream: In function ‘int main()’:
/usr/include/c++/4.4/istream:798: error: ‘std::basic_iostream<_CharT,
_Traits>::basic_iostream() [with _CharT = char, _Traits =
std::char_traits<char>]’ is protected
bla.cc:5: error: within this context
/usr/include/c++/4.4/istream:798: error: ‘std::basic_iostream<_CharT,
_Traits>::basic_iostream() [with _CharT = char, _Traits =
std::char_traits<char>]’ is protected
bla.cc:6: error: within this context
(In reply to comment #17)
> Reduced testcase:
>
> #include <istream>
>
> int main()
> {
> std::basic_iostream<char> a;
> std::basic_iostream<char> b;
> }
This doesn't work with gcc, please use the program from comment 16.
Turns out this wasn't a vtable bug at all.
Committed revision 99829.
13.cpp
(570 bytes, text/plain)before.s
(22817 bytes, text/plain)after.s
(23406 bytes, text/plain)before.s
(20328 bytes, text/plain)after.s
(20921 bytes, text/plain)testcase.cc
(246 bytes, text/x-c++src)testcase.cc
(101 bytes, text/x-c++src)bugpoint-reduced-simplified.ll
(42654 bytes, application/octet-stream)