_LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT has changed in Xcode 12.2

I cannot find this anywhere in the release notes, but I notice that _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT has changed from Xcode 12.1 to Xcode 12.2 (in __config header).

It's changed from 0 to 1.

This changes the behaviour of std::type_info. In particular I'll point out std::type_info::operator==(). With Xcode 12.1 behaviour is (with me inlining some things to simplify):
Code Block
bool operator==(const type_info& other) const {
return name() == other.name()
|| strcmp(name(), other.name()) == 0;
}


Whereas in Xcode 12.2 it's now:
Code Block
bool operator==(const type_info& other) const {
return name() == other.name();
}


It's gone from pointer equality of const char* name() of each type, with a fallback to comparing the strings themselves, to *only* doing the pointer equality check.

So what that means is, if the two objects you're comparing are actually the same type, but they come from different modules, then now they might not compare ==.

This breaks a bunch of our tests (fortunately just tests at the moment) because the test bundle has its own set of strings which are then different to the main app.

I am wondering if this change was on purpose? It's mentioned nowhere in the release notes of Xcode 12.2 (that I can find) and it's a huge change which will subtly break a lot of things I believe.

I've raised a feedback for this as well: FB8894026
This is worse than I thought. There's actually an issue here if you are using typeid with pointer-to-incomplete-type in two different translation units in the app. clang is not emitting the right symbol linkage for the type info in this case.

Essentially it is LLVM bug 37398 (I cannot link to it because Apple forums disallow me posting links?)

So pasting the example problematic code from that bug:

Code Block
// header.h
struct T;
extern std::type_info const& Info;
// tu_one.cpp
#include "header.h"
std::type_info const& Info = typeid(T*);
// tu_two.cpp
#include "header.h"
struct T {};
int main() {
auto &TI1 = Info;
auto &TI2 = typeid(T*);
assert(TI1 == TI2); // Fails
assert(TI1.hash_code() == TI2.hash_code()); // Fails
}


You can see how this can easily become problematic. Either clang needs fixing, or we need to revert the change to the default of _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT. OR at least let us set our own _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT by not forcing its definition at the top of __config.
_LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT has changed in Xcode 12.2
 
 
Q