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