diff options
Diffstat (limited to 'source/Core/Mangled.cpp')
-rw-r--r-- | source/Core/Mangled.cpp | 302 |
1 files changed, 284 insertions, 18 deletions
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index a41986de5143..55bd3cbb8e99 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -20,17 +20,10 @@ #ifdef LLDB_USE_BUILTIN_DEMANGLER -#include <vector> -#include <algorithm> -#include <string> -#include <numeric> -#include <cstdlib> -#include <cstring> -#include <cctype> //---------------------------------------------------------------------- // Inlined copy of: // http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp -// revision 193704. +// revision 199944. // // Changes include: // - remove the "__cxxabiv1" namespace @@ -38,8 +31,32 @@ // - removed extern "C" from the cxa_demangle function // - Changed the scope of the unnamed namespace to include cxa_demangle // function. +// - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning //---------------------------------------------------------------------- +#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below + +//===-------------------------- cxa_demangle.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define _LIBCPP_EXTERN_TEMPLATE(...) +#define _LIBCPP_NO_EXCEPTIONS + +#include <vector> +#include <algorithm> +#include <string> +#include <numeric> +#include <cstdlib> +#include <cstring> +#include <cctype> + + namespace { @@ -558,6 +575,8 @@ parse_template_param(const char* first, const char* last, C& db) { if (first[1] == '_') { + if (db.template_param.empty()) + return first; if (!db.template_param.back().empty()) { for (auto& t : db.template_param.back().front()) @@ -580,7 +599,7 @@ parse_template_param(const char* first, const char* last, C& db) sub *= 10; sub += static_cast<size_t>(*t - '0'); } - if (t == last || *t != '_') + if (t == last || *t != '_' || db.template_param.empty()) return first; ++sub; if (sub < db.template_param.back().size()) @@ -615,6 +634,8 @@ parse_const_cast_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto expr = db.names.back().move_full(); db.names.pop_back(); db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; @@ -639,6 +660,8 @@ parse_dynamic_cast_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto expr = db.names.back().move_full(); db.names.pop_back(); db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; @@ -663,6 +686,8 @@ parse_reinterpret_cast_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto expr = db.names.back().move_full(); db.names.pop_back(); db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")"; @@ -687,6 +712,8 @@ parse_static_cast_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto expr = db.names.back().move_full(); db.names.pop_back(); db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; @@ -723,6 +750,8 @@ parse_sizeof_type_expr(const char* first, const char* last, C& db) const char* t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; first = t; } @@ -741,6 +770,8 @@ parse_sizeof_expr_expr(const char* first, const char* last, C& db) const char* t = parse_expression(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; first = t; } @@ -832,6 +863,8 @@ parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db const char* t = parse_function_param(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; first = t; } @@ -855,6 +888,8 @@ parse_typeid_expr(const char* first, const char* last, C& db) t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back() = "typeid(" + db.names.back().move_full() + ")"; first = t; } @@ -873,6 +908,8 @@ parse_throw_expr(const char* first, const char* last, C& db) const char* t = parse_expression(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back() = "throw " + db.names.back().move_full(); first = t; } @@ -894,6 +931,8 @@ parse_dot_star_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto expr = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += ".*" + expr; @@ -918,6 +957,8 @@ parse_simple_id(const char* first, const char* last, C& db) const char* t1 = parse_template_args(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += std::move(args); @@ -964,6 +1005,8 @@ parse_unresolved_type(const char* first, const char* last, C& db) t = parse_decltype(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; } @@ -979,6 +1022,8 @@ parse_unresolved_type(const char* first, const char* last, C& db) t = parse_unqualified_name(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "std::"); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; @@ -1005,6 +1050,8 @@ parse_destructor_name(const char* first, const char* last, C& db) t = parse_simple_id(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "~"); first = t; } @@ -1036,6 +1083,8 @@ parse_base_unresolved_name(const char* first, const char* last, C& db) first = parse_template_args(t, last, db); if (first != t) { + if (db.names.size() < 2) + return first; auto args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += std::move(args); @@ -1060,6 +1109,8 @@ parse_base_unresolved_name(const char* first, const char* last, C& db) first = parse_template_args(t, last, db); if (first != t) { + if (db.names.size() < 2) + return first; auto args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += std::move(args); @@ -1109,7 +1160,11 @@ parse_unresolved_name(const char* first, const char* last, C& db) if (t2 != t) { if (global) + { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "::"); + } first = t2; } else if (last - t > 2 && t[0] == 's' && t[1] == 'r') @@ -1124,6 +1179,8 @@ parse_unresolved_name(const char* first, const char* last, C& db) t1 = parse_template_args(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += std::move(args); @@ -1137,7 +1194,7 @@ parse_unresolved_name(const char* first, const char* last, C& db) while (*t != 'E') { t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last) + if (t1 == t || t1 == last || db.names.size() < 2) return first; auto s = db.names.back().move_full(); db.names.pop_back(); @@ -1148,9 +1205,12 @@ parse_unresolved_name(const char* first, const char* last, C& db) t1 = parse_base_unresolved_name(t, last, db); if (t1 == t) { - db.names.pop_back(); + if (!db.names.empty()) + db.names.pop_back(); return first; } + if (db.names.size() < 2) + return first; auto s = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += "::" + std::move(s); @@ -1166,6 +1226,8 @@ parse_unresolved_name(const char* first, const char* last, C& db) t1 = parse_template_args(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += std::move(args); @@ -1174,9 +1236,12 @@ parse_unresolved_name(const char* first, const char* last, C& db) t1 = parse_base_unresolved_name(t, last, db); if (t1 == t) { - db.names.pop_back(); + if (!db.names.empty()) + db.names.pop_back(); return first; } + if (db.names.size() < 2) + return first; auto s = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += "::" + std::move(s); @@ -1189,11 +1254,15 @@ parse_unresolved_name(const char* first, const char* last, C& db) return first; t = t1; if (global) + { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "::"); + } while (*t != 'E') { t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last) + if (t1 == t || t1 == last || db.names.size() < 2) return first; auto s = db.names.back().move_full(); db.names.pop_back(); @@ -1204,9 +1273,12 @@ parse_unresolved_name(const char* first, const char* last, C& db) t1 = parse_base_unresolved_name(t, last, db); if (t1 == t) { - db.names.pop_back(); + if (!db.names.empty()) + db.names.pop_back(); return first; } + if (db.names.size() < 2) + return first; auto s = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += "::" + std::move(s); @@ -1232,6 +1304,8 @@ parse_dot_expr(const char* first, const char* last, C& db) const char* t1 = parse_unresolved_name(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto name = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += "." + name; @@ -1255,6 +1329,8 @@ parse_call_expr(const char* first, const char* last, C& db) { if (t == last) return first; + if (db.names.empty()) + return first; db.names.back().first += db.names.back().second; db.names.back().second = typename C::String(); db.names.back().first.append("("); @@ -1264,10 +1340,14 @@ parse_call_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 == t || t1 == last) return first; + if (db.names.empty()) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); if (!tmp.empty()) { + if (db.names.empty()) + return first; if (!first_expr) { db.names.back().first.append(", "); @@ -1278,6 +1358,8 @@ parse_call_expr(const char* first, const char* last, C& db) t = t1; } ++t; + if (db.names.empty()) + return first; db.names.back().first.append(")"); first = t; } @@ -1320,10 +1402,14 @@ parse_new_expr(const char* first, const char* last, C& db) has_expr_list = true; if (!first_expr) { + if (db.names.empty()) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); if (!tmp.empty()) { + if (db.names.empty()) + return first; db.names.back().first.append(", "); db.names.back().first.append(tmp); first_expr = false; @@ -1349,10 +1435,14 @@ parse_new_expr(const char* first, const char* last, C& db) return first; if (!first_expr) { + if (db.names.empty()) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); if (!tmp.empty()) { + if (db.names.empty()) + return first; db.names.back().first.append(", "); db.names.back().first.append(tmp); first_expr = false; @@ -1366,14 +1456,20 @@ parse_new_expr(const char* first, const char* last, C& db) typename C::String init_list; if (has_init) { + if (db.names.empty()) + return first; init_list = db.names.back().move_full(); db.names.pop_back(); } + if (db.names.empty()) + return first; auto type = db.names.back().move_full(); db.names.pop_back(); typename C::String expr_list; if (has_expr_list) { + if (db.names.empty()) + return first; expr_list = db.names.back().move_full(); db.names.pop_back(); } @@ -1435,10 +1531,14 @@ parse_conversion_expr(const char* first, const char* last, C& db) return first; if (!first_expr) { + if (db.names.empty()) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); if (!tmp.empty()) { + if (db.names.empty()) + return first; db.names.back().first.append(", "); db.names.back().first.append(tmp); first_expr = false; @@ -1449,6 +1549,8 @@ parse_conversion_expr(const char* first, const char* last, C& db) } ++t; } + if (db.names.size() < 2) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; @@ -1472,6 +1574,8 @@ parse_arrow_expr(const char* first, const char* last, C& db) const char* t1 = parse_expression(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += "->"; @@ -1564,6 +1668,8 @@ parse_function_type(const char* first, const char* last, C& db) sig += " &&"; break; } + if (db.names.empty()) + return first; db.names.back().first += " "; db.names.back().second.insert(0, sig); first = t; @@ -1587,6 +1693,8 @@ parse_pointer_to_member_type(const char* first, const char* last, C& db) const char* t2 = parse_type(t, last, db); if (t2 != t) { + if (db.names.size() < 2) + return first; auto func = std::move(db.names.back()); db.names.pop_back(); auto class_type = std::move(db.names.back()); @@ -1621,6 +1729,8 @@ parse_array_type(const char* first, const char* last, C& db) const char* t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; if (db.names.back().second.substr(0, 2) == " [") db.names.back().second.erase(0, 1); db.names.back().second.insert(0, " []"); @@ -1635,6 +1745,8 @@ parse_array_type(const char* first, const char* last, C& db) const char* t2 = parse_type(t+1, last, db); if (t2 != t+1) { + if (db.names.empty()) + return first; if (db.names.back().second.substr(0, 2) == " [") db.names.back().second.erase(0, 1); db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]"); @@ -1650,6 +1762,8 @@ parse_array_type(const char* first, const char* last, C& db) const char* t2 = parse_type(++t, last, db); if (t2 != t) { + if (db.names.size() < 2) + return first; auto type = std::move(db.names.back()); db.names.pop_back(); auto expr = std::move(db.names.back()); @@ -1682,6 +1796,8 @@ parse_decltype(const char* first, const char* last, C& db) const char* t = parse_expression(first+2, last, db); if (t != first+2 && t != last && *t == 'E') { + if (db.names.empty()) + return first; db.names.back() = "decltype(" + db.names.back().move_full() + ")"; first = t+1; } @@ -1719,6 +1835,8 @@ parse_vector_type(const char* first, const char* last, C& db) const char* t1 = parse_type(t, last, db); if (t1 != t) { + if (db.names.empty()) + return first; db.names.back().first += " vector[" + typename C::String(num, sz) + "]"; first = t1; } @@ -1740,6 +1858,8 @@ parse_vector_type(const char* first, const char* last, C& db) const char* t = parse_expression(t1, last, db); if (t != t1) { + if (db.names.empty()) + return first; num = db.names.back().move_full(); db.names.pop_back(); t1 = t; @@ -1750,6 +1870,8 @@ parse_vector_type(const char* first, const char* last, C& db) const char* t = parse_type(t1, last, db); if (t != t1) { + if (db.names.empty()) + return first; db.names.back().first += " vector[" + num + "]"; first = t; } @@ -1860,6 +1982,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_array_type(first, last, db); if (t != first) { + if (db.names.empty()) + return first; first = t; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); } @@ -1868,6 +1992,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_type(first+1, last, db); if (t != first+1) { + if (db.names.empty()) + return first; db.names.back().first.append(" complex"); first = t; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); @@ -1877,6 +2003,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_function_type(first, last, db); if (t != first) { + if (db.names.empty()) + return first; first = t; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); } @@ -1885,6 +2013,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_type(first+1, last, db); if (t != first+1) { + if (db.names.empty()) + return first; db.names.back().first.append(" imaginary"); first = t; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); @@ -1894,6 +2024,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_pointer_to_member_type(first, last, db); if (t != first) { + if (db.names.empty()) + return first; first = t; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); } @@ -2021,6 +2153,8 @@ parse_type(const char* first, const char* last, C& db) const char* t2 = parse_type(t, last, db); if (t2 != t) { + if (db.names.size() < 2) + return first; auto type = db.names.back().move_full(); db.names.pop_back(); if (db.names.back().first.substr(0, 9) != "objcproto") @@ -2053,6 +2187,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_name(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; } @@ -2068,6 +2204,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_template_args(first, last, db); if (t != first) { + if (db.names.size() < 2) + return first; auto template_args = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += template_args; @@ -2103,6 +2241,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_decltype(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; return first; @@ -2112,6 +2252,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_vector_type(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; return first; @@ -2133,6 +2275,8 @@ parse_type(const char* first, const char* last, C& db) t = parse_name(first, last, db); if (t != first) { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); first = t; } @@ -2169,6 +2313,7 @@ parse_type(const char* first, const char* last, C& db) // ::= gt # > // ::= ix # [] // ::= le # <= +// ::= li <source-name> # operator "" // ::= ls # << // ::= lS # <<= // ::= lt # < @@ -2251,6 +2396,8 @@ parse_operator_name(const char* first, const char* last, C& db) db.try_to_parse_template_args = try_to_parse_template_args; if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "operator "); db.parsed_ctor_dtor_cv = true; first = t; @@ -2328,6 +2475,18 @@ parse_operator_name(const char* first, const char* last, C& db) db.names.push_back("operator<="); first += 2; break; + case 'i': + { + const char* t = parse_source_name(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator\"\" "); + first = t; + } + } + break; case 's': db.names.push_back("operator<<"); first += 2; @@ -2472,6 +2631,8 @@ parse_operator_name(const char* first, const char* last, C& db) const char* t = parse_source_name(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "operator "); first = t; } @@ -2681,6 +2842,8 @@ parse_expr_primary(const char* first, const char* last, C& db) ; if (n != t && n != last && *n == 'E') { + if (db.names.empty()) + return first; db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n); first = n+1; break; @@ -2781,6 +2944,8 @@ parse_ctor_dtor_name(const char* first, const char* last, C& db) case '2': case '3': case '5': + if (db.names.empty()) + return first; db.names.push_back(base_name(db.names.back().first)); first += 2; db.parsed_ctor_dtor_cv = true; @@ -2794,6 +2959,8 @@ parse_ctor_dtor_name(const char* first, const char* last, C& db) case '1': case '2': case '5': + if (db.names.empty()) + return first; db.names.push_back("~" + base_name(db.names.back().first)); first += 2; db.parsed_ctor_dtor_cv = true; @@ -2864,6 +3031,8 @@ parse_unnamed_type_name(const char* first, const char* last, C& db) db.names.pop_back(); return first; } + if (db.names.size() < 2) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); db.names.back().first.append(tmp); @@ -2873,6 +3042,8 @@ parse_unnamed_type_name(const char* first, const char* last, C& db) t1 = parse_type(t0, last, db); if (t1 == t0) break; + if (db.names.size() < 2) + return first; tmp = db.names.back().move_full(); db.names.pop_back(); if (!tmp.empty()) @@ -2987,7 +3158,11 @@ parse_unscoped_name(const char* first, const char* last, C& db) if (t1 != t0) { if (St) + { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "std::"); + } first = t1; } } @@ -3005,6 +3180,8 @@ parse_alignof_type(const char* first, const char* last, C& db) const char* t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; first = t; } @@ -3023,6 +3200,8 @@ parse_alignof_expr(const char* first, const char* last, C& db) const char* t = parse_expression(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; first = t; } @@ -3037,6 +3216,8 @@ parse_noexcept_expression(const char* first, const char* last, C& db) const char* t1 = parse_expression(first, last, db); if (t1 != first) { + if (db.names.empty()) + return first; db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; first = t1; } @@ -3050,6 +3231,8 @@ parse_prefix_expression(const char* first, const char* last, const typename C::S const char* t1 = parse_expression(first, last, db); if (t1 != first) { + if (db.names.empty()) + return first; db.names.back().first = op + "(" + db.names.back().move_full() + ")"; first = t1; } @@ -3066,6 +3249,8 @@ parse_binary_expression(const char* first, const char* last, const typename C::S const char* t2 = parse_expression(t1, last, db); if (t2 != t1) { + if (db.names.size() < 2) + return first; auto op2 = db.names.back().move_full(); db.names.pop_back(); auto op1 = db.names.back().move_full(); @@ -3216,6 +3401,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t1 = parse_expression(t+2, last, db); if (t1 != t+2) { + if (db.names.empty()) + return first; db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + "delete[] " + db.names.back().move_full(); first = t1; @@ -3235,6 +3422,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t1 = parse_expression(t+2, last, db); if (t1 != t+2) { + if (db.names.empty()) + return first; db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + "delete " + db.names.back().move_full(); first = t1; @@ -3305,6 +3494,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t2 = parse_expression(t1, last, db); if (t2 != t1) { + if (db.names.size() < 2) + return first; auto op2 = db.names.back().move_full(); db.names.pop_back(); auto op1 = db.names.back().move_full(); @@ -3376,6 +3567,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t1 = parse_expression(first+2, last, db); if (t1 != first+2) { + if (db.names.empty()) + return first; db.names.back() = "(" + db.names.back().move_full() + ")--"; first = t1; } @@ -3464,6 +3657,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t1 = parse_expression(first+2, last, db); if (t1 != first+2) { + if (db.names.empty()) + return first; db.names.back() = "(" + db.names.back().move_full() + ")++"; first = t1; } @@ -3491,6 +3686,8 @@ parse_expression(const char* first, const char* last, C& db) const char* t3 = parse_expression(t2, last, db); if (t3 != t2) { + if (db.names.size() < 3) + return first; auto op3 = db.names.back().move_full(); db.names.pop_back(); auto op2 = db.names.back().move_full(); @@ -3918,6 +4115,8 @@ parse_local_name(const char* first, const char* last, C& db) { case 's': first = parse_discriminator(t+1, last); + if (db.names.empty()) + return first; db.names.back().first.append("::string literal"); break; case 'd': @@ -3930,6 +4129,8 @@ parse_local_name(const char* first, const char* last, C& db) t1 = parse_name(t, last, db); if (t1 != t) { + if (db.names.size() < 2) + return first; auto name = db.names.back().move_full(); db.names.pop_back(); db.names.back().first.append("::"); @@ -3948,6 +4149,8 @@ parse_local_name(const char* first, const char* last, C& db) { // parse but ignore discriminator first = parse_discriminator(t1, last); + if (db.names.size() < 2) + return first; auto name = db.names.back().move_full(); db.names.pop_back(); db.names.back().first.append("::"); @@ -4004,11 +4207,15 @@ parse_name(const char* first, const char* last, C& db) { if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args> { + if (db.names.empty()) + return first; db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); t0 = t1; t1 = parse_template_args(t0, last, db); if (t1 != t0) { + if (db.names.size() < 2) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += tmp; @@ -4027,6 +4234,8 @@ parse_name(const char* first, const char* last, C& db) t1 = parse_template_args(t0, last, db); if (t1 != t0) { + if (db.names.size() < 2) + return first; auto tmp = db.names.back().move_full(); db.names.pop_back(); db.names.back().first += tmp; @@ -4112,6 +4321,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "vtable for "); first = t; } @@ -4121,6 +4332,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "VTT for "); first = t; } @@ -4130,6 +4343,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "typeinfo for "); first = t; } @@ -4139,6 +4354,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_type(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "typeinfo name for "); first = t; } @@ -4155,6 +4372,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_encoding(t1, last, db); if (t != t1) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "covariant return thunk to "); first = t; } @@ -4171,6 +4390,8 @@ parse_special_name(const char* first, const char* last, C& db) const char* t1 = parse_type(++t0, last, db); if (t1 != t0) { + if (db.names.size() < 2) + return first; auto left = db.names.back().move_full(); db.names.pop_back(); db.names.back().first = "construction vtable for " + @@ -4190,6 +4411,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_encoding(t0, last, db); if (t != t0) { + if (db.names.empty()) + return first; if (first[2] == 'v') { db.names.back().first.insert(0, "virtual thunk to "); @@ -4213,6 +4436,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_name(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "guard variable for "); first = t; } @@ -4222,6 +4447,8 @@ parse_special_name(const char* first, const char* last, C& db) t = parse_name(first+2, last, db); if (t != first+2) { + if (db.names.empty()) + return first; db.names.back().first.insert(0, "reference temporary for "); first = t; } @@ -4233,6 +4460,26 @@ parse_special_name(const char* first, const char* last, C& db) return first; } +template <class T> +class save_value +{ + T& restore_; + T original_value_; +public: + save_value(T& restore) + : restore_(restore), + original_value_(restore) + {} + + ~save_value() + { + restore_ = std::move(original_value_); + } + + save_value(const save_value&) = delete; + save_value& operator=(const save_value&) = delete; +}; + // <encoding> ::= <function name> <bare-function-type> // ::= <data name> // ::= <special-name> @@ -4243,6 +4490,11 @@ parse_encoding(const char* first, const char* last, C& db) { if (first != last) { + save_value<decltype(db.encoding_depth)> su(db.encoding_depth); + ++db.encoding_depth; + save_value<decltype(db.tag_templates)> sb(db.tag_templates); + if (db.encoding_depth > 1) + db.tag_templates = true; switch (*first) { case 'G': @@ -4258,17 +4510,23 @@ parse_encoding(const char* first, const char* last, C& db) { if (t != last && *t != 'E' && *t != '.') { - bool tag_templates = db.tag_templates; + save_value<bool> sb2(db.tag_templates); db.tag_templates = false; const char* t2; typename C::String ret2; + if (db.names.empty()) + return first; const typename C::String& nm = db.names.back().first; + if (nm.empty()) + return first; if (!db.parsed_ctor_dtor_cv && nm.back() == '>' && nm[nm.size()-2] != '-' && nm[nm.size()-2] != '>') { t2 = parse_type(t, last, db); if (t2 == t) return first; + if (db.names.size() < 2) + return first; auto ret1 = std::move(db.names.back().first); ret2 = std::move(db.names.back().second); if (ret2.empty()) @@ -4305,6 +4563,8 @@ parse_encoding(const char* first, const char* last, C& db) db.names.pop_back(); if (!tmp.empty()) { + if (db.names.empty()) + return first; if (!first_arg) db.names.back().first += ", "; else @@ -4315,6 +4575,8 @@ parse_encoding(const char* first, const char* last, C& db) t = t2; } } + if (db.names.empty()) + return first; db.names.back().first += ')'; if (cv & 1) db.names.back().first.append(" const"); @@ -4328,7 +4590,6 @@ parse_encoding(const char* first, const char* last, C& db) db.names.back().first.append(" &&"); db.names.back().first += ret2; first = t; - db.tag_templates = tag_templates; } else first = t; @@ -4370,6 +4631,8 @@ parse_block_invoke(const char* first, const char* last, C& db) while (t != last && isdigit(*t)) ++t; } + if (db.names.empty()) + return first; db.names.back().first.insert(0, "invocation function for block in "); first = t; } @@ -4385,6 +4648,8 @@ parse_dot_suffix(const char* first, const char* last, C& db) { if (first != last && *first == '.') { + if (db.names.empty()) + return first; db.names.back().first += " (" + typename C::String(first, last) + ")"; first = last; } @@ -4620,6 +4885,7 @@ struct Db Vector<template_param_type> template_param; unsigned cv; unsigned ref; + unsigned encoding_depth; bool parsed_ctor_dtor_cv; bool tag_templates; bool fix_forward_references; @@ -4647,6 +4913,7 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) Db db(a); db.cv = 0; db.ref = 0; + db.encoding_depth = 0; db.parsed_ctor_dtor_cv = false; db.tag_templates = true; db.template_param.emplace_back(a); @@ -4699,8 +4966,7 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) return buf; } -} // unnamed namespace - +} #endif |