https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103240
Bug ID: 103240 Summary: std::type_info::before gives wrong answer for ARM EABI Product: gcc Version: 12.0 Status: UNCONFIRMED Keywords: ABI Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- Target: arm*-*-*gnueabi This passes on x86_64 but fails on armv7hl: // f1.C #include <typeinfo> namespace { struct S { }; } std::type_info const& t1 = typeid(S); // f2.C #include <typeinfo> #include <cassert> extern std::type_info const& t1; namespace { struct S { }; } std::type_info const& t2 = typeid(S); int main() { if (t1 == t2) { assert( !t1.before(t2) ); assert( !t2.before(t1) ); } else { assert( t1.before(t2) || t2.before(t1) ); } } $ g++ f1.C f2.C $ ./a.out a.out: f2.C:22: int main(): Assertion `t1.before(t2) || t2.before(t1)' failed. qemu: uncaught target signal 6 (Aborted) - core dumped Aborted (core dumped) The problem is in libsupc++/tinfo2.cc bool type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT { #if __GXX_MERGED_TYPEINFO_NAMES return name () < arg.name (); #else return (name ()[0] == '*') ? name () < arg.name () : __builtin_strcmp (name (), arg.name ()) < 0; #endif } This should have been fixed like operator== was in r179236 so that it checks __name[0] not name()[0], otherwise the '*' is skipped and so is never found there. That means we do a strcmp comparison of the mangled names, even when the '*' says the types must be compared by pointer address. In the testcase the two structs have the same mangled name, even though they are distinct types (due to the unnamed namespaces). The string comparison therefore returns 0, and so neither type is "before" the other, despite being distinct types.