aboutsummaryrefslogtreecommitdiff
path: root/source/Core/Mangled.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Mangled.cpp')
-rw-r--r--source/Core/Mangled.cpp302
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