@@ -139,19 +139,7 @@ template <typename Variant, typename Char> class is_variant_formattable {
139
139
#endif // FMT_CPP_LIB_VARIANT
140
140
141
141
#if FMT_USE_RTTI
142
-
143
- template <typename OutputIt>
144
- auto write_demangled_name (OutputIt out, const std::type_info& ti) -> OutputIt {
145
- # ifdef FMT_HAS_ABI_CXA_DEMANGLE
146
- int status = 0 ;
147
- size_t size = 0 ;
148
- std::unique_ptr<char , void (*)(void *)> demangled_name_ptr (
149
- abi::__cxa_demangle (ti.name (), nullptr , &size, &status), &std::free);
150
-
151
- string_view demangled_name_view;
152
- if (demangled_name_ptr) {
153
- demangled_name_view = demangled_name_ptr.get ();
154
-
142
+ string_view normalize_libcxx_inline_namespaces (string_view demangled_name_view, char * begin) {
155
143
// Normalization of stdlib inline namespace names.
156
144
// libc++ inline namespaces.
157
145
// std::__1::* -> std::*
@@ -160,13 +148,12 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
160
148
// std::__cxx11::* -> std::*
161
149
// std::filesystem::__cxx11::* -> std::filesystem::*
162
150
if (demangled_name_view.starts_with (" std::" )) {
163
- char * begin = demangled_name_ptr.get ();
164
151
char * to = begin + 5 ; // std::
165
- for (char *from = to, *end = begin + demangled_name_view.size ();
152
+ for (const char *from = to, *end = begin + demangled_name_view.size ();
166
153
from < end;) {
167
154
// This is safe, because demangled_name is NUL-terminated.
168
155
if (from[0 ] == ' _' && from[1 ] == ' _' ) {
169
- char * next = from + 1 ;
156
+ const char * next = from + 1 ;
170
157
while (next < end && *next != ' :' ) next++;
171
158
if (next[0 ] == ' :' && next[1 ] == ' :' ) {
172
159
from = next + 2 ;
@@ -177,12 +164,12 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
177
164
}
178
165
demangled_name_view = {begin, detail::to_unsigned (to - begin)};
179
166
}
180
- } else {
181
- demangled_name_view = string_view (ti. name ());
182
- }
183
- return detail::write_bytes< char >(out, demangled_name_view);
184
- # elif FMT_MSC_VERSION
185
- const string_view demangled_name (ti. name () );
167
+ return demangled_name_view;
168
+ }
169
+
170
+ template < class OutputIt >
171
+ auto normalize_msvc_abi_name (string_view abi_name_view, OutputIt out) {
172
+ const string_view demangled_name (abi_name_view );
186
173
for (size_t i = 0 ; i < demangled_name.size (); ++i) {
187
174
auto sub = demangled_name;
188
175
sub.remove_prefix (i);
@@ -201,6 +188,34 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
201
188
if (*sub.begin () != ' ' ) *out++ = *sub.begin ();
202
189
}
203
190
return out;
191
+ }
192
+
193
+ template <typename OutputIt>
194
+ auto write_demangled_name (OutputIt out, const std::type_info& ti) -> OutputIt {
195
+ # ifdef FMT_HAS_ABI_CXA_DEMANGLE
196
+ int status = 0 ;
197
+ size_t size = 0 ;
198
+ std::unique_ptr<char , void (*)(void *)> demangled_name_ptr (
199
+ abi::__cxa_demangle (ti.name (), nullptr , &size, &status), &std::free);
200
+
201
+ string_view demangled_name_view;
202
+ if (demangled_name_ptr) {
203
+ demangled_name_view = normalize_libcxx_inline_namespaces (demangled_name_ptr.get (), demangled_name_ptr.get ());
204
+ } else {
205
+ demangled_name_view = string_view (ti.name ());
206
+ }
207
+ return detail::write_bytes<char >(out, demangled_name_view);
208
+ # elif FMT_MSC_VERSION && defined(_MSVC_STL_UPDATE)
209
+ return normalize_msvc_abi_name (ti.name (), out);
210
+ # elif FMT_MSC_VERSION && defined(_LIBCPP_VERSION)
211
+ const string_view demangled_name (ti.name ());
212
+ std::string name_copy (demangled_name.size (), ' \0 ' );
213
+ // normalize_msvc_abi_name removes class, struct, union etc that MSVC has in front of types
214
+ name_copy.erase (normalize_msvc_abi_name (demangled_name, name_copy.begin ()), name_copy.end ());
215
+ // normalize_libcxx_inline_namespaces removes the inline __1, __2, etc namespaces libc++ uses for ABI versioning
216
+ // On MSVC ABI + libc++ environments, we need to eliminate both of them.
217
+ const string_view normalized_name = normalize_libcxx_inline_namespaces (name_copy, name_copy.data ());
218
+ return detail::write_bytes<char >(out, normalized_name);
204
219
# else
205
220
return detail::write_bytes<char >(out, string_view (ti.name ()));
206
221
# endif
0 commit comments