diff options
-rw-r--r-- | libcxxabi/src/cxa_demangle.cpp | 63 | ||||
-rw-r--r-- | libcxxabi/test/test_demangle.cpp | 2 |
2 files changed, 16 insertions, 49 deletions
diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index e49ab445043..19e7027466f 100644 --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -547,7 +547,7 @@ parse_template_param(const char* first, const char* last, C& db) } else { - db.names.push_back("`T_"); + db.names.push_back("T_"); first += 2; db.fix_forward_references = true; } @@ -572,7 +572,7 @@ parse_template_param(const char* first, const char* last, C& db) } else { - db.names.push_back("`" + typename C::String(first, t+1)); + db.names.push_back(typename C::String(first, t+1)); first = t+1; db.fix_forward_references = true; } @@ -4425,51 +4425,6 @@ demangle(const char* first, const char* last, C& db, int& status) } if (status == success && db.names.empty()) status = invalid_mangled_name; - if (status == success && db.fix_forward_references) - { - auto nm = db.names.back().move_full(); - db.names.pop_back(); - size_t p = nm.size(); - while (p != 0) - { - if (nm[--p] == '`') - { - size_t k0 = db.names.size(); - const char* t = parse_template_param(&nm[p+1], &nm[nm.size()], db); - size_t k1 = db.names.size(); - if (t == &nm[p+1]) - { - status = invalid_mangled_name; - return; - } - if (k1 == k0) - { - nm.erase(p, static_cast<std::size_t>(t - &nm[p])); - } - else - { - if (db.names[k0].first.front() == '`') - { - status = invalid_mangled_name; - return; - } - size_t p2 = static_cast<size_t>(t - &nm[p]); - size_t s = db.names[k0].size(); - nm.replace(p, p2, db.names[k0].move_full()); - p2 = p + s; - for (size_t k = k0+1; k < k1; ++k) - { - s = db.names[k].size() + 2; - nm.insert(p2, ", " + db.names[k].move_full()); - p2 += s; - } - for (; k1 > k0; --k1) - db.names.pop_back(); - } - } - } - db.names.push_back(std::move(nm)); - } } template <std::size_t N> @@ -4682,8 +4637,20 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) db.fix_forward_references = false; db.try_to_parse_template_args = true; int internal_status = success; - demangle(mangled_name, mangled_name + std::strlen(mangled_name), db, + size_t len = std::strlen(mangled_name); + demangle(mangled_name, mangled_name + len, db, internal_status); + if (internal_status == success && db.fix_forward_references && + !db.template_param.empty() && !db.template_param.front().empty()) + { + db.fix_forward_references = false; + db.tag_templates = false; + db.names.clear(); + db.subs.clear(); + demangle(mangled_name, mangled_name + len, db, internal_status); + if (db.fix_forward_references) + internal_status = invalid_mangled_name; + } if (internal_status == success) { size_t sz = db.names.back().size() + 1; diff --git a/libcxxabi/test/test_demangle.cpp b/libcxxabi/test/test_demangle.cpp index d024d46a69a..0b582d3bdf4 100644 --- a/libcxxabi/test/test_demangle.cpp +++ b/libcxxabi/test/test_demangle.cpp @@ -29582,6 +29582,7 @@ const char* cases[][2] = {"_Z1rM1GFivEMS_KFivES_M1HFivES1_4whatIKS_E5what2IS8_ES3_", "r(int (G::*)(), int (G::*)() const, G, int (H::*)(), int (G::*)(), what<G const>, what2<G const>, int (G::*)() const)"}, {"_Z1fPU11objcproto1A11objc_object", "f(id<A>)"}, {"_Z1fPKU11objcproto1A7NSArray", "f(NSArray<A> const*)"}, + {"_ZNK1AIJ1Z1Y1XEEcv1BIJDpPT_EEIJS2_S1_S0_EEEv", "A<Z, Y, X>::operator B<X*, Y*, Z*><X, Y, Z>() const"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); @@ -29592,7 +29593,6 @@ const char* invalid_cases[] = "Agentt", "NSoERj5E=Y1[uM:ga", "Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i", - "_ZN8Blizza`d6Memory12voidp_returncvPT_IcEEv", "_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_", }; |