Pickup fixes for demangling crashers.

<rdar://problem/15600471>

llvm-svn: 197171
This commit is contained in:
Greg Clayton 2013-12-12 17:39:39 +00:00
parent 3db958387f
commit b73a31efe6
1 changed files with 271 additions and 18 deletions

View File

@ -20,17 +20,10 @@
#ifdef LLDB_USE_BUILTIN_DEMANGLER #ifdef LLDB_USE_BUILTIN_DEMANGLER
#include <vector>
#include <algorithm>
#include <string>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <cctype>
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Inlined copy of: // Inlined copy of:
// http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp // http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp
// revision 193704. // revision 197169.
// //
// Changes include: // Changes include:
// - remove the "__cxxabiv1" namespace // - remove the "__cxxabiv1" namespace
@ -38,8 +31,32 @@
// - removed extern "C" from the cxa_demangle function // - removed extern "C" from the cxa_demangle function
// - Changed the scope of the unnamed namespace to include cxa_demangle // - Changed the scope of the unnamed namespace to include cxa_demangle
// function. // 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 namespace
{ {
@ -558,6 +575,8 @@ parse_template_param(const char* first, const char* last, C& db)
{ {
if (first[1] == '_') if (first[1] == '_')
{ {
if (db.template_param.empty())
return first;
if (!db.template_param.back().empty()) if (!db.template_param.back().empty())
{ {
for (auto& t : db.template_param.back().front()) 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 *= 10;
sub += static_cast<size_t>(*t - '0'); sub += static_cast<size_t>(*t - '0');
} }
if (t == last || *t != '_') if (t == last || *t != '_' || db.template_param.empty())
return first; return first;
++sub; ++sub;
if (sub < db.template_param.back().size()) 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto expr = db.names.back().move_full(); auto expr = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto expr = db.names.back().move_full(); auto expr = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto expr = db.names.back().move_full(); auto expr = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")"; 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto expr = db.names.back().move_full(); auto expr = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; 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); const char* t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
first = t; 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); const char* t = parse_expression(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
first = t; 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); const char* t = parse_function_param(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; db.names.back() = "sizeof...(" + db.names.back().move_full() + ")";
first = t; first = t;
} }
@ -855,6 +888,8 @@ parse_typeid_expr(const char* first, const char* last, C& db)
t = parse_type(first+2, last, db); t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "typeid(" + db.names.back().move_full() + ")"; db.names.back() = "typeid(" + db.names.back().move_full() + ")";
first = t; 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); const char* t = parse_expression(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "throw " + db.names.back().move_full(); db.names.back() = "throw " + db.names.back().move_full();
first = t; 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto expr = db.names.back().move_full(); auto expr = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += ".*" + expr; 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); const char* t1 = parse_template_args(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto args = db.names.back().move_full(); auto args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += std::move(args); 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); t = parse_decltype(first, last, db);
if (t != first) 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; 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); t = parse_unqualified_name(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "std::"); db.names.back().first.insert(0, "std::");
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; first = t;
@ -1005,6 +1050,8 @@ parse_destructor_name(const char* first, const char* last, C& db)
t = parse_simple_id(first, last, db); t = parse_simple_id(first, last, db);
if (t != first) if (t != first)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "~"); db.names.back().first.insert(0, "~");
first = t; 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); first = parse_template_args(t, last, db);
if (first != t) if (first != t)
{ {
if (db.names.size() < 2)
return first;
auto args = db.names.back().move_full(); auto args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += std::move(args); 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); first = parse_template_args(t, last, db);
if (first != t) if (first != t)
{ {
if (db.names.size() < 2)
return first;
auto args = db.names.back().move_full(); auto args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += std::move(args); 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 (t2 != t)
{ {
if (global) if (global)
{
if (db.names.empty())
return first;
db.names.back().first.insert(0, "::"); db.names.back().first.insert(0, "::");
}
first = t2; first = t2;
} }
else if (last - t > 2 && t[0] == 's' && t[1] == 'r') 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); t1 = parse_template_args(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto args = db.names.back().move_full(); auto args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += std::move(args); 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') while (*t != 'E')
{ {
t1 = parse_unresolved_qualifier_level(t, last, db); t1 = parse_unresolved_qualifier_level(t, last, db);
if (t1 == t || t1 == last) if (t1 == t || t1 == last || db.names.size() < 2)
return first; return first;
auto s = db.names.back().move_full(); auto s = db.names.back().move_full();
db.names.pop_back(); 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); t1 = parse_base_unresolved_name(t, last, db);
if (t1 == t) if (t1 == t)
{ {
if (!db.names.empty())
db.names.pop_back(); db.names.pop_back();
return first; return first;
} }
if (db.names.size() < 2)
return first;
auto s = db.names.back().move_full(); auto s = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += "::" + std::move(s); 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); t1 = parse_template_args(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto args = db.names.back().move_full(); auto args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += std::move(args); 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); t1 = parse_base_unresolved_name(t, last, db);
if (t1 == t) if (t1 == t)
{ {
if (!db.names.empty())
db.names.pop_back(); db.names.pop_back();
return first; return first;
} }
if (db.names.size() < 2)
return first;
auto s = db.names.back().move_full(); auto s = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += "::" + std::move(s); db.names.back().first += "::" + std::move(s);
@ -1189,11 +1254,15 @@ parse_unresolved_name(const char* first, const char* last, C& db)
return first; return first;
t = t1; t = t1;
if (global) if (global)
{
if (db.names.empty())
return first;
db.names.back().first.insert(0, "::"); db.names.back().first.insert(0, "::");
}
while (*t != 'E') while (*t != 'E')
{ {
t1 = parse_unresolved_qualifier_level(t, last, db); t1 = parse_unresolved_qualifier_level(t, last, db);
if (t1 == t || t1 == last) if (t1 == t || t1 == last || db.names.size() < 2)
return first; return first;
auto s = db.names.back().move_full(); auto s = db.names.back().move_full();
db.names.pop_back(); 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); t1 = parse_base_unresolved_name(t, last, db);
if (t1 == t) if (t1 == t)
{ {
if (!db.names.empty())
db.names.pop_back(); db.names.pop_back();
return first; return first;
} }
if (db.names.size() < 2)
return first;
auto s = db.names.back().move_full(); auto s = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += "::" + std::move(s); 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); const char* t1 = parse_unresolved_name(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto name = db.names.back().move_full(); auto name = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += "." + name; db.names.back().first += "." + name;
@ -1255,6 +1329,8 @@ parse_call_expr(const char* first, const char* last, C& db)
{ {
if (t == last) if (t == last)
return first; return first;
if (db.names.empty())
return first;
db.names.back().first += db.names.back().second; db.names.back().first += db.names.back().second;
db.names.back().second = typename C::String(); db.names.back().second = typename C::String();
db.names.back().first.append("("); 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); const char* t1 = parse_expression(t, last, db);
if (t1 == t || t1 == last) if (t1 == t || t1 == last)
return first; return first;
if (db.names.empty())
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
{ {
if (db.names.empty())
return first;
if (!first_expr) if (!first_expr)
{ {
db.names.back().first.append(", "); db.names.back().first.append(", ");
@ -1278,6 +1358,8 @@ parse_call_expr(const char* first, const char* last, C& db)
t = t1; t = t1;
} }
++t; ++t;
if (db.names.empty())
return first;
db.names.back().first.append(")"); db.names.back().first.append(")");
first = t; first = t;
} }
@ -1320,10 +1402,14 @@ parse_new_expr(const char* first, const char* last, C& db)
has_expr_list = true; has_expr_list = true;
if (!first_expr) if (!first_expr)
{ {
if (db.names.empty())
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
{ {
if (db.names.empty())
return first;
db.names.back().first.append(", "); db.names.back().first.append(", ");
db.names.back().first.append(tmp); db.names.back().first.append(tmp);
first_expr = false; first_expr = false;
@ -1349,10 +1435,14 @@ parse_new_expr(const char* first, const char* last, C& db)
return first; return first;
if (!first_expr) if (!first_expr)
{ {
if (db.names.empty())
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
{ {
if (db.names.empty())
return first;
db.names.back().first.append(", "); db.names.back().first.append(", ");
db.names.back().first.append(tmp); db.names.back().first.append(tmp);
first_expr = false; first_expr = false;
@ -1366,14 +1456,20 @@ parse_new_expr(const char* first, const char* last, C& db)
typename C::String init_list; typename C::String init_list;
if (has_init) if (has_init)
{ {
if (db.names.empty())
return first;
init_list = db.names.back().move_full(); init_list = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
} }
if (db.names.empty())
return first;
auto type = db.names.back().move_full(); auto type = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
typename C::String expr_list; typename C::String expr_list;
if (has_expr_list) if (has_expr_list)
{ {
if (db.names.empty())
return first;
expr_list = db.names.back().move_full(); expr_list = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
} }
@ -1435,10 +1531,14 @@ parse_conversion_expr(const char* first, const char* last, C& db)
return first; return first;
if (!first_expr) if (!first_expr)
{ {
if (db.names.empty())
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
{ {
if (db.names.empty())
return first;
db.names.back().first.append(", "); db.names.back().first.append(", ");
db.names.back().first.append(tmp); db.names.back().first.append(tmp);
first_expr = false; first_expr = false;
@ -1449,6 +1549,8 @@ parse_conversion_expr(const char* first, const char* last, C& db)
} }
++t; ++t;
} }
if (db.names.size() < 2)
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; 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); const char* t1 = parse_expression(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += "->"; db.names.back().first += "->";
@ -1564,6 +1668,8 @@ parse_function_type(const char* first, const char* last, C& db)
sig += " &&"; sig += " &&";
break; break;
} }
if (db.names.empty())
return first;
db.names.back().first += " "; db.names.back().first += " ";
db.names.back().second.insert(0, sig); db.names.back().second.insert(0, sig);
first = t; 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); const char* t2 = parse_type(t, last, db);
if (t2 != t) if (t2 != t)
{ {
if (db.names.size() < 2)
return first;
auto func = std::move(db.names.back()); auto func = std::move(db.names.back());
db.names.pop_back(); db.names.pop_back();
auto class_type = std::move(db.names.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); const char* t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
if (db.names.back().second.substr(0, 2) == " [") if (db.names.back().second.substr(0, 2) == " [")
db.names.back().second.erase(0, 1); db.names.back().second.erase(0, 1);
db.names.back().second.insert(0, " []"); 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); const char* t2 = parse_type(t+1, last, db);
if (t2 != t+1) if (t2 != t+1)
{ {
if (db.names.empty())
return first;
if (db.names.back().second.substr(0, 2) == " [") if (db.names.back().second.substr(0, 2) == " [")
db.names.back().second.erase(0, 1); db.names.back().second.erase(0, 1);
db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]"); 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); const char* t2 = parse_type(++t, last, db);
if (t2 != t) if (t2 != t)
{ {
if (db.names.size() < 2)
return first;
auto type = std::move(db.names.back()); auto type = std::move(db.names.back());
db.names.pop_back(); db.names.pop_back();
auto expr = std::move(db.names.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); const char* t = parse_expression(first+2, last, db);
if (t != first+2 && t != last && *t == 'E') if (t != first+2 && t != last && *t == 'E')
{ {
if (db.names.empty())
return first;
db.names.back() = "decltype(" + db.names.back().move_full() + ")"; db.names.back() = "decltype(" + db.names.back().move_full() + ")";
first = t+1; 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); const char* t1 = parse_type(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.empty())
return first;
db.names.back().first += " vector[" + typename C::String(num, sz) + "]"; db.names.back().first += " vector[" + typename C::String(num, sz) + "]";
first = t1; 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); const char* t = parse_expression(t1, last, db);
if (t != t1) if (t != t1)
{ {
if (db.names.empty())
return first;
num = db.names.back().move_full(); num = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
t1 = t; 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); const char* t = parse_type(t1, last, db);
if (t != t1) if (t != t1)
{ {
if (db.names.empty())
return first;
db.names.back().first += " vector[" + num + "]"; db.names.back().first += " vector[" + num + "]";
first = t; first = t;
} }
@ -1860,6 +1982,8 @@ parse_type(const char* first, const char* last, C& db)
t = parse_array_type(first, last, db); t = parse_array_type(first, last, db);
if (t != first) if (t != first)
{ {
if (db.names.empty())
return first;
first = t; first = t;
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); 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); t = parse_type(first+1, last, db);
if (t != first+1) if (t != first+1)
{ {
if (db.names.empty())
return first;
db.names.back().first.append(" complex"); db.names.back().first.append(" complex");
first = t; first = t;
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); 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); t = parse_function_type(first, last, db);
if (t != first) if (t != first)
{ {
if (db.names.empty())
return first;
first = t; first = t;
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); 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); t = parse_type(first+1, last, db);
if (t != first+1) if (t != first+1)
{ {
if (db.names.empty())
return first;
db.names.back().first.append(" imaginary"); db.names.back().first.append(" imaginary");
first = t; first = t;
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); 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); t = parse_pointer_to_member_type(first, last, db);
if (t != first) if (t != first)
{ {
if (db.names.empty())
return first;
first = t; first = t;
db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); 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); const char* t2 = parse_type(t, last, db);
if (t2 != t) if (t2 != t)
{ {
if (db.names.size() < 2)
return first;
auto type = db.names.back().move_full(); auto type = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (db.names.back().first.substr(0, 9) != "objcproto") 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); t = parse_name(first, last, db);
if (t != first) 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; first = t;
} }
@ -2068,6 +2204,8 @@ parse_type(const char* first, const char* last, C& db)
t = parse_template_args(first, last, db); t = parse_template_args(first, last, db);
if (t != first) if (t != first)
{ {
if (db.names.size() < 2)
return first;
auto template_args = db.names.back().move_full(); auto template_args = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += template_args; 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); t = parse_decltype(first, last, db);
if (t != first) 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; first = t;
return first; return first;
@ -2112,6 +2252,8 @@ parse_type(const char* first, const char* last, C& db)
t = parse_vector_type(first, last, db); t = parse_vector_type(first, last, db);
if (t != first) 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; first = t;
return first; return first;
@ -2133,6 +2275,8 @@ parse_type(const char* first, const char* last, C& db)
t = parse_name(first, last, db); t = parse_name(first, last, db);
if (t != first) 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
first = t; first = t;
} }
@ -2251,6 +2395,8 @@ parse_operator_name(const char* first, const char* last, C& db)
db.try_to_parse_template_args = try_to_parse_template_args; db.try_to_parse_template_args = try_to_parse_template_args;
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "operator "); db.names.back().first.insert(0, "operator ");
db.parsed_ctor_dtor_cv = true; db.parsed_ctor_dtor_cv = true;
first = t; first = t;
@ -2472,6 +2618,8 @@ parse_operator_name(const char* first, const char* last, C& db)
const char* t = parse_source_name(first+2, last, db); const char* t = parse_source_name(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "operator "); db.names.back().first.insert(0, "operator ");
first = t; first = t;
} }
@ -2681,6 +2829,8 @@ parse_expr_primary(const char* first, const char* last, C& db)
; ;
if (n != t && n != last && *n == 'E') 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); db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n);
first = n+1; first = n+1;
break; break;
@ -2781,6 +2931,8 @@ parse_ctor_dtor_name(const char* first, const char* last, C& db)
case '2': case '2':
case '3': case '3':
case '5': case '5':
if (db.names.empty())
return first;
db.names.push_back(base_name(db.names.back().first)); db.names.push_back(base_name(db.names.back().first));
first += 2; first += 2;
db.parsed_ctor_dtor_cv = true; db.parsed_ctor_dtor_cv = true;
@ -2794,6 +2946,8 @@ parse_ctor_dtor_name(const char* first, const char* last, C& db)
case '1': case '1':
case '2': case '2':
case '5': case '5':
if (db.names.empty())
return first;
db.names.push_back("~" + base_name(db.names.back().first)); db.names.push_back("~" + base_name(db.names.back().first));
first += 2; first += 2;
db.parsed_ctor_dtor_cv = true; db.parsed_ctor_dtor_cv = true;
@ -2864,6 +3018,8 @@ parse_unnamed_type_name(const char* first, const char* last, C& db)
db.names.pop_back(); db.names.pop_back();
return first; return first;
} }
if (db.names.size() < 2)
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first.append(tmp); db.names.back().first.append(tmp);
@ -2873,6 +3029,8 @@ parse_unnamed_type_name(const char* first, const char* last, C& db)
t1 = parse_type(t0, last, db); t1 = parse_type(t0, last, db);
if (t1 == t0) if (t1 == t0)
break; break;
if (db.names.size() < 2)
return first;
tmp = db.names.back().move_full(); tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
@ -2987,7 +3145,11 @@ parse_unscoped_name(const char* first, const char* last, C& db)
if (t1 != t0) if (t1 != t0)
{ {
if (St) if (St)
{
if (db.names.empty())
return first;
db.names.back().first.insert(0, "std::"); db.names.back().first.insert(0, "std::");
}
first = t1; first = t1;
} }
} }
@ -3005,6 +3167,8 @@ parse_alignof_type(const char* first, const char* last, C& db)
const char* t = parse_type(first+2, last, db); const char* t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
first = t; first = t;
} }
@ -3023,6 +3187,8 @@ parse_alignof_expr(const char* first, const char* last, C& db)
const char* t = parse_expression(first+2, last, db); const char* t = parse_expression(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
first = t; first = t;
} }
@ -3037,6 +3203,8 @@ parse_noexcept_expression(const char* first, const char* last, C& db)
const char* t1 = parse_expression(first, last, db); const char* t1 = parse_expression(first, last, db);
if (t1 != first) if (t1 != first)
{ {
if (db.names.empty())
return first;
db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
first = t1; first = t1;
} }
@ -3050,6 +3218,8 @@ parse_prefix_expression(const char* first, const char* last, const typename C::S
const char* t1 = parse_expression(first, last, db); const char* t1 = parse_expression(first, last, db);
if (t1 != first) if (t1 != first)
{ {
if (db.names.empty())
return first;
db.names.back().first = op + "(" + db.names.back().move_full() + ")"; db.names.back().first = op + "(" + db.names.back().move_full() + ")";
first = t1; first = t1;
} }
@ -3066,6 +3236,8 @@ parse_binary_expression(const char* first, const char* last, const typename C::S
const char* t2 = parse_expression(t1, last, db); const char* t2 = parse_expression(t1, last, db);
if (t2 != t1) if (t2 != t1)
{ {
if (db.names.size() < 2)
return first;
auto op2 = db.names.back().move_full(); auto op2 = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
auto op1 = db.names.back().move_full(); auto op1 = db.names.back().move_full();
@ -3216,6 +3388,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t1 = parse_expression(t+2, last, db); const char* t1 = parse_expression(t+2, last, db);
if (t1 != t+2) if (t1 != t+2)
{ {
if (db.names.empty())
return first;
db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
"delete[] " + db.names.back().move_full(); "delete[] " + db.names.back().move_full();
first = t1; first = t1;
@ -3235,6 +3409,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t1 = parse_expression(t+2, last, db); const char* t1 = parse_expression(t+2, last, db);
if (t1 != t+2) if (t1 != t+2)
{ {
if (db.names.empty())
return first;
db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) +
"delete " + db.names.back().move_full(); "delete " + db.names.back().move_full();
first = t1; first = t1;
@ -3305,6 +3481,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t2 = parse_expression(t1, last, db); const char* t2 = parse_expression(t1, last, db);
if (t2 != t1) if (t2 != t1)
{ {
if (db.names.size() < 2)
return first;
auto op2 = db.names.back().move_full(); auto op2 = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
auto op1 = db.names.back().move_full(); auto op1 = db.names.back().move_full();
@ -3376,6 +3554,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t1 = parse_expression(first+2, last, db); const char* t1 = parse_expression(first+2, last, db);
if (t1 != first+2) if (t1 != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "(" + db.names.back().move_full() + ")--"; db.names.back() = "(" + db.names.back().move_full() + ")--";
first = t1; first = t1;
} }
@ -3464,6 +3644,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t1 = parse_expression(first+2, last, db); const char* t1 = parse_expression(first+2, last, db);
if (t1 != first+2) if (t1 != first+2)
{ {
if (db.names.empty())
return first;
db.names.back() = "(" + db.names.back().move_full() + ")++"; db.names.back() = "(" + db.names.back().move_full() + ")++";
first = t1; first = t1;
} }
@ -3491,6 +3673,8 @@ parse_expression(const char* first, const char* last, C& db)
const char* t3 = parse_expression(t2, last, db); const char* t3 = parse_expression(t2, last, db);
if (t3 != t2) if (t3 != t2)
{ {
if (db.names.size() < 3)
return first;
auto op3 = db.names.back().move_full(); auto op3 = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
auto op2 = db.names.back().move_full(); auto op2 = db.names.back().move_full();
@ -3918,6 +4102,8 @@ parse_local_name(const char* first, const char* last, C& db)
{ {
case 's': case 's':
first = parse_discriminator(t+1, last); first = parse_discriminator(t+1, last);
if (db.names.empty())
return first;
db.names.back().first.append("::string literal"); db.names.back().first.append("::string literal");
break; break;
case 'd': case 'd':
@ -3930,6 +4116,8 @@ parse_local_name(const char* first, const char* last, C& db)
t1 = parse_name(t, last, db); t1 = parse_name(t, last, db);
if (t1 != t) if (t1 != t)
{ {
if (db.names.size() < 2)
return first;
auto name = db.names.back().move_full(); auto name = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first.append("::"); db.names.back().first.append("::");
@ -3948,6 +4136,8 @@ parse_local_name(const char* first, const char* last, C& db)
{ {
// parse but ignore discriminator // parse but ignore discriminator
first = parse_discriminator(t1, last); first = parse_discriminator(t1, last);
if (db.names.size() < 2)
return first;
auto name = db.names.back().move_full(); auto name = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first.append("::"); db.names.back().first.append("::");
@ -4004,11 +4194,15 @@ parse_name(const char* first, const char* last, C& db)
{ {
if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args> 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())); db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));
t0 = t1; t0 = t1;
t1 = parse_template_args(t0, last, db); t1 = parse_template_args(t0, last, db);
if (t1 != t0) if (t1 != t0)
{ {
if (db.names.size() < 2)
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += tmp; db.names.back().first += tmp;
@ -4027,6 +4221,8 @@ parse_name(const char* first, const char* last, C& db)
t1 = parse_template_args(t0, last, db); t1 = parse_template_args(t0, last, db);
if (t1 != t0) if (t1 != t0)
{ {
if (db.names.size() < 2)
return first;
auto tmp = db.names.back().move_full(); auto tmp = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first += tmp; db.names.back().first += tmp;
@ -4112,6 +4308,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_type(first+2, last, db); t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "vtable for "); db.names.back().first.insert(0, "vtable for ");
first = t; first = t;
} }
@ -4121,6 +4319,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_type(first+2, last, db); t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "VTT for "); db.names.back().first.insert(0, "VTT for ");
first = t; first = t;
} }
@ -4130,6 +4330,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_type(first+2, last, db); t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "typeinfo for "); db.names.back().first.insert(0, "typeinfo for ");
first = t; first = t;
} }
@ -4139,6 +4341,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_type(first+2, last, db); t = parse_type(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "typeinfo name for "); db.names.back().first.insert(0, "typeinfo name for ");
first = t; first = t;
} }
@ -4155,6 +4359,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_encoding(t1, last, db); t = parse_encoding(t1, last, db);
if (t != t1) if (t != t1)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "covariant return thunk to "); db.names.back().first.insert(0, "covariant return thunk to ");
first = t; first = t;
} }
@ -4171,6 +4377,8 @@ parse_special_name(const char* first, const char* last, C& db)
const char* t1 = parse_type(++t0, last, db); const char* t1 = parse_type(++t0, last, db);
if (t1 != t0) if (t1 != t0)
{ {
if (db.names.size() < 2)
return first;
auto left = db.names.back().move_full(); auto left = db.names.back().move_full();
db.names.pop_back(); db.names.pop_back();
db.names.back().first = "construction vtable for " + db.names.back().first = "construction vtable for " +
@ -4190,6 +4398,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_encoding(t0, last, db); t = parse_encoding(t0, last, db);
if (t != t0) if (t != t0)
{ {
if (db.names.empty())
return first;
if (first[2] == 'v') if (first[2] == 'v')
{ {
db.names.back().first.insert(0, "virtual thunk to "); db.names.back().first.insert(0, "virtual thunk to ");
@ -4213,6 +4423,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_name(first+2, last, db); t = parse_name(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "guard variable for "); db.names.back().first.insert(0, "guard variable for ");
first = t; first = t;
} }
@ -4222,6 +4434,8 @@ parse_special_name(const char* first, const char* last, C& db)
t = parse_name(first+2, last, db); t = parse_name(first+2, last, db);
if (t != first+2) if (t != first+2)
{ {
if (db.names.empty())
return first;
db.names.back().first.insert(0, "reference temporary for "); db.names.back().first.insert(0, "reference temporary for ");
first = t; first = t;
} }
@ -4233,6 +4447,26 @@ parse_special_name(const char* first, const char* last, C& db)
return first; 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> // <encoding> ::= <function name> <bare-function-type>
// ::= <data name> // ::= <data name>
// ::= <special-name> // ::= <special-name>
@ -4243,6 +4477,11 @@ parse_encoding(const char* first, const char* last, C& db)
{ {
if (first != last) 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) switch (*first)
{ {
case 'G': case 'G':
@ -4258,17 +4497,23 @@ parse_encoding(const char* first, const char* last, C& db)
{ {
if (t != last && *t != 'E' && *t != '.') if (t != last && *t != 'E' && *t != '.')
{ {
bool tag_templates = db.tag_templates; save_value<bool> sb2(db.tag_templates);
db.tag_templates = false; db.tag_templates = false;
const char* t2; const char* t2;
typename C::String ret2; typename C::String ret2;
if (db.names.empty())
return first;
const typename C::String& nm = db.names.back().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] != '-' if (!db.parsed_ctor_dtor_cv && nm.back() == '>' && nm[nm.size()-2] != '-'
&& nm[nm.size()-2] != '>') && nm[nm.size()-2] != '>')
{ {
t2 = parse_type(t, last, db); t2 = parse_type(t, last, db);
if (t2 == t) if (t2 == t)
return first; return first;
if (db.names.size() < 2)
return first;
auto ret1 = std::move(db.names.back().first); auto ret1 = std::move(db.names.back().first);
ret2 = std::move(db.names.back().second); ret2 = std::move(db.names.back().second);
if (ret2.empty()) if (ret2.empty())
@ -4305,6 +4550,8 @@ parse_encoding(const char* first, const char* last, C& db)
db.names.pop_back(); db.names.pop_back();
if (!tmp.empty()) if (!tmp.empty())
{ {
if (db.names.empty())
return first;
if (!first_arg) if (!first_arg)
db.names.back().first += ", "; db.names.back().first += ", ";
else else
@ -4315,6 +4562,8 @@ parse_encoding(const char* first, const char* last, C& db)
t = t2; t = t2;
} }
} }
if (db.names.empty())
return first;
db.names.back().first += ')'; db.names.back().first += ')';
if (cv & 1) if (cv & 1)
db.names.back().first.append(" const"); db.names.back().first.append(" const");
@ -4328,7 +4577,6 @@ parse_encoding(const char* first, const char* last, C& db)
db.names.back().first.append(" &&"); db.names.back().first.append(" &&");
db.names.back().first += ret2; db.names.back().first += ret2;
first = t; first = t;
db.tag_templates = tag_templates;
} }
else else
first = t; first = t;
@ -4370,6 +4618,8 @@ parse_block_invoke(const char* first, const char* last, C& db)
while (t != last && isdigit(*t)) while (t != last && isdigit(*t))
++t; ++t;
} }
if (db.names.empty())
return first;
db.names.back().first.insert(0, "invocation function for block in "); db.names.back().first.insert(0, "invocation function for block in ");
first = t; first = t;
} }
@ -4385,6 +4635,8 @@ parse_dot_suffix(const char* first, const char* last, C& db)
{ {
if (first != last && *first == '.') if (first != last && *first == '.')
{ {
if (db.names.empty())
return first;
db.names.back().first += " (" + typename C::String(first, last) + ")"; db.names.back().first += " (" + typename C::String(first, last) + ")";
first = last; first = last;
} }
@ -4620,6 +4872,7 @@ struct Db
Vector<template_param_type> template_param; Vector<template_param_type> template_param;
unsigned cv; unsigned cv;
unsigned ref; unsigned ref;
unsigned encoding_depth;
bool parsed_ctor_dtor_cv; bool parsed_ctor_dtor_cv;
bool tag_templates; bool tag_templates;
bool fix_forward_references; bool fix_forward_references;
@ -4647,6 +4900,7 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
Db db(a); Db db(a);
db.cv = 0; db.cv = 0;
db.ref = 0; db.ref = 0;
db.encoding_depth = 0;
db.parsed_ctor_dtor_cv = false; db.parsed_ctor_dtor_cv = false;
db.tag_templates = true; db.tag_templates = true;
db.template_param.emplace_back(a); db.template_param.emplace_back(a);
@ -4699,8 +4953,7 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)
return buf; return buf;
} }
} // unnamed namespace }
#endif #endif