summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward Hinnant <hhinnant@apple.com>2013-06-23 19:52:45 +0000
committerHoward Hinnant <hhinnant@apple.com>2013-06-23 19:52:45 +0000
commitb2d1f94e76c016628f868868ed40a53c2b40b6ed (patch)
tree380fa26318d2d3e2b47e29e65034682f0fdd5103
parenteb8d46c54e181eea4d33b96a9a13e2ac0bd329a8 (diff)
I'd no sooner made the last commit when Matthew Dempsky sent me another test case that led me to yet another closely related test case that the current design could not handle. I've now changed the way forward references are handled completely. It wasn't that much code to change. The demangler, when confronted with a forward reference to a template parameter, now parses things twice. During the second parse, all forward references are remembered from the first parse. Test suite updated with new case.
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@184672 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--src/cxa_demangle.cpp63
-rw-r--r--test/test_demangle.cpp2
2 files changed, 16 insertions, 49 deletions
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index e49ab44..19e7027 100644
--- a/src/cxa_demangle.cpp
+++ b/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/test/test_demangle.cpp b/test/test_demangle.cpp
index d024d46..0b582d3 100644
--- a/test/test_demangle.cpp
+++ b/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_",
};