[llvm-bugs] [Bug 34907] New: IA64 ABI: RTTI name for class in anonymous namespace lacks '*', breaks dynamic_cast and type_info::operator== on GNU/Linux
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Oct 10 14:10:14 PDT 2017
https://bugs.llvm.org/show_bug.cgi?id=34907
Bug ID: 34907
Summary: IA64 ABI: RTTI name for class in anonymous namespace
lacks '*', breaks dynamic_cast and
type_info::operator== on GNU/Linux
Product: clang
Version: 5.0
Hardware: PC
OS: Linux
Status: NEW
Severity: enhancement
Priority: P
Component: LLVM Codegen
Assignee: unassignedclangbugs at nondot.org
Reporter: ryan.prichard at gmail.com
CC: llvm-bugs at lists.llvm.org
libstdc++ apparently has a convention where the typeinfo name for a class
declared in an anonymous namespace begins with an asterisk ('*'), which tells
std::type_info::operator== to consider two type_info objects unequal even if
their names are equal. Clang is not outputting this asterisk on GNU/Linux.
Because it's omitted, if I declare two classes with the same name, in two
different anonymous namespaces, the two class types are considered equal
according to std::type_info::operator==, and I can cast from one type to
another with dynamic_cast. G++ outputs the asterisk, so the types are treated
as unequal.
The asterisk is stripped off in GNU's std::type_info::name(), so it's not user
visible.
AFAICT, libc++ doesn't have this convention, but for ARM64 iOS, there is a
different convention of setting the highest(?) bit of the type_info's
__type_name pointer to indicate that string comparison *should* be performed.
(Look for the _LIBCPP_HAS_NONUNIQUE_TYPEINFO and _LIBCPP_NONUNIQUE_RTTI_BIT
flags in libc++. I wonder if ARM64 iOS also sets _LIBCXX_DYNAMIC_FALLBACK for
libc++abi?)
I'm wondering whether there's a compatibility concern here w.r.t. previous
versions of Clang. My first guess is that compatibility with
G++/libstdc++/libsupc++ (and correctness) is sufficient to motivate changing
Clang. I guess Clang would have to generate different code for
-stdlib=libstdc++ and -stdlib=libc++?
Test case:
test.h
#include <typeinfo>
#include <stddef.h>
#include <stdio.h>
struct Base {
virtual ~Base() {}
};
namespace def {
Base *alloc();
const std::type_info &type();
}
test-def.cc
#include "test.h"
namespace {
struct A : Base {};
}
namespace def {
Base *alloc() {
return new A;
}
const std::type_info &type() {
return typeid(A);
}
}
test-run.cc
#include "test.h"
namespace {
struct A : Base {
void func() {
printf("ERROR: run func called, field=%d\n", field);
}
private:
int field = 42;
};
}
__attribute__((noinline))
static A *do_cast(Base *b) {
return dynamic_cast<A*>(b);
}
__attribute__((noinline))
static bool types_eq(const std::type_info &x, const std::type_info &y) {
return x == y;
}
int main() {
printf("def A == run A: %d\n", types_eq(def::type(),
typeid(A)));
printf("&def A == &run A: %d\n", &def::type() == &typeid(A));
printf("name of def A: %s\n", def::type().name());
printf("name of run A: %s\n", typeid(A).name());
printf("def A name == run A name: %d\n", def::type().name() ==
typeid(A).name());
Base *b = def::alloc();
auto *p = do_cast(b);
if (p == nullptr) {
printf("SUCCESS: dynamic_cast returned nullptr\n");
} else {
p->func();
}
#ifdef __GXX_TYPEINFO_EQUALITY_INLINE
printf("__GXX_TYPEINFO_EQUALITY_INLINE = %d\n",
__GXX_TYPEINFO_EQUALITY_INLINE);
#endif
#ifdef __GXX_MERGED_TYPEINFO_NAMES
printf("__GXX_MERGED_TYPEINFO_NAMES = %d\n",
__GXX_MERGED_TYPEINFO_NAMES);
#endif
}
$ cat /etc/issue
Ubuntu 14.04.5 LTS \n \l
$ uname -m
x86_64
$ g++ test-def.cc test-run.cc -std=c++11 && ./a.out
def A == run A: 0
&def A == &run A: 0
name of def A: N12_GLOBAL__N_11AE
name of run A: N12_GLOBAL__N_11AE
def A name == run A name: 0
SUCCESS: dynamic_cast returned nullptr
__GXX_TYPEINFO_EQUALITY_INLINE = 1
__GXX_MERGED_TYPEINFO_NAMES = 0
$ ~/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04/bin/clang++ test-def.cc
test-run.cc -std=c++11 && ./a.out
def A == run A: 1
&def A == &run A: 0
name of def A: N12_GLOBAL__N_11AE
name of run A: N12_GLOBAL__N_11AE
def A name == run A name: 0
ERROR: run func called, field=0
__GXX_TYPEINFO_EQUALITY_INLINE = 1
__GXX_MERGED_TYPEINFO_NAMES = 0
$ g++ test-def.cc -S && cat test-def.s
...
_ZTSN12_GLOBAL__N_11AE:
.string "*N12_GLOBAL__N_11AE"
...
$ ~/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04/bin/clang++ test-def.cc -S && cat
test-def.s
...
_ZTSN12_GLOBAL__N_11AE:
.asciz "N12_GLOBAL__N_11AE"
...
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20171010/486cfa1f/attachment-0001.html>
More information about the llvm-bugs
mailing list