| 
 | 1 | +//===----------------------------------------------------------------------===//  | 
 | 2 | +//  | 
 | 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  | 
 | 4 | +// See https://llvm.org/LICENSE.txt for license information.  | 
 | 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  | 
 | 6 | +//  | 
 | 7 | +//===----------------------------------------------------------------------===//  | 
 | 8 | + | 
 | 9 | +// We're using `string::starts_with` in this test  | 
 | 10 | +// UNSUPPORTED: c++03, c++11, c++14, c++17  | 
 | 11 | + | 
 | 12 | +// Make sure that the mangling of our public types stays the same  | 
 | 13 | + | 
 | 14 | +// UNSUPPORTED: no-rtti, msvc  | 
 | 15 | + | 
 | 16 | +#include <cassert>  | 
 | 17 | +#include <charconv>  | 
 | 18 | +#include <iostream>  | 
 | 19 | +#include <map>  | 
 | 20 | +#include <typeinfo>  | 
 | 21 | +#include <string>  | 
 | 22 | +#include <string_view>  | 
 | 23 | + | 
 | 24 | +template <class>  | 
 | 25 | +struct mangling {};  | 
 | 26 | + | 
 | 27 | +struct test_struct {};  | 
 | 28 | + | 
 | 29 | +_LIBCPP_BEGIN_NAMESPACE_STD  | 
 | 30 | +struct ns_mangling {};  | 
 | 31 | +_LIBCPP_END_NAMESPACE_STD  | 
 | 32 | + | 
 | 33 | +namespace std::__name {  | 
 | 34 | +struct ns_mangling {};  | 
 | 35 | +} // namespace std::__name  | 
 | 36 | + | 
 | 37 | +namespace std::__long_name_to_make_sure_multiple_digits_work {  | 
 | 38 | +struct ns_mangling {};  | 
 | 39 | +} // namespace std::__long_name_to_make_sure_multiple_digits_work  | 
 | 40 | + | 
 | 41 | +std::string get_std_inline_namespace_mangling(const std::type_info& info) {  | 
 | 42 | +  std::string name = info.name();  | 
 | 43 | +  assert(name.starts_with("NSt"));  | 
 | 44 | +  unsigned name_len;  | 
 | 45 | +  auto res = std::from_chars(name.data() + 3, name.data() + name.size(), name_len);  | 
 | 46 | +  assert(res.ec == std::errc{});  | 
 | 47 | +  return std::move(name).substr(0, (res.ptr + name_len) - name.data());  | 
 | 48 | +}  | 
 | 49 | + | 
 | 50 | +void expect_mangling(const std::type_info& info, std::string expected_name) {  | 
 | 51 | +  if (expected_name != info.name())  | 
 | 52 | +    std::__libcpp_verbose_abort("Expected: '%s'\n     Got: '%s'\n", expected_name.c_str(), info.name());  | 
 | 53 | +}  | 
 | 54 | + | 
 | 55 | +// Mangling names are really long, but splitting it up into multiple lines doesn't make it any more readable  | 
 | 56 | +// clang-format off  | 
 | 57 | +int main(int, char**) {  | 
 | 58 | +  // self-test inline namespace recovery  | 
 | 59 | +  assert(get_std_inline_namespace_mangling(typeid(std::__name::ns_mangling)) == "NSt6__name");  | 
 | 60 | +  assert(get_std_inline_namespace_mangling(typeid(std::__long_name_to_make_sure_multiple_digits_work::ns_mangling)) == "NSt45__long_name_to_make_sure_multiple_digits_work");  | 
 | 61 | + | 
 | 62 | +  // selftest  | 
 | 63 | +  expect_mangling(typeid(test_struct), "11test_struct");  | 
 | 64 | + | 
 | 65 | +  std::string ns_std = get_std_inline_namespace_mangling(typeid(std::ns_mangling));  | 
 | 66 | +  std::string ptrdiff = typeid(std::ptrdiff_t).name();  | 
 | 67 | + | 
 | 68 | +  // std::map  | 
 | 69 | +  expect_mangling(typeid(std::map<int, int>), ns_std + "3mapIiiNS_4lessIiEENS_9allocatorINS_4pairIKiiEEEEEE");  | 
 | 70 | +  expect_mangling(typeid(std::map<int, int>::iterator), ns_std + "14__map_iteratorINS_15__tree_iteratorINS_12__value_typeIiiEEPNS_11__tree_nodeIS3_PvEE" + ptrdiff +"EEEE");  | 
 | 71 | +  expect_mangling(typeid(std::map<int, int>::const_iterator), ns_std + "20__map_const_iteratorINS_21__tree_const_iteratorINS_12__value_typeIiiEEPNS_11__tree_nodeIS3_PvEE" + ptrdiff + "EEEE");  | 
 | 72 | + | 
 | 73 | +  return 0;  | 
 | 74 | +}  | 
0 commit comments