This is the mail archive of the
gcc-prs@gcc.gnu.org
mailing list for the GCC project.
libstdc++/10448: Bug in dynamic_cast algorithm
- From: sunil dot k dot davasam at intel dot com
- To: gcc-gnats at gcc dot gnu dot org
- Cc: sunil dot k dot davasam at intel dot com
- Date: 22 Apr 2003 01:04:49 -0000
- Subject: libstdc++/10448: Bug in dynamic_cast algorithm
- Reply-to: sunil dot k dot davasam at intel dot com
>Number: 10448
>Category: libstdc++
>Synopsis: Bug in dynamic_cast algorithm
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Apr 22 01:06:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator: sunil dot k dot davasam at intel dot com
>Release: unknown-1.0
>Organization:
>Environment:
UnitedLinux 1.0 (ia64)
>Description:
There is a bug in dynamic_cast algorithm. Based on ABI document, the function __dynamic_cast () takes 4 arguments.
Here is prototype:
extern "C" void* __dynamic_cast ( const void *sub, const abi:: __class_type_info *src, const abi::__class_type_info *dst, std::ptrdiff_t src2dst_offset );
The 4th argument "src2dst_offset" is a static hint about the location of the source subobject with respect to the complete object;
special negative values for 4th argument are:
-1 : no hint
-2 : src is not a public base of dst
-3 : src is a multiple public base type but never a virtual base type.
Gcc compiler generates "-2" for 4th argument for the attached testcase. The testcase passes ,if you just compile and run. But, it fails when we change the value of 4th argument for __dynamic_cast() function from "-2" to "-1". Basically, If we don't provide any hint to dynamic_cast algorithm, it doesn't work properly atleast for this testcase.
I don't know whether gcc compiler generates "-1" for any case, but this is an interoperability problem. Because, if some other compiler generates "-1" and link with gcc libraries, the application gives wrong output or sometimes segmentation fault.
>How-To-Repeat:
cmd> g++ -v
Reading specs from /usr/lib/gcc-lib/ia64-suse-linux/3.2/specs
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --enable-languages=c,c++,f77,objc,java,ada --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit ia64-suse-linux
Thread model: posix
gcc version 3.2
cmd> g++ tt.cpp
cmd> a.out
C3()
C2()
C3()
C2()
C3()
C2()
Catching bad_cast Exception.
cmd> g++ -S tt.cpp
Open the file tt.s and change the 4th argument of __dynamic_cast() function from "-2" to "-1"
cmd> g++ tt.s
cmd> a.out
C3()
C2()
C3()
C2()
C3()
C2()
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="tt.cpp"
Content-Disposition: inline; filename="tt.cpp"
#include <stdio.h>
#include <exception>
#include <typeinfo>
struct C11
{
virtual int f1() { return 11; }
virtual ~C11() {
printf("%sC%d()\n", "~", 11);
}
C11() {
printf("%sC%d()\n", "", 11);
}
};
struct C3
{
virtual int f4() { return 3; }
virtual int f2() { return 3; }
// int i;
C3() {
printf("%sC%d()\n", "", 3);
}
};
struct C2: virtual C3
{
C2() {
printf("%sC%d()\n", "", 2);
}
};
C2 x2_3(C11 *ptrC11)
{
C2 tmp_C2;
tmp_C2 = dynamic_cast<C2 &>(*ptrC11);
return tmp_C2;
}
int main()
{
try {
C2 ref_obj2, tmp_ref_obj2;
C11 *tmp_ref_ptrC11;
tmp_ref_ptrC11 = (C11 *)&ref_obj2;
tmp_ref_obj2 = x2_3(tmp_ref_ptrC11);
} catch(std::bad_cast) {
printf("Catching bad_cast Exception.\n");
}
return 0;
}