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  | 
