LCOV - code coverage report
Current view: top level - lib/Demangle - ItaniumDemangle.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 982 2438 40.3 %
Date: 2017-09-14 15:23:50 Functions: 39 69 56.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ItaniumDemangle.cpp ------------------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is dual licensed under the MIT and the University of Illinois Open
       6             : // Source Licenses. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/Demangle/Demangle.h"
      11             : 
      12             : // This file exports a single function: llvm::itanium_demangle.
      13             : // It also has no dependencies on the rest of llvm. It is implemented this way
      14             : // so that it can be easily reused in libcxxabi.
      15             : 
      16             : #include <algorithm>
      17             : #include <cctype>
      18             : #include <cstdlib>
      19             : #include <cstring>
      20             : #include <numeric>
      21             : #include <string>
      22             : #include <vector>
      23             : 
      24             : #ifdef _MSC_VER
      25             : // snprintf is implemented in VS 2015
      26             : #if _MSC_VER < 1900
      27             : #define snprintf _snprintf_s
      28             : #endif
      29             : #endif
      30             : 
      31             : enum {
      32             :   unknown_error = -4,
      33             :   invalid_args = -3,
      34             :   invalid_mangled_name,
      35             :   memory_alloc_failure,
      36             :   success
      37             : };
      38             : 
      39             : enum {
      40             :   CV_const = (1 << 0),
      41             :   CV_volatile = (1 << 1),
      42             :   CV_restrict = (1 << 2),
      43             : };
      44             : 
      45             : template <class C>
      46             : static const char *parse_type(const char *first, const char *last, C &db);
      47             : template <class C>
      48             : static const char *parse_encoding(const char *first, const char *last, C &db);
      49             : template <class C>
      50             : static const char *parse_name(const char *first, const char *last, C &db,
      51             :                               bool *ends_with_template_args = 0);
      52             : template <class C>
      53             : static const char *parse_expression(const char *first, const char *last, C &db);
      54             : template <class C>
      55             : static const char *parse_template_args(const char *first, const char *last,
      56             :                                        C &db);
      57             : template <class C>
      58             : static const char *parse_operator_name(const char *first, const char *last,
      59             :                                        C &db);
      60             : template <class C>
      61             : static const char *parse_unqualified_name(const char *first, const char *last,
      62             :                                           C &db);
      63             : template <class C>
      64             : static const char *parse_decltype(const char *first, const char *last, C &db);
      65             : 
      66             : // <number> ::= [n] <non-negative decimal integer>
      67             : 
      68        1218 : static const char *parse_number(const char *first, const char *last) {
      69        1218 :   if (first != last) {
      70        1218 :     const char *t = first;
      71        1218 :     if (*t == 'n')
      72           0 :       ++t;
      73        1218 :     if (t != last) {
      74        1218 :       if (*t == '0') {
      75         193 :         first = t + 1;
      76        1025 :       } else if ('1' <= *t && *t <= '9') {
      77        1024 :         first = t + 1;
      78        4912 :         while (first != last && std::isdigit(*first))
      79        1944 :           ++first;
      80             :       }
      81             :     }
      82             :   }
      83        1218 :   return first;
      84             : }
      85             : 
      86             : namespace {
      87             : template <class Float> struct float_data;
      88             : 
      89             : template <> struct float_data<float> {
      90             :   static const size_t mangled_size = 8;
      91             :   static const size_t max_demangled_size = 24;
      92             :   static const char *spec;
      93             : };
      94             : const char *float_data<float>::spec = "%af";
      95             : 
      96             : template <> struct float_data<double> {
      97             :   static const size_t mangled_size = 16;
      98             :   static const size_t max_demangled_size = 32;
      99             :   static const char *spec;
     100             : };
     101             : 
     102             : const char *float_data<double>::spec = "%a";
     103             : 
     104             : template <> struct float_data<long double> {
     105             : #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) ||        \
     106             :     defined(__wasm__)
     107             :   static const size_t mangled_size = 32;
     108             : #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
     109             :   static const size_t mangled_size = 16;
     110             : #else
     111             :   static const size_t mangled_size =
     112             :       20; // May need to be adjusted to 16 or 24 on other platforms
     113             : #endif
     114             :   static const size_t max_demangled_size = 40;
     115             :   static const char *spec;
     116             : };
     117             : 
     118             : const char *float_data<long double>::spec = "%LaL";
     119             : }
     120             : 
     121             : template <class Float, class C>
     122           0 : static const char *parse_floating_number(const char *first, const char *last,
     123             :                                          C &db) {
     124           0 :   const size_t N = float_data<Float>::mangled_size;
     125           0 :   if (static_cast<std::size_t>(last - first) > N) {
     126           0 :     last = first + N;
     127             :     union {
     128             :       Float value;
     129             :       char buf[sizeof(Float)];
     130           0 :     };
     131           0 :     const char *t = first;
     132           0 :     char *e = buf;
     133           0 :     for (; t != last; ++t, ++e) {
     134           0 :       if (!isxdigit(*t))
     135           0 :         return first;
     136           0 :       unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
     137           0 :                                 : static_cast<unsigned>(*t - 'a' + 10);
     138           0 :       ++t;
     139           0 :       unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
     140           0 :                                 : static_cast<unsigned>(*t - 'a' + 10);
     141           0 :       *e = static_cast<char>((d1 << 4) + d0);
     142             :     }
     143           0 :     if (*t == 'E') {
     144             : #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     145           0 :       std::reverse(buf, e);
     146             : #endif
     147           0 :       char num[float_data<Float>::max_demangled_size] = {0};
     148           0 :       int n = snprintf(num, sizeof(num), float_data<Float>::spec, value);
     149           0 :       if (static_cast<std::size_t>(n) >= sizeof(num))
     150           0 :         return first;
     151           0 :       db.names.push_back(std::string(num, static_cast<std::size_t>(n)));
     152           0 :       first = t + 1;
     153             :     }
     154             :   }
     155             :   return first;
     156             : }
     157             : 
     158             : // <source-name> ::= <positive length number> <identifier>
     159             : 
     160             : template <class C>
     161       12025 : static const char *parse_source_name(const char *first, const char *last,
     162             :                                      C &db) {
     163       12025 :   if (first != last) {
     164       12025 :     char c = *first;
     165       12025 :     if (isdigit(c) && first + 1 != last) {
     166       11759 :       const char *t = first + 1;
     167       11759 :       size_t n = static_cast<size_t>(c - '0');
     168       17244 :       for (c = *t; isdigit(c); c = *t) {
     169        5485 :         n = n * 10 + static_cast<size_t>(c - '0');
     170        5485 :         if (++t == last)
     171             :           return first;
     172             :       }
     173       11759 :       if (static_cast<size_t>(last - t) >= n) {
     174       47036 :         std::string r(t, n);
     175       35277 :         if (r.substr(0, 10) == "_GLOBAL__N")
     176           0 :           db.names.push_back("(anonymous namespace)");
     177             :         else
     178       58795 :           db.names.push_back(std::move(r));
     179       11759 :         first = t + n;
     180             :       }
     181             :     }
     182             :   }
     183             :   return first;
     184             : }
     185             : 
     186             : // <substitution> ::= S <seq-id> _
     187             : //                ::= S_
     188             : // <substitution> ::= Sa # ::std::allocator
     189             : // <substitution> ::= Sb # ::std::basic_string
     190             : // <substitution> ::= Ss # ::std::basic_string < char,
     191             : //                                               ::std::char_traits<char>,
     192             : //                                               ::std::allocator<char> >
     193             : // <substitution> ::= Si # ::std::basic_istream<char,  std::char_traits<char> >
     194             : // <substitution> ::= So # ::std::basic_ostream<char,  std::char_traits<char> >
     195             : // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
     196             : 
     197             : template <class C>
     198        6341 : static const char *parse_substitution(const char *first, const char *last,
     199             :                                       C &db) {
     200        6341 :   if (last - first >= 2) {
     201        6341 :     if (*first == 'S') {
     202        5199 :       switch (first[1]) {
     203        1639 :       case 'a':
     204        4917 :         db.names.push_back("std::allocator");
     205        1639 :         first += 2;
     206        1639 :         break;
     207           0 :       case 'b':
     208           0 :         db.names.push_back("std::basic_string");
     209           0 :         first += 2;
     210           0 :         break;
     211           0 :       case 's':
     212           0 :         db.names.push_back("std::string");
     213           0 :         first += 2;
     214           0 :         break;
     215           0 :       case 'i':
     216           0 :         db.names.push_back("std::istream");
     217           0 :         first += 2;
     218           0 :         break;
     219          46 :       case 'o':
     220         138 :         db.names.push_back("std::ostream");
     221          46 :         first += 2;
     222          46 :         break;
     223           0 :       case 'd':
     224           0 :         db.names.push_back("std::iostream");
     225           0 :         first += 2;
     226           0 :         break;
     227         593 :       case '_':
     228        1186 :         if (!db.subs.empty()) {
     229        3558 :           for (const auto &n : db.subs.front())
     230         593 :             db.names.push_back(n);
     231         593 :           first += 2;
     232             :         }
     233             :         break;
     234        2921 :       default:
     235        2921 :         if (std::isdigit(first[1]) || std::isupper(first[1])) {
     236        2837 :           size_t sub = 0;
     237        2837 :           const char *t = first + 1;
     238        2837 :           if (std::isdigit(*t))
     239        2610 :             sub = static_cast<size_t>(*t - '0');
     240             :           else
     241         227 :             sub = static_cast<size_t>(*t - 'A') + 10;
     242        2837 :           for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t) {
     243           0 :             sub *= 36;
     244           0 :             if (std::isdigit(*t))
     245           0 :               sub += static_cast<size_t>(*t - '0');
     246             :             else
     247           0 :               sub += static_cast<size_t>(*t - 'A') + 10;
     248             :           }
     249        2837 :           if (t == last || *t != '_')
     250             :             return first;
     251        2837 :           ++sub;
     252        5674 :           if (sub < db.subs.size()) {
     253       15441 :             for (const auto &n : db.subs[sub])
     254        2576 :               db.names.push_back(n);
     255        2573 :             first = t + 1;
     256             :           }
     257             :         }
     258             :         break;
     259             :       }
     260             :     }
     261             :   }
     262             :   return first;
     263             : }
     264             : 
     265             : // <builtin-type> ::= v    # void
     266             : //                ::= w    # wchar_t
     267             : //                ::= b    # bool
     268             : //                ::= c    # char
     269             : //                ::= a    # signed char
     270             : //                ::= h    # unsigned char
     271             : //                ::= s    # short
     272             : //                ::= t    # unsigned short
     273             : //                ::= i    # int
     274             : //                ::= j    # unsigned int
     275             : //                ::= l    # long
     276             : //                ::= m    # unsigned long
     277             : //                ::= x    # long long, __int64
     278             : //                ::= y    # unsigned long long, __int64
     279             : //                ::= n    # __int128
     280             : //                ::= o    # unsigned __int128
     281             : //                ::= f    # float
     282             : //                ::= d    # double
     283             : //                ::= e    # long double, __float80
     284             : //                ::= g    # __float128
     285             : //                ::= z    # ellipsis
     286             : //                ::= Dd   # IEEE 754r decimal floating point (64 bits)
     287             : //                ::= De   # IEEE 754r decimal floating point (128 bits)
     288             : //                ::= Df   # IEEE 754r decimal floating point (32 bits)
     289             : //                ::= Dh   # IEEE 754r half-precision floating point (16 bits)
     290             : //                ::= Di   # char32_t
     291             : //                ::= Ds   # char16_t
     292             : //                ::= Da   # auto (in dependent new-expressions)
     293             : //                ::= Dc   # decltype(auto)
     294             : //                ::= Dn   # std::nullptr_t (i.e., decltype(nullptr))
     295             : //                ::= u <source-name>    # vendor extended type
     296             : 
     297             : template <class C>
     298       24611 : static const char *parse_builtin_type(const char *first, const char *last,
     299             :                                       C &db) {
     300       24611 :   if (first != last) {
     301       24611 :     switch (*first) {
     302         748 :     case 'v':
     303        2244 :       db.names.push_back("void");
     304         748 :       ++first;
     305         748 :       break;
     306          26 :     case 'w':
     307          78 :       db.names.push_back("wchar_t");
     308          26 :       ++first;
     309          26 :       break;
     310          16 :     case 'b':
     311          48 :       db.names.push_back("bool");
     312          16 :       ++first;
     313          16 :       break;
     314        3710 :     case 'c':
     315       11130 :       db.names.push_back("char");
     316        3710 :       ++first;
     317        3710 :       break;
     318           0 :     case 'a':
     319           0 :       db.names.push_back("signed char");
     320           0 :       ++first;
     321           0 :       break;
     322           0 :     case 'h':
     323           0 :       db.names.push_back("unsigned char");
     324           0 :       ++first;
     325           0 :       break;
     326           0 :     case 's':
     327           0 :       db.names.push_back("short");
     328           0 :       ++first;
     329           0 :       break;
     330           0 :     case 't':
     331           0 :       db.names.push_back("unsigned short");
     332           0 :       ++first;
     333           0 :       break;
     334         793 :     case 'i':
     335        2379 :       db.names.push_back("int");
     336         793 :       ++first;
     337         793 :       break;
     338         181 :     case 'j':
     339         543 :       db.names.push_back("unsigned int");
     340         181 :       ++first;
     341         181 :       break;
     342         650 :     case 'l':
     343        1950 :       db.names.push_back("long");
     344         650 :       ++first;
     345         650 :       break;
     346         294 :     case 'm':
     347         882 :       db.names.push_back("unsigned long");
     348         294 :       ++first;
     349         294 :       break;
     350           0 :     case 'x':
     351           0 :       db.names.push_back("long long");
     352           0 :       ++first;
     353           0 :       break;
     354           0 :     case 'y':
     355           0 :       db.names.push_back("unsigned long long");
     356           0 :       ++first;
     357           0 :       break;
     358           0 :     case 'n':
     359           0 :       db.names.push_back("__int128");
     360           0 :       ++first;
     361           0 :       break;
     362           0 :     case 'o':
     363           0 :       db.names.push_back("unsigned __int128");
     364           0 :       ++first;
     365           0 :       break;
     366           9 :     case 'f':
     367          27 :       db.names.push_back("float");
     368           9 :       ++first;
     369           9 :       break;
     370           6 :     case 'd':
     371          18 :       db.names.push_back("double");
     372           6 :       ++first;
     373           6 :       break;
     374           0 :     case 'e':
     375           0 :       db.names.push_back("long double");
     376           0 :       ++first;
     377           0 :       break;
     378           0 :     case 'g':
     379           0 :       db.names.push_back("__float128");
     380           0 :       ++first;
     381           0 :       break;
     382           0 :     case 'z':
     383           0 :       db.names.push_back("...");
     384           0 :       ++first;
     385           0 :       break;
     386           0 :     case 'u': {
     387           0 :       const char *t = parse_source_name(first + 1, last, db);
     388           0 :       if (t != first + 1)
     389           0 :         first = t;
     390             :     } break;
     391         251 :     case 'D':
     392         251 :       if (first + 1 != last) {
     393         251 :         switch (first[1]) {
     394           0 :         case 'd':
     395           0 :           db.names.push_back("decimal64");
     396           0 :           first += 2;
     397           0 :           break;
     398           0 :         case 'e':
     399           0 :           db.names.push_back("decimal128");
     400           0 :           first += 2;
     401           0 :           break;
     402           0 :         case 'f':
     403           0 :           db.names.push_back("decimal32");
     404           0 :           first += 2;
     405           0 :           break;
     406           0 :         case 'h':
     407           0 :           db.names.push_back("decimal16");
     408           0 :           first += 2;
     409           0 :           break;
     410           0 :         case 'i':
     411           0 :           db.names.push_back("char32_t");
     412           0 :           first += 2;
     413           0 :           break;
     414           0 :         case 's':
     415           0 :           db.names.push_back("char16_t");
     416           0 :           first += 2;
     417           0 :           break;
     418           0 :         case 'a':
     419           0 :           db.names.push_back("auto");
     420           0 :           first += 2;
     421           0 :           break;
     422           0 :         case 'c':
     423           0 :           db.names.push_back("decltype(auto)");
     424           0 :           first += 2;
     425           0 :           break;
     426           1 :         case 'n':
     427           3 :           db.names.push_back("std::nullptr_t");
     428           1 :           first += 2;
     429           1 :           break;
     430             :         }
     431             :       }
     432             :       break;
     433             :     }
     434             :   }
     435       24611 :   return first;
     436             : }
     437             : 
     438             : // <CV-qualifiers> ::= [r] [V] [K]
     439             : 
     440             : static const char *parse_cv_qualifiers(const char *first, const char *last,
     441             :                                        unsigned &cv) {
     442        5370 :   cv = 0;
     443        4377 :   if (first != last) {
     444        5370 :     if (*first == 'r') {
     445           0 :       cv |= CV_restrict;
     446           0 :       ++first;
     447             :     }
     448        5370 :     if (*first == 'V') {
     449           0 :       cv |= CV_volatile;
     450           0 :       ++first;
     451             :     }
     452        5370 :     if (*first == 'K') {
     453        1100 :       cv |= CV_const;
     454        1100 :       ++first;
     455             :     }
     456             :   }
     457             :   return first;
     458             : }
     459             : 
     460             : // <template-param> ::= T_    # first template parameter
     461             : //                  ::= T <parameter-2 non-negative number> _
     462             : 
     463             : template <class C>
     464        1135 : static const char *parse_template_param(const char *first, const char *last,
     465             :                                         C &db) {
     466        1135 :   if (last - first >= 2) {
     467        1135 :     if (*first == 'T') {
     468        1135 :       if (first[1] == '_') {
     469        1516 :         if (db.template_param.empty())
     470             :           return first;
     471        2274 :         if (!db.template_param.back().empty()) {
     472        5347 :           for (auto &t : db.template_param.back().front())
     473         799 :             db.names.push_back(t);
     474         758 :           first += 2;
     475             :         } else {
     476           0 :           db.names.push_back("T_");
     477           0 :           first += 2;
     478           0 :           db.fix_forward_references = true;
     479             :         }
     480         377 :       } else if (isdigit(first[1])) {
     481         377 :         const char *t = first + 1;
     482         377 :         size_t sub = static_cast<size_t>(*t - '0');
     483         377 :         for (++t; t != last && isdigit(*t); ++t) {
     484           0 :           sub *= 10;
     485           0 :           sub += static_cast<size_t>(*t - '0');
     486             :         }
     487         754 :         if (t == last || *t != '_' || db.template_param.empty())
     488             :           return first;
     489         377 :         ++sub;
     490        1131 :         if (sub < db.template_param.back().size()) {
     491        2654 :           for (auto &temp : db.template_param.back()[sub])
     492         392 :             db.names.push_back(temp);
     493         377 :           first = t + 1;
     494             :         } else {
     495           0 :           db.names.push_back(std::string(first, t + 1));
     496           0 :           first = t + 1;
     497           0 :           db.fix_forward_references = true;
     498             :         }
     499             :       }
     500             :     }
     501             :   }
     502             :   return first;
     503             : }
     504             : 
     505             : // cc <type> <expression>                               # const_cast<type>
     506             : // (expression)
     507             : 
     508             : template <class C>
     509           0 : static const char *parse_const_cast_expr(const char *first, const char *last,
     510             :                                          C &db) {
     511           0 :   if (last - first >= 3 && first[0] == 'c' && first[1] == 'c') {
     512           0 :     const char *t = parse_type(first + 2, last, db);
     513           0 :     if (t != first + 2) {
     514           0 :       const char *t1 = parse_expression(t, last, db);
     515           0 :       if (t1 != t) {
     516           0 :         if (db.names.size() < 2)
     517           0 :           return first;
     518           0 :         auto expr = db.names.back().move_full();
     519           0 :         db.names.pop_back();
     520           0 :         if (db.names.empty())
     521           0 :           return first;
     522           0 :         db.names.back() =
     523           0 :             "const_cast<" + db.names.back().move_full() + ">(" + expr + ")";
     524           0 :         first = t1;
     525             :       }
     526             :     }
     527             :   }
     528             :   return first;
     529             : }
     530             : 
     531             : // dc <type> <expression>                               # dynamic_cast<type>
     532             : // (expression)
     533             : 
     534             : template <class C>
     535           0 : static const char *parse_dynamic_cast_expr(const char *first, const char *last,
     536             :                                            C &db) {
     537           0 :   if (last - first >= 3 && first[0] == 'd' && first[1] == 'c') {
     538           0 :     const char *t = parse_type(first + 2, last, db);
     539           0 :     if (t != first + 2) {
     540           0 :       const char *t1 = parse_expression(t, last, db);
     541           0 :       if (t1 != t) {
     542           0 :         if (db.names.size() < 2)
     543           0 :           return first;
     544           0 :         auto expr = db.names.back().move_full();
     545           0 :         db.names.pop_back();
     546           0 :         if (db.names.empty())
     547           0 :           return first;
     548           0 :         db.names.back() =
     549           0 :             "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")";
     550           0 :         first = t1;
     551             :       }
     552             :     }
     553             :   }
     554             :   return first;
     555             : }
     556             : 
     557             : // rc <type> <expression>                               # reinterpret_cast<type>
     558             : // (expression)
     559             : 
     560             : template <class C>
     561           0 : static const char *parse_reinterpret_cast_expr(const char *first,
     562             :                                                const char *last, C &db) {
     563           0 :   if (last - first >= 3 && first[0] == 'r' && first[1] == 'c') {
     564           0 :     const char *t = parse_type(first + 2, last, db);
     565           0 :     if (t != first + 2) {
     566           0 :       const char *t1 = parse_expression(t, last, db);
     567           0 :       if (t1 != t) {
     568           0 :         if (db.names.size() < 2)
     569           0 :           return first;
     570           0 :         auto expr = db.names.back().move_full();
     571           0 :         db.names.pop_back();
     572           0 :         if (db.names.empty())
     573           0 :           return first;
     574           0 :         db.names.back() = "reinterpret_cast<" + db.names.back().move_full() +
     575             :                           ">(" + expr + ")";
     576           0 :         first = t1;
     577             :       }
     578             :     }
     579             :   }
     580             :   return first;
     581             : }
     582             : 
     583             : // sc <type> <expression>                               # static_cast<type>
     584             : // (expression)
     585             : 
     586             : template <class C>
     587           0 : static const char *parse_static_cast_expr(const char *first, const char *last,
     588             :                                           C &db) {
     589           0 :   if (last - first >= 3 && first[0] == 's' && first[1] == 'c') {
     590           0 :     const char *t = parse_type(first + 2, last, db);
     591           0 :     if (t != first + 2) {
     592           0 :       const char *t1 = parse_expression(t, last, db);
     593           0 :       if (t1 != t) {
     594           0 :         if (db.names.size() < 2)
     595           0 :           return first;
     596           0 :         auto expr = db.names.back().move_full();
     597           0 :         db.names.pop_back();
     598           0 :         db.names.back() =
     599           0 :             "static_cast<" + db.names.back().move_full() + ">(" + expr + ")";
     600           0 :         first = t1;
     601             :       }
     602             :     }
     603             :   }
     604             :   return first;
     605             : }
     606             : 
     607             : // sp <expression>                                  # pack expansion
     608             : 
     609             : template <class C>
     610          34 : static const char *parse_pack_expansion(const char *first, const char *last,
     611             :                                         C &db) {
     612          34 :   if (last - first >= 3 && first[0] == 's' && first[1] == 'p') {
     613          34 :     const char *t = parse_expression(first + 2, last, db);
     614          34 :     if (t != first + 2)
     615          34 :       first = t;
     616             :   }
     617          34 :   return first;
     618             : }
     619             : 
     620             : // st <type>                                            # sizeof (a type)
     621             : 
     622             : template <class C>
     623           0 : static const char *parse_sizeof_type_expr(const char *first, const char *last,
     624             :                                           C &db) {
     625           0 :   if (last - first >= 3 && first[0] == 's' && first[1] == 't') {
     626           0 :     const char *t = parse_type(first + 2, last, db);
     627           0 :     if (t != first + 2) {
     628           0 :       if (db.names.empty())
     629             :         return first;
     630           0 :       db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
     631           0 :       first = t;
     632             :     }
     633             :   }
     634             :   return first;
     635             : }
     636             : 
     637             : // sz <expr>                                            # sizeof (a expression)
     638             : 
     639             : template <class C>
     640           0 : static const char *parse_sizeof_expr_expr(const char *first, const char *last,
     641             :                                           C &db) {
     642           0 :   if (last - first >= 3 && first[0] == 's' && first[1] == 'z') {
     643           0 :     const char *t = parse_expression(first + 2, last, db);
     644           0 :     if (t != first + 2) {
     645           0 :       if (db.names.empty())
     646             :         return first;
     647           0 :       db.names.back() = "sizeof (" + db.names.back().move_full() + ")";
     648           0 :       first = t;
     649             :     }
     650             :   }
     651             :   return first;
     652             : }
     653             : 
     654             : // sZ <template-param>                                  # size of a parameter
     655             : // pack
     656             : 
     657             : template <class C>
     658           0 : static const char *parse_sizeof_param_pack_expr(const char *first,
     659             :                                                 const char *last, C &db) {
     660           0 :   if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' &&
     661           0 :       first[2] == 'T') {
     662           0 :     size_t k0 = db.names.size();
     663           0 :     const char *t = parse_template_param(first + 2, last, db);
     664           0 :     size_t k1 = db.names.size();
     665           0 :     if (t != first + 2) {
     666           0 :       std::string tmp("sizeof...(");
     667           0 :       size_t k = k0;
     668           0 :       if (k != k1) {
     669           0 :         tmp += db.names[k].move_full();
     670           0 :         for (++k; k != k1; ++k)
     671           0 :           tmp += ", " + db.names[k].move_full();
     672             :       }
     673             :       tmp += ")";
     674           0 :       for (; k1 != k0; --k1)
     675           0 :         db.names.pop_back();
     676           0 :       db.names.push_back(std::move(tmp));
     677           0 :       first = t;
     678             :     }
     679             :   }
     680           0 :   return first;
     681             : }
     682             : 
     683             : // <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
     684             : //                  ::= fp <top-level CV-qualifiers> <parameter-2 non-negative
     685             : //                  number> _   # L == 0, second and later parameters
     686             : //                  ::= fL <L-1 non-negative number> p <top-level CV-qualifiers>
     687             : //                  _         # L > 0, first parameter
     688             : //                  ::= fL <L-1 non-negative number> p <top-level CV-qualifiers>
     689             : //                  <parameter-2 non-negative number> _   # L > 0, second and
     690             : //                  later parameters
     691             : 
     692             : template <class C>
     693           1 : static const char *parse_function_param(const char *first, const char *last,
     694             :                                         C &db) {
     695           1 :   if (last - first >= 3 && *first == 'f') {
     696           1 :     if (first[1] == 'p') {
     697             :       unsigned cv;
     698           2 :       const char *t = parse_cv_qualifiers(first + 2, last, cv);
     699           1 :       const char *t1 = parse_number(t, last);
     700           1 :       if (t1 != last && *t1 == '_') {
     701           7 :         db.names.push_back("fp" + std::string(t, t1));
     702           1 :         first = t1 + 1;
     703             :       }
     704           0 :     } else if (first[1] == 'L') {
     705             :       unsigned cv;
     706           0 :       const char *t0 = parse_number(first + 2, last);
     707           0 :       if (t0 != last && *t0 == 'p') {
     708           0 :         ++t0;
     709           0 :         const char *t = parse_cv_qualifiers(t0, last, cv);
     710           0 :         const char *t1 = parse_number(t, last);
     711           0 :         if (t1 != last && *t1 == '_') {
     712           0 :           db.names.push_back("fp" + std::string(t, t1));
     713           0 :           first = t1 + 1;
     714             :         }
     715             :       }
     716             :     }
     717             :   }
     718           1 :   return first;
     719             : }
     720             : 
     721             : // sZ <function-param>                                  # size of a function
     722             : // parameter pack
     723             : 
     724             : template <class C>
     725           0 : static const char *parse_sizeof_function_param_pack_expr(const char *first,
     726             :                                                          const char *last,
     727             :                                                          C &db) {
     728           0 :   if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' &&
     729           0 :       first[2] == 'f') {
     730           0 :     const char *t = parse_function_param(first + 2, last, db);
     731           0 :     if (t != first + 2) {
     732           0 :       if (db.names.empty())
     733             :         return first;
     734           0 :       db.names.back() = "sizeof...(" + db.names.back().move_full() + ")";
     735           0 :       first = t;
     736             :     }
     737             :   }
     738             :   return first;
     739             : }
     740             : 
     741             : // te <expression>                                      # typeid (expression)
     742             : // ti <type>                                            # typeid (type)
     743             : 
     744             : template <class C>
     745           0 : static const char *parse_typeid_expr(const char *first, const char *last,
     746             :                                      C &db) {
     747           0 :   if (last - first >= 3 && first[0] == 't' &&
     748           0 :       (first[1] == 'e' || first[1] == 'i')) {
     749             :     const char *t;
     750           0 :     if (first[1] == 'e')
     751           0 :       t = parse_expression(first + 2, last, db);
     752             :     else
     753           0 :       t = parse_type(first + 2, last, db);
     754           0 :     if (t != first + 2) {
     755           0 :       if (db.names.empty())
     756             :         return first;
     757           0 :       db.names.back() = "typeid(" + db.names.back().move_full() + ")";
     758           0 :       first = t;
     759             :     }
     760             :   }
     761             :   return first;
     762             : }
     763             : 
     764             : // tw <expression>                                      # throw expression
     765             : 
     766             : template <class C>
     767           0 : static const char *parse_throw_expr(const char *first, const char *last,
     768             :                                     C &db) {
     769           0 :   if (last - first >= 3 && first[0] == 't' && first[1] == 'w') {
     770           0 :     const char *t = parse_expression(first + 2, last, db);
     771           0 :     if (t != first + 2) {
     772           0 :       if (db.names.empty())
     773             :         return first;
     774           0 :       db.names.back() = "throw " + db.names.back().move_full();
     775           0 :       first = t;
     776             :     }
     777             :   }
     778             :   return first;
     779             : }
     780             : 
     781             : // ds <expression> <expression>                         # expr.*expr
     782             : 
     783             : template <class C>
     784           0 : static const char *parse_dot_star_expr(const char *first, const char *last,
     785             :                                        C &db) {
     786           0 :   if (last - first >= 3 && first[0] == 'd' && first[1] == 's') {
     787           0 :     const char *t = parse_expression(first + 2, last, db);
     788           0 :     if (t != first + 2) {
     789           0 :       const char *t1 = parse_expression(t, last, db);
     790           0 :       if (t1 != t) {
     791           0 :         if (db.names.size() < 2)
     792           0 :           return first;
     793           0 :         auto expr = db.names.back().move_full();
     794           0 :         db.names.pop_back();
     795           0 :         db.names.back().first += ".*" + expr;
     796           0 :         first = t1;
     797             :       }
     798             :     }
     799             :   }
     800             :   return first;
     801             : }
     802             : 
     803             : // <simple-id> ::= <source-name> [ <template-args> ]
     804             : 
     805             : template <class C>
     806         746 : static const char *parse_simple_id(const char *first, const char *last, C &db) {
     807         746 :   if (first != last) {
     808         746 :     const char *t = parse_source_name(first, last, db);
     809         746 :     if (t != first) {
     810         480 :       const char *t1 = parse_template_args(t, last, db);
     811         480 :       if (t1 != t) {
     812         400 :         if (db.names.size() < 2)
     813           0 :           return first;
     814         800 :         auto args = db.names.back().move_full();
     815         400 :         db.names.pop_back();
     816         600 :         db.names.back().first += std::move(args);
     817             :       }
     818             :       first = t1;
     819             :     } else
     820             :       first = t;
     821             :   }
     822             :   return first;
     823             : }
     824             : 
     825             : // <unresolved-type> ::= <template-param>
     826             : //                   ::= <decltype>
     827             : //                   ::= <substitution>
     828             : 
     829             : template <class C>
     830         266 : static const char *parse_unresolved_type(const char *first, const char *last,
     831             :                                          C &db) {
     832         266 :   if (first != last) {
     833         266 :     const char *t = first;
     834         266 :     switch (*first) {
     835           0 :     case 'T': {
     836           0 :       size_t k0 = db.names.size();
     837           0 :       t = parse_template_param(first, last, db);
     838           0 :       size_t k1 = db.names.size();
     839           0 :       if (t != first && k1 == k0 + 1) {
     840           0 :         db.subs.push_back(typename C::sub_type(1, db.names.back()));
     841           0 :         first = t;
     842             :       } else {
     843           0 :         for (; k1 != k0; --k1)
     844           0 :           db.names.pop_back();
     845             :       }
     846             :       break;
     847             :     }
     848           0 :     case 'D':
     849           0 :       t = parse_decltype(first, last, db);
     850           0 :       if (t != first) {
     851           0 :         if (db.names.empty())
     852             :           return first;
     853           0 :         db.subs.push_back(typename C::sub_type(1, db.names.back()));
     854           0 :         first = t;
     855             :       }
     856             :       break;
     857         266 :     case 'S':
     858         266 :       t = parse_substitution(first, last, db);
     859         266 :       if (t != first)
     860             :         first = t;
     861             :       else {
     862          84 :         if (last - first > 2 && first[1] == 't') {
     863          84 :           t = parse_unqualified_name(first + 2, last, db);
     864          84 :           if (t != first + 2) {
     865         168 :             if (db.names.empty())
     866             :               return first;
     867         168 :             db.names.back().first.insert(0, "std::");
     868         336 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
     869          84 :             first = t;
     870             :           }
     871             :         }
     872             :       }
     873             :       break;
     874             :     }
     875             :   }
     876             :   return first;
     877             : }
     878             : 
     879             : // <destructor-name> ::= <unresolved-type>                               # e.g.,
     880             : // ~T or ~decltype(f())
     881             : //                   ::= <simple-id>                                     # e.g.,
     882             : //                   ~A<2*N>
     883             : 
     884             : template <class C>
     885           0 : static const char *parse_destructor_name(const char *first, const char *last,
     886             :                                          C &db) {
     887           0 :   if (first != last) {
     888           0 :     const char *t = parse_unresolved_type(first, last, db);
     889           0 :     if (t == first)
     890           0 :       t = parse_simple_id(first, last, db);
     891           0 :     if (t != first) {
     892           0 :       if (db.names.empty())
     893             :         return first;
     894           0 :       db.names.back().first.insert(0, "~");
     895           0 :       first = t;
     896             :     }
     897             :   }
     898             :   return first;
     899             : }
     900             : 
     901             : // <base-unresolved-name> ::= <simple-id>                                #
     902             : // unresolved name
     903             : //          extension     ::= <operator-name>                            #
     904             : //          unresolved operator-function-id
     905             : //          extension     ::= <operator-name> <template-args>            #
     906             : //          unresolved operator template-id
     907             : //                        ::= on <operator-name>                         #
     908             : //                        unresolved operator-function-id
     909             : //                        ::= on <operator-name> <template-args>         #
     910             : //                        unresolved operator template-id
     911             : //                        ::= dn <destructor-name>                       #
     912             : //                        destructor or pseudo-destructor;
     913             : //                                                                         #
     914             : //                                                                         e.g.
     915             : //                                                                         ~X or
     916             : //                                                                         ~X<N-1>
     917             : 
     918             : template <class C>
     919         564 : static const char *parse_base_unresolved_name(const char *first,
     920             :                                               const char *last, C &db) {
     921         564 :   if (last - first >= 2) {
     922         564 :     if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') {
     923           0 :       if (first[0] == 'o') {
     924           0 :         const char *t = parse_operator_name(first + 2, last, db);
     925           0 :         if (t != first + 2) {
     926           0 :           first = parse_template_args(t, last, db);
     927           0 :           if (first != t) {
     928           0 :             if (db.names.size() < 2)
     929           0 :               return first;
     930           0 :             auto args = db.names.back().move_full();
     931           0 :             db.names.pop_back();
     932           0 :             db.names.back().first += std::move(args);
     933             :           }
     934             :         }
     935             :       } else {
     936           0 :         const char *t = parse_destructor_name(first + 2, last, db);
     937           0 :         if (t != first + 2)
     938           0 :           first = t;
     939             :       }
     940             :     } else {
     941         564 :       const char *t = parse_simple_id(first, last, db);
     942         564 :       if (t == first) {
     943         266 :         t = parse_operator_name(first, last, db);
     944         266 :         if (t != first) {
     945           0 :           first = parse_template_args(t, last, db);
     946           0 :           if (first != t) {
     947           0 :             if (db.names.size() < 2)
     948           0 :               return first;
     949           0 :             auto args = db.names.back().move_full();
     950           0 :             db.names.pop_back();
     951           0 :             db.names.back().first += std::move(args);
     952             :           }
     953             :         }
     954             :       } else
     955             :         first = t;
     956             :     }
     957             :   }
     958             :   return first;
     959             : }
     960             : 
     961             : // <unresolved-qualifier-level> ::= <simple-id>
     962             : 
     963             : template <class C>
     964             : static const char *parse_unresolved_qualifier_level(const char *first,
     965             :                                                     const char *last, C &db) {
     966         182 :   return parse_simple_id(first, last, db);
     967             : }
     968             : 
     969             : // <unresolved-name>
     970             : //  extension        ::= srN <unresolved-type> [<template-args>]
     971             : //  <unresolved-qualifier-level>* E <base-unresolved-name>
     972             : //                   ::= [gs] <base-unresolved-name>                     # x or
     973             : //                   (with "gs") ::x
     974             : //                   ::= [gs] sr <unresolved-qualifier-level>+ E
     975             : //                   <base-unresolved-name>
     976             : //                                                                       # A::x,
     977             : //                                                                       N::y,
     978             : //                                                                       A<T>::z;
     979             : //                                                                       "gs"
     980             : //                                                                       means
     981             : //                                                                       leading
     982             : //                                                                       "::"
     983             : //                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x
     984             : //                   / decltype(p)::x
     985             : //  extension        ::= sr <unresolved-type> <template-args>
     986             : //  <base-unresolved-name>
     987             : //                                                                       #
     988             : //                                                                       T::N::x
     989             : //                                                                       /decltype(p)::N::x
     990             : //  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E
     991             : //  <base-unresolved-name>
     992             : 
     993             : template <class C>
     994         298 : static const char *parse_unresolved_name(const char *first, const char *last,
     995             :                                          C &db) {
     996         298 :   if (last - first > 2) {
     997         298 :     const char *t = first;
     998         298 :     bool global = false;
     999         298 :     if (t[0] == 'g' && t[1] == 's') {
    1000           0 :       global = true;
    1001           0 :       t += 2;
    1002             :     }
    1003         298 :     const char *t2 = parse_base_unresolved_name(t, last, db);
    1004         298 :     if (t2 != t) {
    1005          32 :       if (global) {
    1006           0 :         if (db.names.empty())
    1007             :           return first;
    1008           0 :         db.names.back().first.insert(0, "::");
    1009             :       }
    1010             :       first = t2;
    1011         266 :     } else if (last - t > 2 && t[0] == 's' && t[1] == 'r') {
    1012         266 :       if (t[2] == 'N') {
    1013         182 :         t += 3;
    1014         182 :         const char *t1 = parse_unresolved_type(t, last, db);
    1015         182 :         if (t1 == t || t1 == last)
    1016           0 :           return first;
    1017         182 :         t = t1;
    1018         182 :         t1 = parse_template_args(t, last, db);
    1019         182 :         if (t1 != t) {
    1020           0 :           if (db.names.size() < 2)
    1021           0 :             return first;
    1022           0 :           auto args = db.names.back().move_full();
    1023           0 :           db.names.pop_back();
    1024           0 :           db.names.back().first += std::move(args);
    1025           0 :           t = t1;
    1026           0 :           if (t == last) {
    1027           0 :             db.names.pop_back();
    1028           0 :             return first;
    1029             :           }
    1030             :         }
    1031         546 :         while (*t != 'E') {
    1032         182 :           t1 = parse_unresolved_qualifier_level(t, last, db);
    1033         364 :           if (t1 == t || t1 == last || db.names.size() < 2)
    1034           0 :             return first;
    1035         728 :           auto s = db.names.back().move_full();
    1036         364 :           db.names.pop_back();
    1037         728 :           db.names.back().first += "::" + std::move(s);
    1038         182 :           t = t1;
    1039             :         }
    1040         182 :         ++t;
    1041         182 :         t1 = parse_base_unresolved_name(t, last, db);
    1042         182 :         if (t1 == t) {
    1043           0 :           if (!db.names.empty())
    1044           0 :             db.names.pop_back();
    1045             :           return first;
    1046             :         }
    1047         364 :         if (db.names.size() < 2)
    1048             :           return first;
    1049         728 :         auto s = db.names.back().move_full();
    1050         364 :         db.names.pop_back();
    1051         728 :         db.names.back().first += "::" + std::move(s);
    1052         182 :         first = t1;
    1053             :       } else {
    1054          84 :         t += 2;
    1055          84 :         const char *t1 = parse_unresolved_type(t, last, db);
    1056          84 :         if (t1 != t) {
    1057          84 :           t = t1;
    1058          84 :           t1 = parse_template_args(t, last, db);
    1059          84 :           if (t1 != t) {
    1060         168 :             if (db.names.size() < 2)
    1061           0 :               return first;
    1062         336 :             auto args = db.names.back().move_full();
    1063         168 :             db.names.pop_back();
    1064         252 :             db.names.back().first += std::move(args);
    1065          84 :             t = t1;
    1066             :           }
    1067          84 :           t1 = parse_base_unresolved_name(t, last, db);
    1068          84 :           if (t1 == t) {
    1069           0 :             if (!db.names.empty())
    1070           0 :               db.names.pop_back();
    1071             :             return first;
    1072             :           }
    1073         168 :           if (db.names.size() < 2)
    1074             :             return first;
    1075         336 :           auto s = db.names.back().move_full();
    1076         168 :           db.names.pop_back();
    1077         336 :           db.names.back().first += "::" + std::move(s);
    1078          84 :           first = t1;
    1079             :         } else {
    1080           0 :           t1 = parse_unresolved_qualifier_level(t, last, db);
    1081           0 :           if (t1 == t || t1 == last)
    1082           0 :             return first;
    1083           0 :           t = t1;
    1084           0 :           if (global) {
    1085           0 :             if (db.names.empty())
    1086             :               return first;
    1087           0 :             db.names.back().first.insert(0, "::");
    1088             :           }
    1089           0 :           while (*t != 'E') {
    1090           0 :             t1 = parse_unresolved_qualifier_level(t, last, db);
    1091           0 :             if (t1 == t || t1 == last || db.names.size() < 2)
    1092           0 :               return first;
    1093           0 :             auto s = db.names.back().move_full();
    1094           0 :             db.names.pop_back();
    1095           0 :             db.names.back().first += "::" + std::move(s);
    1096           0 :             t = t1;
    1097             :           }
    1098           0 :           ++t;
    1099           0 :           t1 = parse_base_unresolved_name(t, last, db);
    1100           0 :           if (t1 == t) {
    1101           0 :             if (!db.names.empty())
    1102           0 :               db.names.pop_back();
    1103             :             return first;
    1104             :           }
    1105           0 :           if (db.names.size() < 2)
    1106             :             return first;
    1107           0 :           auto s = db.names.back().move_full();
    1108           0 :           db.names.pop_back();
    1109           0 :           db.names.back().first += "::" + std::move(s);
    1110           0 :           first = t1;
    1111             :         }
    1112             :       }
    1113             :     }
    1114             :   }
    1115             :   return first;
    1116             : }
    1117             : 
    1118             : // dt <expression> <unresolved-name>                    # expr.name
    1119             : 
    1120             : template <class C>
    1121           1 : static const char *parse_dot_expr(const char *first, const char *last, C &db) {
    1122           1 :   if (last - first >= 3 && first[0] == 'd' && first[1] == 't') {
    1123           1 :     const char *t = parse_expression(first + 2, last, db);
    1124           1 :     if (t != first + 2) {
    1125           1 :       const char *t1 = parse_unresolved_name(t, last, db);
    1126           1 :       if (t1 != t) {
    1127           2 :         if (db.names.size() < 2)
    1128           0 :           return first;
    1129           4 :         auto name = db.names.back().move_full();
    1130           1 :         db.names.pop_back();
    1131           2 :         if (db.names.empty())
    1132           0 :           return first;
    1133           4 :         db.names.back().first += "." + name;
    1134           1 :         first = t1;
    1135             :       }
    1136             :     }
    1137             :   }
    1138             :   return first;
    1139             : }
    1140             : 
    1141             : // cl <expression>+ E                                   # call
    1142             : 
    1143             : template <class C>
    1144          32 : static const char *parse_call_expr(const char *first, const char *last, C &db) {
    1145          32 :   if (last - first >= 4 && first[0] == 'c' && first[1] == 'l') {
    1146          32 :     const char *t = parse_expression(first + 2, last, db);
    1147          32 :     if (t != first + 2) {
    1148          32 :       if (t == last)
    1149             :         return first;
    1150          64 :       if (db.names.empty())
    1151             :         return first;
    1152         128 :       db.names.back().first += db.names.back().second;
    1153          96 :       db.names.back().second = std::string();
    1154          64 :       db.names.back().first.append("(");
    1155          32 :       bool first_expr = true;
    1156          51 :       while (*t != 'E') {
    1157          19 :         const char *t1 = parse_expression(t, last, db);
    1158          19 :         if (t1 == t || t1 == last)
    1159           0 :           return first;
    1160          38 :         if (db.names.empty())
    1161             :           return first;
    1162          76 :         auto tmp = db.names.back().move_full();
    1163          38 :         db.names.pop_back();
    1164          19 :         if (!tmp.empty()) {
    1165          38 :           if (db.names.empty())
    1166           0 :             return first;
    1167             :           if (!first_expr) {
    1168             :             db.names.back().first.append(", ");
    1169             :             first_expr = false;
    1170             :           }
    1171          38 :           db.names.back().first.append(tmp);
    1172             :         }
    1173          19 :         t = t1;
    1174             :       }
    1175          32 :       ++t;
    1176          64 :       if (db.names.empty())
    1177             :         return first;
    1178          64 :       db.names.back().first.append(")");
    1179          32 :       first = t;
    1180             :     }
    1181             :   }
    1182             :   return first;
    1183             : }
    1184             : 
    1185             : // [gs] nw <expression>* _ <type> E                     # new (expr-list) type
    1186             : // [gs] nw <expression>* _ <type> <initializer>         # new (expr-list) type
    1187             : // (init)
    1188             : // [gs] na <expression>* _ <type> E                     # new[] (expr-list) type
    1189             : // [gs] na <expression>* _ <type> <initializer>         # new[] (expr-list) type
    1190             : // (init)
    1191             : // <initializer> ::= pi <expression>* E                 # parenthesized
    1192             : // initialization
    1193             : 
    1194             : template <class C>
    1195           0 : static const char *parse_new_expr(const char *first, const char *last, C &db) {
    1196           0 :   if (last - first >= 4) {
    1197           0 :     const char *t = first;
    1198           0 :     bool parsed_gs = false;
    1199           0 :     if (t[0] == 'g' && t[1] == 's') {
    1200           0 :       t += 2;
    1201           0 :       parsed_gs = true;
    1202             :     }
    1203           0 :     if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a')) {
    1204           0 :       bool is_array = t[1] == 'a';
    1205           0 :       t += 2;
    1206           0 :       if (t == last)
    1207           0 :         return first;
    1208             :       bool has_expr_list = false;
    1209             :       bool first_expr = true;
    1210           0 :       while (*t != '_') {
    1211           0 :         const char *t1 = parse_expression(t, last, db);
    1212           0 :         if (t1 == t || t1 == last)
    1213             :           return first;
    1214             :         has_expr_list = true;
    1215             :         if (!first_expr) {
    1216             :           if (db.names.empty())
    1217             :             return first;
    1218             :           auto tmp = db.names.back().move_full();
    1219             :           db.names.pop_back();
    1220             :           if (!tmp.empty()) {
    1221             :             if (db.names.empty())
    1222             :               return first;
    1223             :             db.names.back().first.append(", ");
    1224             :             db.names.back().first.append(tmp);
    1225             :             first_expr = false;
    1226             :           }
    1227             :         }
    1228             :         t = t1;
    1229             :       }
    1230           0 :       ++t;
    1231           0 :       const char *t1 = parse_type(t, last, db);
    1232           0 :       if (t1 == t || t1 == last)
    1233             :         return first;
    1234           0 :       t = t1;
    1235           0 :       bool has_init = false;
    1236           0 :       if (last - t >= 3 && t[0] == 'p' && t[1] == 'i') {
    1237           0 :         t += 2;
    1238           0 :         has_init = true;
    1239           0 :         first_expr = true;
    1240           0 :         while (*t != 'E') {
    1241           0 :           t1 = parse_expression(t, last, db);
    1242           0 :           if (t1 == t || t1 == last)
    1243             :             return first;
    1244             :           if (!first_expr) {
    1245             :             if (db.names.empty())
    1246             :               return first;
    1247             :             auto tmp = db.names.back().move_full();
    1248             :             db.names.pop_back();
    1249             :             if (!tmp.empty()) {
    1250             :               if (db.names.empty())
    1251             :                 return first;
    1252             :               db.names.back().first.append(", ");
    1253             :               db.names.back().first.append(tmp);
    1254             :               first_expr = false;
    1255             :             }
    1256             :           }
    1257             :           t = t1;
    1258             :         }
    1259             :       }
    1260           0 :       if (*t != 'E')
    1261             :         return first;
    1262           0 :       std::string init_list;
    1263           0 :       if (has_init) {
    1264           0 :         if (db.names.empty())
    1265             :           return first;
    1266           0 :         init_list = db.names.back().move_full();
    1267           0 :         db.names.pop_back();
    1268             :       }
    1269           0 :       if (db.names.empty())
    1270             :         return first;
    1271           0 :       auto type = db.names.back().move_full();
    1272           0 :       db.names.pop_back();
    1273           0 :       std::string expr_list;
    1274           0 :       if (has_expr_list) {
    1275           0 :         if (db.names.empty())
    1276           0 :           return first;
    1277           0 :         expr_list = db.names.back().move_full();
    1278           0 :         db.names.pop_back();
    1279             :       }
    1280           0 :       std::string r;
    1281           0 :       if (parsed_gs)
    1282             :         r = "::";
    1283           0 :       if (is_array)
    1284             :         r += "[] ";
    1285             :       else
    1286             :         r += " ";
    1287           0 :       if (has_expr_list)
    1288           0 :         r += "(" + expr_list + ") ";
    1289           0 :       r += type;
    1290           0 :       if (has_init)
    1291           0 :         r += " (" + init_list + ")";
    1292           0 :       db.names.push_back(std::move(r));
    1293           0 :       first = t + 1;
    1294             :     }
    1295             :   }
    1296             :   return first;
    1297             : }
    1298             : 
    1299             : // cv <type> <expression>                               # conversion with one
    1300             : // argument
    1301             : // cv <type> _ <expression>* E                          # conversion with a
    1302             : // different number of arguments
    1303             : 
    1304             : template <class C>
    1305           0 : static const char *parse_conversion_expr(const char *first, const char *last,
    1306             :                                          C &db) {
    1307           0 :   if (last - first >= 3 && first[0] == 'c' && first[1] == 'v') {
    1308           0 :     bool try_to_parse_template_args = db.try_to_parse_template_args;
    1309           0 :     db.try_to_parse_template_args = false;
    1310           0 :     const char *t = parse_type(first + 2, last, db);
    1311           0 :     db.try_to_parse_template_args = try_to_parse_template_args;
    1312           0 :     if (t != first + 2 && t != last) {
    1313           0 :       if (*t != '_') {
    1314           0 :         const char *t1 = parse_expression(t, last, db);
    1315           0 :         if (t1 == t)
    1316           0 :           return first;
    1317             :         t = t1;
    1318             :       } else {
    1319           0 :         ++t;
    1320           0 :         if (t == last)
    1321             :           return first;
    1322           0 :         if (*t == 'E')
    1323           0 :           db.names.emplace_back();
    1324             :         else {
    1325             :           bool first_expr = true;
    1326           0 :           while (*t != 'E') {
    1327           0 :             const char *t1 = parse_expression(t, last, db);
    1328           0 :             if (t1 == t || t1 == last)
    1329             :               return first;
    1330             :             if (!first_expr) {
    1331             :               if (db.names.empty())
    1332             :                 return first;
    1333             :               auto tmp = db.names.back().move_full();
    1334             :               db.names.pop_back();
    1335             :               if (!tmp.empty()) {
    1336             :                 if (db.names.empty())
    1337             :                   return first;
    1338             :                 db.names.back().first.append(", ");
    1339             :                 db.names.back().first.append(tmp);
    1340             :                 first_expr = false;
    1341             :               }
    1342             :             }
    1343             :             t = t1;
    1344             :           }
    1345             :         }
    1346           0 :         ++t;
    1347             :       }
    1348           0 :       if (db.names.size() < 2)
    1349             :         return first;
    1350           0 :       auto tmp = db.names.back().move_full();
    1351           0 :       db.names.pop_back();
    1352           0 :       db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")";
    1353           0 :       first = t;
    1354             :     }
    1355             :   }
    1356             :   return first;
    1357             : }
    1358             : 
    1359             : // pt <expression> <expression>                    # expr->name
    1360             : 
    1361             : template <class C>
    1362           0 : static const char *parse_arrow_expr(const char *first, const char *last,
    1363             :                                     C &db) {
    1364           0 :   if (last - first >= 3 && first[0] == 'p' && first[1] == 't') {
    1365           0 :     const char *t = parse_expression(first + 2, last, db);
    1366           0 :     if (t != first + 2) {
    1367           0 :       const char *t1 = parse_expression(t, last, db);
    1368           0 :       if (t1 != t) {
    1369           0 :         if (db.names.size() < 2)
    1370           0 :           return first;
    1371           0 :         auto tmp = db.names.back().move_full();
    1372           0 :         db.names.pop_back();
    1373           0 :         db.names.back().first += "->";
    1374           0 :         db.names.back().first += tmp;
    1375           0 :         first = t1;
    1376             :       }
    1377             :     }
    1378             :   }
    1379             :   return first;
    1380             : }
    1381             : 
    1382             : //  <ref-qualifier> ::= R                   # & ref-qualifier
    1383             : //  <ref-qualifier> ::= O                   # && ref-qualifier
    1384             : 
    1385             : // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
    1386             : 
    1387             : template <class C>
    1388         371 : static const char *parse_function_type(const char *first, const char *last,
    1389             :                                        C &db) {
    1390         371 :   if (first != last && *first == 'F') {
    1391         371 :     const char *t = first + 1;
    1392         371 :     if (t != last) {
    1393         371 :       if (*t == 'Y') {
    1394             :         /* extern "C" */
    1395           0 :         if (++t == last)
    1396             :           return first;
    1397             :       }
    1398         371 :       const char *t1 = parse_type(t, last, db);
    1399         371 :       if (t1 != t) {
    1400         371 :         t = t1;
    1401        1113 :         std::string sig("(");
    1402         371 :         int ref_qual = 0;
    1403             :         while (true) {
    1404         742 :           if (t == last) {
    1405           0 :             if (!db.names.empty())
    1406           0 :               db.names.pop_back();
    1407           0 :             return first;
    1408             :           }
    1409         742 :           if (*t == 'E') {
    1410         371 :             ++t;
    1411             :             break;
    1412             :           }
    1413         499 :           if (*t == 'v') {
    1414         128 :             ++t;
    1415         128 :             continue;
    1416             :           }
    1417         243 :           if (*t == 'R' && t + 1 != last && t[1] == 'E') {
    1418           0 :             ref_qual = 1;
    1419           0 :             ++t;
    1420           0 :             continue;
    1421             :           }
    1422         243 :           if (*t == 'O' && t + 1 != last && t[1] == 'E') {
    1423           0 :             ref_qual = 2;
    1424           0 :             ++t;
    1425           0 :             continue;
    1426             :           }
    1427         486 :           size_t k0 = db.names.size();
    1428         243 :           t1 = parse_type(t, last, db);
    1429         486 :           size_t k1 = db.names.size();
    1430         243 :           if (t1 == t || t1 == last)
    1431             :             return first;
    1432         729 :           for (size_t k = k0; k < k1; ++k) {
    1433         243 :             if (sig.size() > 1)
    1434             :               sig += ", ";
    1435        1215 :             sig += db.names[k].move_full();
    1436             :           }
    1437         729 :           for (size_t k = k0; k < k1; ++k)
    1438         243 :             db.names.pop_back();
    1439             :           t = t1;
    1440             :         }
    1441         371 :         sig += ")";
    1442         371 :         switch (ref_qual) {
    1443           0 :         case 1:
    1444             :           sig += " &";
    1445             :           break;
    1446           0 :         case 2:
    1447             :           sig += " &&";
    1448             :           break;
    1449             :         }
    1450         742 :         if (db.names.empty())
    1451             :           return first;
    1452        1113 :         db.names.back().first += " ";
    1453        1113 :         db.names.back().second.insert(0, sig);
    1454         371 :         first = t;
    1455             :       }
    1456             :     }
    1457             :   }
    1458             :   return first;
    1459             : }
    1460             : 
    1461             : // <pointer-to-member-type> ::= M <class type> <member type>
    1462             : 
    1463             : template <class C>
    1464           0 : static const char *parse_pointer_to_member_type(const char *first,
    1465             :                                                 const char *last, C &db) {
    1466           0 :   if (first != last && *first == 'M') {
    1467           0 :     const char *t = parse_type(first + 1, last, db);
    1468           0 :     if (t != first + 1) {
    1469           0 :       const char *t2 = parse_type(t, last, db);
    1470           0 :       if (t2 != t) {
    1471           0 :         if (db.names.size() < 2)
    1472           0 :           return first;
    1473           0 :         auto func = std::move(db.names.back());
    1474           0 :         db.names.pop_back();
    1475           0 :         auto class_type = std::move(db.names.back());
    1476           0 :         if (!func.second.empty() && func.second.front() == '(') {
    1477           0 :           db.names.back().first =
    1478           0 :               std::move(func.first) + "(" + class_type.move_full() + "::*";
    1479           0 :           db.names.back().second = ")" + std::move(func.second);
    1480             :         } else {
    1481           0 :           db.names.back().first =
    1482           0 :               std::move(func.first) + " " + class_type.move_full() + "::*";
    1483           0 :           db.names.back().second = std::move(func.second);
    1484             :         }
    1485           0 :         first = t2;
    1486             :       }
    1487             :     }
    1488             :   }
    1489             :   return first;
    1490             : }
    1491             : 
    1492             : // <array-type> ::= A <positive dimension number> _ <element type>
    1493             : //              ::= A [<dimension expression>] _ <element type>
    1494             : 
    1495             : template <class C>
    1496          22 : static const char *parse_array_type(const char *first, const char *last,
    1497             :                                     C &db) {
    1498          22 :   if (first != last && *first == 'A' && first + 1 != last) {
    1499          22 :     if (first[1] == '_') {
    1500           0 :       const char *t = parse_type(first + 2, last, db);
    1501           0 :       if (t != first + 2) {
    1502           0 :         if (db.names.empty())
    1503             :           return first;
    1504           0 :         if (db.names.back().second.substr(0, 2) == " [")
    1505           0 :           db.names.back().second.erase(0, 1);
    1506           0 :         db.names.back().second.insert(0, " []");
    1507           0 :         first = t;
    1508             :       }
    1509          22 :     } else if ('1' <= first[1] && first[1] <= '9') {
    1510          22 :       const char *t = parse_number(first + 1, last);
    1511          22 :       if (t != last && *t == '_') {
    1512          22 :         const char *t2 = parse_type(t + 1, last, db);
    1513          22 :         if (t2 != t + 1) {
    1514          44 :           if (db.names.empty())
    1515             :             return first;
    1516          88 :           if (db.names.back().second.substr(0, 2) == " [")
    1517           0 :             db.names.back().second.erase(0, 1);
    1518         176 :           db.names.back().second.insert(0,
    1519             :                                         " [" + std::string(first + 1, t) + "]");
    1520          22 :           first = t2;
    1521             :         }
    1522             :       }
    1523             :     } else {
    1524           0 :       const char *t = parse_expression(first + 1, last, db);
    1525           0 :       if (t != first + 1 && t != last && *t == '_') {
    1526           0 :         const char *t2 = parse_type(++t, last, db);
    1527           0 :         if (t2 != t) {
    1528           0 :           if (db.names.size() < 2)
    1529           0 :             return first;
    1530           0 :           auto type = std::move(db.names.back());
    1531           0 :           db.names.pop_back();
    1532           0 :           auto expr = std::move(db.names.back());
    1533           0 :           db.names.back().first = std::move(type.first);
    1534           0 :           if (type.second.substr(0, 2) == " [")
    1535           0 :             type.second.erase(0, 1);
    1536           0 :           db.names.back().second =
    1537           0 :               " [" + expr.move_full() + "]" + std::move(type.second);
    1538           0 :           first = t2;
    1539             :         }
    1540             :       }
    1541             :     }
    1542             :   }
    1543             :   return first;
    1544             : }
    1545             : 
    1546             : // <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class
    1547             : // member access (C++0x)
    1548             : //             ::= DT <expression> E  # decltype of an expression (C++0x)
    1549             : 
    1550             : template <class C>
    1551          13 : static const char *parse_decltype(const char *first, const char *last, C &db) {
    1552          13 :   if (last - first >= 4 && first[0] == 'D') {
    1553          13 :     switch (first[1]) {
    1554          13 :     case 't':
    1555             :     case 'T': {
    1556          13 :       const char *t = parse_expression(first + 2, last, db);
    1557          13 :       if (t != first + 2 && t != last && *t == 'E') {
    1558          26 :         if (db.names.empty())
    1559             :           return first;
    1560         117 :         db.names.back() = "decltype(" + db.names.back().move_full() + ")";
    1561          13 :         first = t + 1;
    1562             :       }
    1563             :     } break;
    1564             :     }
    1565             :   }
    1566             :   return first;
    1567             : }
    1568             : 
    1569             : // extension:
    1570             : // <vector-type>           ::= Dv <positive dimension number> _
    1571             : //                                    <extended element type>
    1572             : //                         ::= Dv [<dimension expression>] _ <element type>
    1573             : // <extended element type> ::= <element type>
    1574             : //                         ::= p # AltiVec vector pixel
    1575             : 
    1576             : template <class C>
    1577           0 : static const char *parse_vector_type(const char *first, const char *last,
    1578             :                                      C &db) {
    1579           0 :   if (last - first > 3 && first[0] == 'D' && first[1] == 'v') {
    1580           0 :     if ('1' <= first[2] && first[2] <= '9') {
    1581           0 :       const char *t = parse_number(first + 2, last);
    1582           0 :       if (t == last || *t != '_')
    1583             :         return first;
    1584           0 :       const char *num = first + 2;
    1585           0 :       size_t sz = static_cast<size_t>(t - num);
    1586           0 :       if (++t != last) {
    1587           0 :         if (*t != 'p') {
    1588           0 :           const char *t1 = parse_type(t, last, db);
    1589           0 :           if (t1 != t) {
    1590           0 :             if (db.names.empty())
    1591             :               return first;
    1592           0 :             db.names.back().first += " vector[" + std::string(num, sz) + "]";
    1593           0 :             first = t1;
    1594             :           }
    1595             :         } else {
    1596           0 :           ++t;
    1597           0 :           db.names.push_back("pixel vector[" + std::string(num, sz) + "]");
    1598           0 :           first = t;
    1599             :         }
    1600             :       }
    1601             :     } else {
    1602           0 :       std::string num;
    1603           0 :       const char *t1 = first + 2;
    1604           0 :       if (*t1 != '_') {
    1605           0 :         const char *t = parse_expression(t1, last, db);
    1606           0 :         if (t != t1) {
    1607           0 :           if (db.names.empty())
    1608           0 :             return first;
    1609           0 :           num = db.names.back().move_full();
    1610           0 :           db.names.pop_back();
    1611           0 :           t1 = t;
    1612             :         }
    1613             :       }
    1614           0 :       if (t1 != last && *t1 == '_' && ++t1 != last) {
    1615           0 :         const char *t = parse_type(t1, last, db);
    1616           0 :         if (t != t1) {
    1617           0 :           if (db.names.empty())
    1618             :             return first;
    1619           0 :           db.names.back().first += " vector[" + num + "]";
    1620           0 :           first = t;
    1621             :         }
    1622             :       }
    1623             :     }
    1624             :   }
    1625             :   return first;
    1626             : }
    1627             : 
    1628             : // <type> ::= <builtin-type>
    1629             : //        ::= <function-type>
    1630             : //        ::= <class-enum-type>
    1631             : //        ::= <array-type>
    1632             : //        ::= <pointer-to-member-type>
    1633             : //        ::= <template-param>
    1634             : //        ::= <template-template-param> <template-args>
    1635             : //        ::= <decltype>
    1636             : //        ::= <substitution>
    1637             : //        ::= <CV-qualifiers> <type>
    1638             : //        ::= P <type>        # pointer-to
    1639             : //        ::= R <type>        # reference-to
    1640             : //        ::= O <type>        # rvalue reference-to (C++0x)
    1641             : //        ::= C <type>        # complex pair (C 2000)
    1642             : //        ::= G <type>        # imaginary (C 2000)
    1643             : //        ::= Dp <type>       # pack expansion (C++0x)
    1644             : //        ::= U <source-name> <type>  # vendor extended type qualifier
    1645             : // extension := U <objc-name> <objc-type>  # objc-type<identifier>
    1646             : // extension := <vector-type> # <vector-type> starts with Dv
    1647             : 
    1648             : // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 +
    1649             : // <number of digits in k1> + k1
    1650             : // <objc-type> := <source-name>  # PU<11+>objcproto 11objc_object<source-name>
    1651             : // 11objc_object -> id<source-name>
    1652             : 
    1653             : template <class C>
    1654       23247 : static const char *parse_type(const char *first, const char *last, C &db) {
    1655       23247 :   if (first != last) {
    1656       22470 :     switch (*first) {
    1657             :     case 'r':
    1658             :     case 'V':
    1659             :     case 'K': {
    1660         993 :       unsigned cv = 0;
    1661         993 :       const char *t = parse_cv_qualifiers(first, last, cv);
    1662         993 :       if (t != first) {
    1663         993 :         bool is_function = *t == 'F';
    1664        1986 :         size_t k0 = db.names.size();
    1665         993 :         const char *t1 = parse_type(t, last, db);
    1666        1986 :         size_t k1 = db.names.size();
    1667         993 :         if (t1 != t) {
    1668         993 :           if (is_function)
    1669           0 :             db.subs.pop_back();
    1670         993 :           db.subs.emplace_back();
    1671        1986 :           for (size_t k = k0; k < k1; ++k) {
    1672         993 :             if (is_function) {
    1673           0 :               auto &name = db.names[k].second;
    1674           0 :               size_t p = name.size();
    1675             : 
    1676           0 :               if (name[p - 2] == '&' && name[p - 1] == '&')
    1677             :                 p -= 2;
    1678           0 :               else if (name.back() == '&')
    1679           0 :                 p -= 1;
    1680             : 
    1681           0 :               if (cv & CV_const) {
    1682           0 :                 name.insert(p, " const");
    1683           0 :                 p += 6;
    1684             :               }
    1685           0 :               if (cv & CV_volatile) {
    1686           0 :                 name.insert(p, " volatile");
    1687           0 :                 p += 9;
    1688             :               }
    1689           0 :               if (cv & CV_restrict)
    1690           0 :                 name.insert(p, " restrict");
    1691             :             } else {
    1692         993 :               if (cv & CV_const)
    1693        1986 :                 db.names[k].first.append(" const");
    1694         993 :               if (cv & CV_volatile)
    1695           0 :                 db.names[k].first.append(" volatile");
    1696         993 :               if (cv & CV_restrict)
    1697           0 :                 db.names[k].first.append(" restrict");
    1698             :             }
    1699        2979 :             db.subs.back().push_back(db.names[k]);
    1700             :           }
    1701             :           first = t1;
    1702             :         }
    1703             :       }
    1704             :     } break;
    1705       21477 :     default: {
    1706       21477 :       const char *t = parse_builtin_type(first, last, db);
    1707       21477 :       if (t != first) {
    1708             :         first = t;
    1709             :       } else {
    1710       15043 :         switch (*first) {
    1711          22 :         case 'A':
    1712          22 :           t = parse_array_type(first, last, db);
    1713          22 :           if (t != first) {
    1714          44 :             if (db.names.empty())
    1715             :               return first;
    1716          22 :             first = t;
    1717          88 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1718             :           }
    1719             :           break;
    1720           0 :         case 'C':
    1721           0 :           t = parse_type(first + 1, last, db);
    1722           0 :           if (t != first + 1) {
    1723           0 :             if (db.names.empty())
    1724             :               return first;
    1725           0 :             db.names.back().first.append(" complex");
    1726           0 :             first = t;
    1727           0 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1728             :           }
    1729             :           break;
    1730         371 :         case 'F':
    1731         371 :           t = parse_function_type(first, last, db);
    1732         371 :           if (t != first) {
    1733         742 :             if (db.names.empty())
    1734             :               return first;
    1735         371 :             first = t;
    1736        1484 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1737             :           }
    1738             :           break;
    1739           0 :         case 'G':
    1740           0 :           t = parse_type(first + 1, last, db);
    1741           0 :           if (t != first + 1) {
    1742           0 :             if (db.names.empty())
    1743             :               return first;
    1744           0 :             db.names.back().first.append(" imaginary");
    1745           0 :             first = t;
    1746           0 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1747             :           }
    1748             :           break;
    1749           0 :         case 'M':
    1750           0 :           t = parse_pointer_to_member_type(first, last, db);
    1751           0 :           if (t != first) {
    1752           0 :             if (db.names.empty())
    1753             :               return first;
    1754           0 :             first = t;
    1755           0 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1756             :           }
    1757             :           break;
    1758         496 :         case 'O': {
    1759         992 :           size_t k0 = db.names.size();
    1760         496 :           t = parse_type(first + 1, last, db);
    1761         992 :           size_t k1 = db.names.size();
    1762         496 :           if (t != first + 1) {
    1763         496 :             db.subs.emplace_back();
    1764        1035 :             for (size_t k = k0; k < k1; ++k) {
    1765        2156 :               if (db.names[k].second.substr(0, 2) == " [") {
    1766           0 :                 db.names[k].first += " (";
    1767           0 :                 db.names[k].second.insert(0, ")");
    1768        1731 :               } else if (!db.names[k].second.empty() &&
    1769         228 :                          db.names[k].second.front() == '(') {
    1770           0 :                 db.names[k].first += "(";
    1771           0 :                 db.names[k].second.insert(0, ")");
    1772             :               }
    1773        1078 :               db.names[k].first.append("&&");
    1774        1617 :               db.subs.back().push_back(db.names[k]);
    1775             :             }
    1776             :             first = t;
    1777             :           }
    1778             :           break;
    1779             :         }
    1780        1263 :         case 'P': {
    1781        2526 :           size_t k0 = db.names.size();
    1782        1263 :           t = parse_type(first + 1, last, db);
    1783        2526 :           size_t k1 = db.names.size();
    1784        1263 :           if (t != first + 1) {
    1785        1263 :             db.subs.emplace_back();
    1786        2526 :             for (size_t k = k0; k < k1; ++k) {
    1787        5052 :               if (db.names[k].second.substr(0, 2) == " [") {
    1788           0 :                 db.names[k].first += " (";
    1789           0 :                 db.names[k].second.insert(0, ")");
    1790        4130 :               } else if (!db.names[k].second.empty() &&
    1791         682 :                          db.names[k].second.front() == '(') {
    1792         682 :                 db.names[k].first += "(";
    1793         682 :                 db.names[k].second.insert(0, ")");
    1794             :               }
    1795        2526 :               if (first[1] != 'U' ||
    1796        2526 :                   db.names[k].first.substr(0, 12) != "objc_object<") {
    1797        2526 :                 db.names[k].first.append("*");
    1798             :               } else {
    1799           0 :                 db.names[k].first.replace(0, 11, "id");
    1800             :               }
    1801        3789 :               db.subs.back().push_back(db.names[k]);
    1802             :             }
    1803             :             first = t;
    1804             :           }
    1805             :           break;
    1806             :         }
    1807        1002 :         case 'R': {
    1808        2004 :           size_t k0 = db.names.size();
    1809        1002 :           t = parse_type(first + 1, last, db);
    1810        2004 :           size_t k1 = db.names.size();
    1811        1002 :           if (t != first + 1) {
    1812        1002 :             db.subs.emplace_back();
    1813        2004 :             for (size_t k = k0; k < k1; ++k) {
    1814        4008 :               if (db.names[k].second.substr(0, 2) == " [") {
    1815          66 :                 db.names[k].first += " (";
    1816          44 :                 db.names[k].second.insert(0, ")");
    1817        3012 :               } else if (!db.names[k].second.empty() &&
    1818         144 :                          db.names[k].second.front() == '(') {
    1819         100 :                 db.names[k].first += "(";
    1820         100 :                 db.names[k].second.insert(0, ")");
    1821             :               }
    1822        2004 :               db.names[k].first.append("&");
    1823        3006 :               db.subs.back().push_back(db.names[k]);
    1824             :             }
    1825             :             first = t;
    1826             :           }
    1827             :           break;
    1828             :         }
    1829        1020 :         case 'T': {
    1830        2040 :           size_t k0 = db.names.size();
    1831        1020 :           t = parse_template_param(first, last, db);
    1832        2040 :           size_t k1 = db.names.size();
    1833        1020 :           if (t != first) {
    1834        1020 :             db.subs.emplace_back();
    1835        2094 :             for (size_t k = k0; k < k1; ++k)
    1836        3222 :               db.subs.back().push_back(db.names[k]);
    1837        1020 :             if (db.try_to_parse_template_args && k1 == k0 + 1) {
    1838         907 :               const char *t1 = parse_template_args(t, last, db);
    1839         907 :               if (t1 != t) {
    1840           0 :                 auto args = db.names.back().move_full();
    1841           0 :                 db.names.pop_back();
    1842           0 :                 db.names.back().first += std::move(args);
    1843           0 :                 db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1844           0 :                 t = t1;
    1845             :               }
    1846             :             }
    1847             :             first = t;
    1848             :           }
    1849             :           break;
    1850             :         }
    1851           0 :         case 'U':
    1852           0 :           if (first + 1 != last) {
    1853           0 :             t = parse_source_name(first + 1, last, db);
    1854           0 :             if (t != first + 1) {
    1855           0 :               const char *t2 = parse_type(t, last, db);
    1856           0 :               if (t2 != t) {
    1857           0 :                 if (db.names.size() < 2)
    1858           0 :                   return first;
    1859           0 :                 auto type = db.names.back().move_full();
    1860           0 :                 db.names.pop_back();
    1861           0 :                 if (db.names.back().first.substr(0, 9) != "objcproto") {
    1862           0 :                   db.names.back() = type + " " + db.names.back().move_full();
    1863             :                 } else {
    1864           0 :                   auto proto = db.names.back().move_full();
    1865           0 :                   db.names.pop_back();
    1866           0 :                   t = parse_source_name(proto.data() + 9,
    1867           0 :                                         proto.data() + proto.size(), db);
    1868           0 :                   if (t != proto.data() + 9) {
    1869           0 :                     db.names.back() =
    1870           0 :                         type + "<" + db.names.back().move_full() + ">";
    1871             :                   } else {
    1872           0 :                     db.names.push_back(type + " " + proto);
    1873             :                   }
    1874             :                 }
    1875           0 :                 db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1876           0 :                 first = t2;
    1877             :               }
    1878             :             }
    1879             :           }
    1880             :           break;
    1881        7485 :         case 'S':
    1882        7485 :           if (first + 1 != last && first[1] == 't') {
    1883        3293 :             t = parse_name(first, last, db);
    1884        3293 :             if (t != first) {
    1885        6586 :               if (db.names.empty())
    1886             :                 return first;
    1887       13172 :               db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1888        3293 :               first = t;
    1889             :             }
    1890             :           } else {
    1891        4192 :             t = parse_substitution(first, last, db);
    1892        4192 :             if (t != first) {
    1893        3928 :               first = t;
    1894             :               // Parsed a substitution.  If the substitution is a
    1895             :               //  <template-param> it might be followed by <template-args>.
    1896        3928 :               t = parse_template_args(first, last, db);
    1897        3928 :               if (t != first) {
    1898        3234 :                 if (db.names.size() < 2)
    1899           0 :                   return first;
    1900        6468 :                 auto template_args = db.names.back().move_full();
    1901        1617 :                 db.names.pop_back();
    1902        4851 :                 db.names.back().first += template_args;
    1903             :                 // Need to create substitution for <template-template-param>
    1904             :                 // <template-args>
    1905        6468 :                 db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1906        1617 :                 first = t;
    1907             :               }
    1908             :             }
    1909             :           }
    1910             :           break;
    1911         250 :         case 'D':
    1912         250 :           if (first + 1 != last) {
    1913         250 :             switch (first[1]) {
    1914         237 :             case 'p': {
    1915         474 :               size_t k0 = db.names.size();
    1916         237 :               t = parse_type(first + 2, last, db);
    1917         474 :               size_t k1 = db.names.size();
    1918         237 :               if (t != first + 2) {
    1919         237 :                 db.subs.emplace_back();
    1920         527 :                 for (size_t k = k0; k < k1; ++k)
    1921         870 :                   db.subs.back().push_back(db.names[k]);
    1922             :                 first = t;
    1923             :                 return first;
    1924             :               }
    1925             :               break;
    1926             :             }
    1927          13 :             case 't':
    1928             :             case 'T':
    1929          13 :               t = parse_decltype(first, last, db);
    1930          13 :               if (t != first) {
    1931          26 :                 if (db.names.empty())
    1932             :                   return first;
    1933          52 :                 db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1934          13 :                 first = t;
    1935          13 :                 return first;
    1936             :               }
    1937             :               break;
    1938           0 :             case 'v':
    1939           0 :               t = parse_vector_type(first, last, db);
    1940           0 :               if (t != first) {
    1941           0 :                 if (db.names.empty())
    1942             :                   return first;
    1943           0 :                 db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1944           0 :                 first = t;
    1945           0 :                 return first;
    1946             :               }
    1947             :               break;
    1948             :             }
    1949             :           }
    1950             :         // falls through
    1951             :         default:
    1952             :           // must check for builtin-types before class-enum-types to avoid
    1953             :           // ambiguities with operator-names
    1954        3134 :           t = parse_builtin_type(first, last, db);
    1955        3134 :           if (t != first) {
    1956             :             first = t;
    1957             :           } else {
    1958        3134 :             t = parse_name(first, last, db);
    1959        3134 :             if (t != first) {
    1960        3624 :               if (db.names.empty())
    1961             :                 return first;
    1962        7248 :               db.subs.push_back(typename C::sub_type(1, db.names.back()));
    1963        1812 :               first = t;
    1964             :             }
    1965             :           }
    1966             :           break;
    1967             :         }
    1968             :       }
    1969             :       break;
    1970             :     }
    1971             :     }
    1972             :   }
    1973             :   return first;
    1974             : }
    1975             : 
    1976             : //   <operator-name>
    1977             : //                   ::= aa    # &&
    1978             : //                   ::= ad    # & (unary)
    1979             : //                   ::= an    # &
    1980             : //                   ::= aN    # &=
    1981             : //                   ::= aS    # =
    1982             : //                   ::= cl    # ()
    1983             : //                   ::= cm    # ,
    1984             : //                   ::= co    # ~
    1985             : //                   ::= cv <type>    # (cast)
    1986             : //                   ::= da    # delete[]
    1987             : //                   ::= de    # * (unary)
    1988             : //                   ::= dl    # delete
    1989             : //                   ::= dv    # /
    1990             : //                   ::= dV    # /=
    1991             : //                   ::= eo    # ^
    1992             : //                   ::= eO    # ^=
    1993             : //                   ::= eq    # ==
    1994             : //                   ::= ge    # >=
    1995             : //                   ::= gt    # >
    1996             : //                   ::= ix    # []
    1997             : //                   ::= le    # <=
    1998             : //                   ::= li <source-name>  # operator ""
    1999             : //                   ::= ls    # <<
    2000             : //                   ::= lS    # <<=
    2001             : //                   ::= lt    # <
    2002             : //                   ::= mi    # -
    2003             : //                   ::= mI    # -=
    2004             : //                   ::= ml    # *
    2005             : //                   ::= mL    # *=
    2006             : //                   ::= mm    # -- (postfix in <expression> context)
    2007             : //                   ::= na    # new[]
    2008             : //                   ::= ne    # !=
    2009             : //                   ::= ng    # - (unary)
    2010             : //                   ::= nt    # !
    2011             : //                   ::= nw    # new
    2012             : //                   ::= oo    # ||
    2013             : //                   ::= or    # |
    2014             : //                   ::= oR    # |=
    2015             : //                   ::= pm    # ->*
    2016             : //                   ::= pl    # +
    2017             : //                   ::= pL    # +=
    2018             : //                   ::= pp    # ++ (postfix in <expression> context)
    2019             : //                   ::= ps    # + (unary)
    2020             : //                   ::= pt    # ->
    2021             : //                   ::= qu    # ?
    2022             : //                   ::= rm    # %
    2023             : //                   ::= rM    # %=
    2024             : //                   ::= rs    # >>
    2025             : //                   ::= rS    # >>=
    2026             : //                   ::= v <digit> <source-name>        # vendor extended
    2027             : //                   operator
    2028             : 
    2029             : template <class C>
    2030        2009 : static const char *parse_operator_name(const char *first, const char *last,
    2031             :                                        C &db) {
    2032        2009 :   if (last - first >= 2) {
    2033        2009 :     switch (first[0]) {
    2034           7 :     case 'a':
    2035           7 :       switch (first[1]) {
    2036           0 :       case 'a':
    2037           0 :         db.names.push_back("operator&&");
    2038           0 :         first += 2;
    2039           0 :         break;
    2040           0 :       case 'd':
    2041             :       case 'n':
    2042           0 :         db.names.push_back("operator&");
    2043           0 :         first += 2;
    2044           0 :         break;
    2045           0 :       case 'N':
    2046           0 :         db.names.push_back("operator&=");
    2047           0 :         first += 2;
    2048           0 :         break;
    2049           7 :       case 'S':
    2050          21 :         db.names.push_back("operator=");
    2051           7 :         first += 2;
    2052           7 :         break;
    2053             :       }
    2054             :       break;
    2055          11 :     case 'c':
    2056          11 :       switch (first[1]) {
    2057          11 :       case 'l':
    2058          33 :         db.names.push_back("operator()");
    2059          11 :         first += 2;
    2060          11 :         break;
    2061           0 :       case 'm':
    2062           0 :         db.names.push_back("operator,");
    2063           0 :         first += 2;
    2064           0 :         break;
    2065           0 :       case 'o':
    2066           0 :         db.names.push_back("operator~");
    2067           0 :         first += 2;
    2068           0 :         break;
    2069           0 :       case 'v': {
    2070           0 :         bool try_to_parse_template_args = db.try_to_parse_template_args;
    2071           0 :         db.try_to_parse_template_args = false;
    2072           0 :         const char *t = parse_type(first + 2, last, db);
    2073           0 :         db.try_to_parse_template_args = try_to_parse_template_args;
    2074           0 :         if (t != first + 2) {
    2075           0 :           if (db.names.empty())
    2076             :             return first;
    2077           0 :           db.names.back().first.insert(0, "operator ");
    2078           0 :           db.parsed_ctor_dtor_cv = true;
    2079           0 :           first = t;
    2080             :         }
    2081             :       } break;
    2082             :       }
    2083             :       break;
    2084         209 :     case 'd':
    2085         209 :       switch (first[1]) {
    2086          14 :       case 'a':
    2087          42 :         db.names.push_back("operator delete[]");
    2088          14 :         first += 2;
    2089          14 :         break;
    2090           4 :       case 'e':
    2091          12 :         db.names.push_back("operator*");
    2092           4 :         first += 2;
    2093           4 :         break;
    2094         191 :       case 'l':
    2095         573 :         db.names.push_back("operator delete");
    2096         191 :         first += 2;
    2097         191 :         break;
    2098           0 :       case 'v':
    2099           0 :         db.names.push_back("operator/");
    2100           0 :         first += 2;
    2101           0 :         break;
    2102           0 :       case 'V':
    2103           0 :         db.names.push_back("operator/=");
    2104           0 :         first += 2;
    2105           0 :         break;
    2106             :       }
    2107             :       break;
    2108           5 :     case 'e':
    2109           5 :       switch (first[1]) {
    2110           0 :       case 'o':
    2111           0 :         db.names.push_back("operator^");
    2112           0 :         first += 2;
    2113           0 :         break;
    2114           0 :       case 'O':
    2115           0 :         db.names.push_back("operator^=");
    2116           0 :         first += 2;
    2117           0 :         break;
    2118           5 :       case 'q':
    2119          15 :         db.names.push_back("operator==");
    2120           5 :         first += 2;
    2121           5 :         break;
    2122             :       }
    2123             :       break;
    2124           0 :     case 'g':
    2125           0 :       switch (first[1]) {
    2126           0 :       case 'e':
    2127           0 :         db.names.push_back("operator>=");
    2128           0 :         first += 2;
    2129           0 :         break;
    2130           0 :       case 't':
    2131           0 :         db.names.push_back("operator>");
    2132           0 :         first += 2;
    2133           0 :         break;
    2134             :       }
    2135             :       break;
    2136           9 :     case 'i':
    2137           9 :       if (first[1] == 'x') {
    2138          27 :         db.names.push_back("operator[]");
    2139           9 :         first += 2;
    2140             :       }
    2141             :       break;
    2142          81 :     case 'l':
    2143          81 :       switch (first[1]) {
    2144           0 :       case 'e':
    2145           0 :         db.names.push_back("operator<=");
    2146           0 :         first += 2;
    2147           0 :         break;
    2148           0 :       case 'i': {
    2149           0 :         const char *t = parse_source_name(first + 2, last, db);
    2150           0 :         if (t != first + 2) {
    2151           0 :           if (db.names.empty())
    2152             :             return first;
    2153           0 :           db.names.back().first.insert(0, "operator\"\" ");
    2154           0 :           first = t;
    2155             :         }
    2156             :       } break;
    2157          80 :       case 's':
    2158         240 :         db.names.push_back("operator<<");
    2159          80 :         first += 2;
    2160          80 :         break;
    2161           0 :       case 'S':
    2162           0 :         db.names.push_back("operator<<=");
    2163           0 :         first += 2;
    2164           0 :         break;
    2165           1 :       case 't':
    2166           3 :         db.names.push_back("operator<");
    2167           1 :         first += 2;
    2168           1 :         break;
    2169             :       }
    2170             :       break;
    2171          12 :     case 'm':
    2172          12 :       switch (first[1]) {
    2173           9 :       case 'i':
    2174          27 :         db.names.push_back("operator-");
    2175           9 :         first += 2;
    2176           9 :         break;
    2177           0 :       case 'I':
    2178           0 :         db.names.push_back("operator-=");
    2179           0 :         first += 2;
    2180           0 :         break;
    2181           0 :       case 'l':
    2182           0 :         db.names.push_back("operator*");
    2183           0 :         first += 2;
    2184           0 :         break;
    2185           0 :       case 'L':
    2186           0 :         db.names.push_back("operator*=");
    2187           0 :         first += 2;
    2188           0 :         break;
    2189           3 :       case 'm':
    2190           9 :         db.names.push_back("operator--");
    2191           3 :         first += 2;
    2192           3 :         break;
    2193             :       }
    2194             :       break;
    2195         253 :     case 'n':
    2196         253 :       switch (first[1]) {
    2197          28 :       case 'a':
    2198          84 :         db.names.push_back("operator new[]");
    2199          28 :         first += 2;
    2200          28 :         break;
    2201           1 :       case 'e':
    2202           3 :         db.names.push_back("operator!=");
    2203           1 :         first += 2;
    2204           1 :         break;
    2205           0 :       case 'g':
    2206           0 :         db.names.push_back("operator-");
    2207           0 :         first += 2;
    2208           0 :         break;
    2209           0 :       case 't':
    2210           0 :         db.names.push_back("operator!");
    2211           0 :         first += 2;
    2212           0 :         break;
    2213         224 :       case 'w':
    2214         672 :         db.names.push_back("operator new");
    2215         224 :         first += 2;
    2216         224 :         break;
    2217             :       }
    2218             :       break;
    2219           0 :     case 'o':
    2220           0 :       switch (first[1]) {
    2221           0 :       case 'o':
    2222           0 :         db.names.push_back("operator||");
    2223           0 :         first += 2;
    2224           0 :         break;
    2225           0 :       case 'r':
    2226           0 :         db.names.push_back("operator|");
    2227           0 :         first += 2;
    2228           0 :         break;
    2229           0 :       case 'R':
    2230           0 :         db.names.push_back("operator|=");
    2231           0 :         first += 2;
    2232           0 :         break;
    2233             :       }
    2234             :       break;
    2235           4 :     case 'p':
    2236           4 :       switch (first[1]) {
    2237           0 :       case 'm':
    2238           0 :         db.names.push_back("operator->*");
    2239           0 :         first += 2;
    2240           0 :         break;
    2241           0 :       case 'l':
    2242           0 :         db.names.push_back("operator+");
    2243           0 :         first += 2;
    2244           0 :         break;
    2245           0 :       case 'L':
    2246           0 :         db.names.push_back("operator+=");
    2247           0 :         first += 2;
    2248           0 :         break;
    2249           4 :       case 'p':
    2250          12 :         db.names.push_back("operator++");
    2251           4 :         first += 2;
    2252           4 :         break;
    2253           0 :       case 's':
    2254           0 :         db.names.push_back("operator+");
    2255           0 :         first += 2;
    2256           0 :         break;
    2257           0 :       case 't':
    2258           0 :         db.names.push_back("operator->");
    2259           0 :         first += 2;
    2260           0 :         break;
    2261             :       }
    2262             :       break;
    2263          10 :     case 'q':
    2264          10 :       if (first[1] == 'u') {
    2265          30 :         db.names.push_back("operator?");
    2266          10 :         first += 2;
    2267             :       }
    2268             :       break;
    2269           0 :     case 'r':
    2270           0 :       switch (first[1]) {
    2271           0 :       case 'm':
    2272           0 :         db.names.push_back("operator%");
    2273           0 :         first += 2;
    2274           0 :         break;
    2275           0 :       case 'M':
    2276           0 :         db.names.push_back("operator%=");
    2277           0 :         first += 2;
    2278           0 :         break;
    2279           0 :       case 's':
    2280           0 :         db.names.push_back("operator>>");
    2281           0 :         first += 2;
    2282           0 :         break;
    2283           0 :       case 'S':
    2284           0 :         db.names.push_back("operator>>=");
    2285           0 :         first += 2;
    2286           0 :         break;
    2287             :       }
    2288             :       break;
    2289           0 :     case 'v':
    2290           0 :       if (std::isdigit(first[1])) {
    2291           0 :         const char *t = parse_source_name(first + 2, last, db);
    2292           0 :         if (t != first + 2) {
    2293           0 :           if (db.names.empty())
    2294             :             return first;
    2295           0 :           db.names.back().first.insert(0, "operator ");
    2296           0 :           first = t;
    2297             :         }
    2298             :       }
    2299             :       break;
    2300             :     }
    2301             :   }
    2302             :   return first;
    2303             : }
    2304             : 
    2305             : template <class C>
    2306        1195 : static const char *parse_integer_literal(const char *first, const char *last,
    2307             :                                          const std::string &lit, C &db) {
    2308        1195 :   const char *t = parse_number(first, last);
    2309        1195 :   if (t != first && t != last && *t == 'E') {
    2310        1195 :     if (lit.size() > 3)
    2311           0 :       db.names.push_back("(" + lit + ")");
    2312             :     else
    2313        1195 :       db.names.emplace_back();
    2314        1195 :     if (*first == 'n') {
    2315           0 :       db.names.back().first += '-';
    2316           0 :       ++first;
    2317             :     }
    2318        3585 :     db.names.back().first.append(first, t);
    2319        1195 :     if (lit.size() <= 3)
    2320        2390 :       db.names.back().first += lit;
    2321        1195 :     first = t + 1;
    2322             :   }
    2323        1195 :   return first;
    2324             : }
    2325             : 
    2326             : // <expr-primary> ::= L <type> <value number> E                          #
    2327             : // integer literal
    2328             : //                ::= L <type> <value float> E                           #
    2329             : //                floating literal
    2330             : //                ::= L <string type> E                                  #
    2331             : //                string literal
    2332             : //                ::= L <nullptr type> E                                 #
    2333             : //                nullptr literal (i.e., "LDnE")
    2334             : //                ::= L <type> <real-part float> _ <imag-part float> E   #
    2335             : //                complex floating point literal (C 2000)
    2336             : //                ::= L <mangled-name> E                                 #
    2337             : //                external name
    2338             : 
    2339             : template <class C>
    2340        1405 : static const char *parse_expr_primary(const char *first, const char *last,
    2341             :                                       C &db) {
    2342        1405 :   if (last - first >= 4 && *first == 'L') {
    2343        1405 :     switch (first[1]) {
    2344             :     case 'w': {
    2345           0 :       const char *t = parse_integer_literal(first + 2, last, "wchar_t", db);
    2346           0 :       if (t != first + 2)
    2347           0 :         first = t;
    2348             :     } break;
    2349         153 :     case 'b':
    2350         153 :       if (first[3] == 'E') {
    2351         153 :         switch (first[2]) {
    2352          64 :         case '0':
    2353         192 :           db.names.push_back("false");
    2354          64 :           first += 4;
    2355          64 :           break;
    2356          89 :         case '1':
    2357         267 :           db.names.push_back("true");
    2358          89 :           first += 4;
    2359          89 :           break;
    2360             :         }
    2361             :       }
    2362             :       break;
    2363             :     case 'c': {
    2364           0 :       const char *t = parse_integer_literal(first + 2, last, "char", db);
    2365           0 :       if (t != first + 2)
    2366           0 :         first = t;
    2367             :     } break;
    2368             :     case 'a': {
    2369           0 :       const char *t = parse_integer_literal(first + 2, last, "signed char", db);
    2370           0 :       if (t != first + 2)
    2371           0 :         first = t;
    2372             :     } break;
    2373             :     case 'h': {
    2374           0 :       const char *t =
    2375           0 :           parse_integer_literal(first + 2, last, "unsigned char", db);
    2376           0 :       if (t != first + 2)
    2377           0 :         first = t;
    2378             :     } break;
    2379             :     case 's': {
    2380           0 :       const char *t = parse_integer_literal(first + 2, last, "short", db);
    2381           0 :       if (t != first + 2)
    2382           0 :         first = t;
    2383             :     } break;
    2384             :     case 't': {
    2385           0 :       const char *t =
    2386           0 :           parse_integer_literal(first + 2, last, "unsigned short", db);
    2387           0 :       if (t != first + 2)
    2388           0 :         first = t;
    2389             :     } break;
    2390             :     case 'i': {
    2391          15 :       const char *t = parse_integer_literal(first + 2, last, "", db);
    2392           5 :       if (t != first + 2)
    2393           5 :         first = t;
    2394             :     } break;
    2395             :     case 'j': {
    2396           0 :       const char *t = parse_integer_literal(first + 2, last, "u", db);
    2397           0 :       if (t != first + 2)
    2398           0 :         first = t;
    2399             :     } break;
    2400             :     case 'l': {
    2401        2664 :       const char *t = parse_integer_literal(first + 2, last, "l", db);
    2402         888 :       if (t != first + 2)
    2403         888 :         first = t;
    2404             :     } break;
    2405             :     case 'm': {
    2406         906 :       const char *t = parse_integer_literal(first + 2, last, "ul", db);
    2407         302 :       if (t != first + 2)
    2408         302 :         first = t;
    2409             :     } break;
    2410             :     case 'x': {
    2411           0 :       const char *t = parse_integer_literal(first + 2, last, "ll", db);
    2412           0 :       if (t != first + 2)
    2413           0 :         first = t;
    2414             :     } break;
    2415             :     case 'y': {
    2416           0 :       const char *t = parse_integer_literal(first + 2, last, "ull", db);
    2417           0 :       if (t != first + 2)
    2418           0 :         first = t;
    2419             :     } break;
    2420             :     case 'n': {
    2421           0 :       const char *t = parse_integer_literal(first + 2, last, "__int128", db);
    2422           0 :       if (t != first + 2)
    2423           0 :         first = t;
    2424             :     } break;
    2425             :     case 'o': {
    2426           0 :       const char *t =
    2427           0 :           parse_integer_literal(first + 2, last, "unsigned __int128", db);
    2428           0 :       if (t != first + 2)
    2429           0 :         first = t;
    2430             :     } break;
    2431           0 :     case 'f': {
    2432           0 :       const char *t = parse_floating_number<float>(first + 2, last, db);
    2433           0 :       if (t != first + 2)
    2434           0 :         first = t;
    2435             :     } break;
    2436           0 :     case 'd': {
    2437           0 :       const char *t = parse_floating_number<double>(first + 2, last, db);
    2438           0 :       if (t != first + 2)
    2439           0 :         first = t;
    2440             :     } break;
    2441           0 :     case 'e': {
    2442           0 :       const char *t = parse_floating_number<long double>(first + 2, last, db);
    2443           0 :       if (t != first + 2)
    2444           0 :         first = t;
    2445             :     } break;
    2446           0 :     case '_':
    2447           0 :       if (first[2] == 'Z') {
    2448           0 :         const char *t = parse_encoding(first + 3, last, db);
    2449           0 :         if (t != first + 3 && t != last && *t == 'E')
    2450           0 :           first = t + 1;
    2451             :       }
    2452             :       break;
    2453             :     case 'T':
    2454             :       // Invalid mangled name per
    2455             :       //   http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
    2456             :       break;
    2457          57 :     default: {
    2458             :       // might be named type
    2459          57 :       const char *t = parse_type(first + 1, last, db);
    2460          57 :       if (t != first + 1 && t != last) {
    2461          57 :         if (*t != 'E') {
    2462             :           const char *n = t;
    2463         114 :           for (; n != last && isdigit(*n); ++n)
    2464             :             ;
    2465          57 :           if (n != t && n != last && *n == 'E') {
    2466         114 :             if (db.names.empty())
    2467             :               return first;
    2468         684 :             db.names.back() =
    2469         114 :                 "(" + db.names.back().move_full() + ")" + std::string(t, n);
    2470          57 :             first = n + 1;
    2471          57 :             break;
    2472             :           }
    2473             :         } else {
    2474           0 :           first = t + 1;
    2475           0 :           break;
    2476             :         }
    2477             :       }
    2478             :     }
    2479             :     }
    2480             :   }
    2481             :   return first;
    2482             : }
    2483             : 
    2484        1417 : static std::string base_name(std::string &s) {
    2485        1417 :   if (s.empty())
    2486             :     return s;
    2487        1417 :   if (s == "std::string") {
    2488           0 :     s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> "
    2489             :         ">";
    2490           0 :     return "basic_string";
    2491             :   }
    2492        1417 :   if (s == "std::istream") {
    2493           0 :     s = "std::basic_istream<char, std::char_traits<char> >";
    2494           0 :     return "basic_istream";
    2495             :   }
    2496        1417 :   if (s == "std::ostream") {
    2497           0 :     s = "std::basic_ostream<char, std::char_traits<char> >";
    2498           0 :     return "basic_ostream";
    2499             :   }
    2500        1417 :   if (s == "std::iostream") {
    2501           0 :     s = "std::basic_iostream<char, std::char_traits<char> >";
    2502           0 :     return "basic_iostream";
    2503             :   }
    2504        1417 :   const char *const pf = s.data();
    2505        1417 :   const char *pe = pf + s.size();
    2506        1417 :   if (pe[-1] == '>') {
    2507             :     unsigned c = 1;
    2508             :     while (true) {
    2509       63560 :       if (--pe == pf)
    2510             :         return std::string();
    2511       63560 :       if (pe[-1] == '<') {
    2512        3261 :         if (--c == 0) {
    2513        1098 :           --pe;
    2514             :           break;
    2515             :         }
    2516       60299 :       } else if (pe[-1] == '>')
    2517        2163 :         ++c;
    2518             :     }
    2519             :   }
    2520        1417 :   if (pe - pf <= 1)
    2521             :     return std::string();
    2522        1417 :   const char *p0 = pe - 1;
    2523       29109 :   for (; p0 != pf; --p0) {
    2524       15261 :     if (*p0 == ':') {
    2525        1415 :       ++p0;
    2526        1415 :       break;
    2527             :     }
    2528       13846 :     if (!isalpha(*p0) && !isdigit(*p0) && *p0 != '_') {
    2529             :       return std::string();
    2530             :     }
    2531             :   }
    2532        4251 :   return std::string(p0, pe);
    2533             : }
    2534             : 
    2535             : // <ctor-dtor-name> ::= C1    # complete object constructor
    2536             : //                  ::= C2    # base object constructor
    2537             : //                  ::= C3    # complete object allocating constructor
    2538             : //   extension      ::= C5    # ?
    2539             : //                  ::= D0    # deleting destructor
    2540             : //                  ::= D1    # complete object destructor
    2541             : //                  ::= D2    # base object destructor
    2542             : //   extension      ::= D5    # ?
    2543             : 
    2544             : template <class C>
    2545        1417 : static const char *parse_ctor_dtor_name(const char *first, const char *last,
    2546             :                                         C &db) {
    2547        2834 :   if (last - first >= 2 && !db.names.empty()) {
    2548        1417 :     switch (first[0]) {
    2549         806 :     case 'C':
    2550         806 :       switch (first[1]) {
    2551             :       case '1':
    2552             :       case '2':
    2553             :       case '3':
    2554             :       case '5':
    2555        1612 :         if (db.names.empty())
    2556             :           return first;
    2557        4030 :         db.names.push_back(base_name(db.names.back().first));
    2558         806 :         first += 2;
    2559         806 :         db.parsed_ctor_dtor_cv = true;
    2560         806 :         break;
    2561             :       }
    2562             :       break;
    2563         611 :     case 'D':
    2564         611 :       switch (first[1]) {
    2565             :       case '0':
    2566             :       case '1':
    2567             :       case '2':
    2568             :       case '5':
    2569        1222 :         if (db.names.empty())
    2570             :           return first;
    2571        3666 :         db.names.push_back("~" + base_name(db.names.back().first));
    2572         611 :         first += 2;
    2573         611 :         db.parsed_ctor_dtor_cv = true;
    2574         611 :         break;
    2575             :       }
    2576             :       break;
    2577             :     }
    2578             :   }
    2579             :   return first;
    2580             : }
    2581             : 
    2582             : // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
    2583             : //                     ::= <closure-type-name>
    2584             : //
    2585             : // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
    2586             : //
    2587             : // <lambda-sig> ::= <parameter type>+  # Parameter types or "v" if the lambda
    2588             : // has no parameters
    2589             : 
    2590             : template <class C>
    2591           0 : static const char *parse_unnamed_type_name(const char *first, const char *last,
    2592             :                                            C &db) {
    2593           0 :   if (last - first > 2 && first[0] == 'U') {
    2594           0 :     char type = first[1];
    2595           0 :     switch (type) {
    2596           0 :     case 't': {
    2597           0 :       db.names.push_back(std::string("'unnamed"));
    2598           0 :       const char *t0 = first + 2;
    2599           0 :       if (t0 == last) {
    2600           0 :         db.names.pop_back();
    2601           0 :         return first;
    2602             :       }
    2603           0 :       if (std::isdigit(*t0)) {
    2604           0 :         const char *t1 = t0 + 1;
    2605           0 :         while (t1 != last && std::isdigit(*t1))
    2606           0 :           ++t1;
    2607           0 :         db.names.back().first.append(t0, t1);
    2608           0 :         t0 = t1;
    2609             :       }
    2610           0 :       db.names.back().first.push_back('\'');
    2611           0 :       if (t0 == last || *t0 != '_') {
    2612           0 :         db.names.pop_back();
    2613           0 :         return first;
    2614             :       }
    2615           0 :       first = t0 + 1;
    2616           0 :     } break;
    2617           0 :     case 'l': {
    2618           0 :       size_t lambda_pos = db.names.size();
    2619           0 :       db.names.push_back(std::string("'lambda'("));
    2620           0 :       const char *t0 = first + 2;
    2621           0 :       if (first[2] == 'v') {
    2622           0 :         db.names.back().first += ')';
    2623           0 :         ++t0;
    2624             :       } else {
    2625           0 :         bool is_first_it = true;
    2626           0 :         while (true) {
    2627           0 :           long k0 = static_cast<long>(db.names.size());
    2628           0 :           const char *t1 = parse_type(t0, last, db);
    2629           0 :           long k1 = static_cast<long>(db.names.size());
    2630           0 :           if (t1 == t0)
    2631             :             break;
    2632           0 :           if (k0 >= k1)
    2633           0 :             return first;
    2634             :           // If the call to parse_type above found a pack expansion
    2635             :           // substitution, then multiple names could have been
    2636             :           // inserted into the name table. Walk through the names,
    2637             :           // appending each onto the lambda's parameter list.
    2638           0 :           std::for_each(db.names.begin() + k0, db.names.begin() + k1,
    2639           0 :                         [&](typename C::sub_type::value_type &pair) {
    2640             :                           if (pair.empty())
    2641             :                             return;
    2642           0 :                           auto &lambda = db.names[lambda_pos].first;
    2643           0 :                           if (!is_first_it)
    2644           0 :                             lambda.append(", ");
    2645           0 :                           is_first_it = false;
    2646           0 :                           lambda.append(pair.move_full());
    2647             :                         });
    2648           0 :           db.names.erase(db.names.begin() + k0, db.names.end());
    2649           0 :           t0 = t1;
    2650             :         }
    2651           0 :         if (is_first_it) {
    2652           0 :           if (!db.names.empty())
    2653           0 :             db.names.pop_back();
    2654             :           return first;
    2655             :         }
    2656           0 :         if (db.names.empty() || db.names.size() - 1 != lambda_pos)
    2657             :           return first;
    2658           0 :         db.names.back().first.append(")");
    2659             :       }
    2660           0 :       if (t0 == last || *t0 != 'E') {
    2661           0 :         if (!db.names.empty())
    2662           0 :           db.names.pop_back();
    2663             :         return first;
    2664             :       }
    2665           0 :       ++t0;
    2666           0 :       if (t0 == last) {
    2667           0 :         if (!db.names.empty())
    2668           0 :           db.names.pop_back();
    2669             :         return first;
    2670             :       }
    2671           0 :       if (std::isdigit(*t0)) {
    2672           0 :         const char *t1 = t0 + 1;
    2673           0 :         while (t1 != last && std::isdigit(*t1))
    2674           0 :           ++t1;
    2675           0 :         db.names.back().first.insert(db.names.back().first.begin() + 7, t0, t1);
    2676           0 :         t0 = t1;
    2677             :       }
    2678           0 :       if (t0 == last || *t0 != '_') {
    2679           0 :         if (!db.names.empty())
    2680           0 :           db.names.pop_back();
    2681             :         return first;
    2682             :       }
    2683           0 :       first = t0 + 1;
    2684           0 :     } break;
    2685             :     }
    2686             :   }
    2687             :   return first;
    2688             : }
    2689             : 
    2690             : // <unqualified-name> ::= <operator-name>
    2691             : //                    ::= <ctor-dtor-name>
    2692             : //                    ::= <source-name>
    2693             : //                    ::= <unnamed-type-name>
    2694             : 
    2695             : template <class C>
    2696       14439 : static const char *parse_unqualified_name(const char *first, const char *last,
    2697             :                                           C &db) {
    2698       14439 :   if (first != last) {
    2699             :     const char *t;
    2700       14439 :     switch (*first) {
    2701        1417 :     case 'C':
    2702             :     case 'D':
    2703        1417 :       t = parse_ctor_dtor_name(first, last, db);
    2704        1417 :       if (t != first)
    2705        1417 :         first = t;
    2706             :       break;
    2707           0 :     case 'U':
    2708           0 :       t = parse_unnamed_type_name(first, last, db);
    2709           0 :       if (t != first)
    2710           0 :         first = t;
    2711             :       break;
    2712       11279 :     case '1':
    2713             :     case '2':
    2714             :     case '3':
    2715             :     case '4':
    2716             :     case '5':
    2717             :     case '6':
    2718             :     case '7':
    2719             :     case '8':
    2720             :     case '9':
    2721       11279 :       t = parse_source_name(first, last, db);
    2722       11279 :       if (t != first)
    2723       11279 :         first = t;
    2724             :       break;
    2725        1743 :     default:
    2726        1743 :       t = parse_operator_name(first, last, db);
    2727        1743 :       if (t != first)
    2728         601 :         first = t;
    2729             :       break;
    2730             :     };
    2731             :   }
    2732       14439 :   return first;
    2733             : }
    2734             : 
    2735             : // <unscoped-name> ::= <unqualified-name>
    2736             : //                 ::= St <unqualified-name>   # ::std::
    2737             : // extension       ::= StL<unqualified-name>
    2738             : 
    2739             : template <class C>
    2740        5770 : static const char *parse_unscoped_name(const char *first, const char *last,
    2741             :                                        C &db) {
    2742        5770 :   if (last - first >= 2) {
    2743        5770 :     const char *t0 = first;
    2744        5770 :     bool St = false;
    2745        5770 :     if (first[0] == 'S' && first[1] == 't') {
    2746        4006 :       t0 += 2;
    2747        4006 :       St = true;
    2748        4006 :       if (t0 != last && *t0 == 'L')
    2749           0 :         ++t0;
    2750             :     }
    2751        5770 :     const char *t1 = parse_unqualified_name(t0, last, db);
    2752        5770 :     if (t1 != t0) {
    2753        4628 :       if (St) {
    2754        8012 :         if (db.names.empty())
    2755             :           return first;
    2756        8012 :         db.names.back().first.insert(0, "std::");
    2757             :       }
    2758             :       first = t1;
    2759             :     }
    2760             :   }
    2761             :   return first;
    2762             : }
    2763             : 
    2764             : // at <type>                                            # alignof (a type)
    2765             : 
    2766             : template <class C>
    2767           0 : static const char *parse_alignof_type(const char *first, const char *last,
    2768             :                                       C &db) {
    2769           0 :   if (last - first >= 3 && first[0] == 'a' && first[1] == 't') {
    2770           0 :     const char *t = parse_type(first + 2, last, db);
    2771           0 :     if (t != first + 2) {
    2772           0 :       if (db.names.empty())
    2773             :         return first;
    2774           0 :       db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
    2775           0 :       first = t;
    2776             :     }
    2777             :   }
    2778             :   return first;
    2779             : }
    2780             : 
    2781             : // az <expression>                                            # alignof (a
    2782             : // expression)
    2783             : 
    2784             : template <class C>
    2785           0 : static const char *parse_alignof_expr(const char *first, const char *last,
    2786             :                                       C &db) {
    2787           0 :   if (last - first >= 3 && first[0] == 'a' && first[1] == 'z') {
    2788           0 :     const char *t = parse_expression(first + 2, last, db);
    2789           0 :     if (t != first + 2) {
    2790           0 :       if (db.names.empty())
    2791             :         return first;
    2792           0 :       db.names.back().first = "alignof (" + db.names.back().move_full() + ")";
    2793           0 :       first = t;
    2794             :     }
    2795             :   }
    2796             :   return first;
    2797             : }
    2798             : 
    2799             : template <class C>
    2800           0 : static const char *parse_noexcept_expression(const char *first,
    2801             :                                              const char *last, C &db) {
    2802           0 :   const char *t1 = parse_expression(first, last, db);
    2803           0 :   if (t1 != first) {
    2804           0 :     if (db.names.empty())
    2805             :       return first;
    2806           0 :     db.names.back().first = "noexcept (" + db.names.back().move_full() + ")";
    2807           0 :     first = t1;
    2808             :   }
    2809             :   return first;
    2810             : }
    2811             : 
    2812             : template <class C>
    2813           2 : static const char *parse_prefix_expression(const char *first, const char *last,
    2814             :                                            const std::string &op,
    2815             :                                            C &db) {
    2816           2 :   const char *t1 = parse_expression(first, last, db);
    2817           2 :   if (t1 != first) {
    2818           4 :     if (db.names.empty())
    2819             :       return first;
    2820          16 :     db.names.back().first = op + "(" + db.names.back().move_full() + ")";
    2821           2 :     first = t1;
    2822             :   }
    2823             :   return first;
    2824             : }
    2825             : 
    2826             : template <class C>
    2827           0 : static const char *parse_binary_expression(const char *first, const char *last,
    2828             :                                            const std::string &op,
    2829             :                                            C &db) {
    2830           0 :   const char *t1 = parse_expression(first, last, db);
    2831           0 :   if (t1 != first) {
    2832           0 :     const char *t2 = parse_expression(t1, last, db);
    2833           0 :     if (t2 != t1) {
    2834           0 :       if (db.names.size() < 2)
    2835           0 :         return first;
    2836           0 :       auto op2 = db.names.back().move_full();
    2837           0 :       db.names.pop_back();
    2838           0 :       auto op1 = db.names.back().move_full();
    2839           0 :       auto &nm = db.names.back().first;
    2840           0 :       nm.clear();
    2841           0 :       if (op == ">")
    2842             :         nm += '(';
    2843           0 :       nm += "(" + op1 + ") " + op + " (" + op2 + ")";
    2844           0 :       if (op == ">")
    2845             :         nm += ')';
    2846           0 :       first = t2;
    2847           0 :     } else if (!db.names.empty())
    2848           0 :       db.names.pop_back();
    2849             :   }
    2850             :   return first;
    2851             : }
    2852             : 
    2853             : // <expression> ::= <unary operator-name> <expression>
    2854             : //              ::= <binary operator-name> <expression> <expression>
    2855             : //              ::= <ternary operator-name> <expression> <expression>
    2856             : //              <expression>
    2857             : //              ::= cl <expression>+ E                                   # call
    2858             : //              ::= cv <type> <expression>                               #
    2859             : //              conversion with one argument
    2860             : //              ::= cv <type> _ <expression>* E                          #
    2861             : //              conversion with a different number of arguments
    2862             : //              ::= [gs] nw <expression>* _ <type> E                     # new
    2863             : //              (expr-list) type
    2864             : //              ::= [gs] nw <expression>* _ <type> <initializer>         # new
    2865             : //              (expr-list) type (init)
    2866             : //              ::= [gs] na <expression>* _ <type> E                     # new[]
    2867             : //              (expr-list) type
    2868             : //              ::= [gs] na <expression>* _ <type> <initializer>         # new[]
    2869             : //              (expr-list) type (init)
    2870             : //              ::= [gs] dl <expression>                                 #
    2871             : //              delete expression
    2872             : //              ::= [gs] da <expression>                                 #
    2873             : //              delete[] expression
    2874             : //              ::= pp_ <expression>                                     #
    2875             : //              prefix ++
    2876             : //              ::= mm_ <expression>                                     #
    2877             : //              prefix --
    2878             : //              ::= ti <type>                                            #
    2879             : //              typeid (type)
    2880             : //              ::= te <expression>                                      #
    2881             : //              typeid (expression)
    2882             : //              ::= dc <type> <expression>                               #
    2883             : //              dynamic_cast<type> (expression)
    2884             : //              ::= sc <type> <expression>                               #
    2885             : //              static_cast<type> (expression)
    2886             : //              ::= cc <type> <expression>                               #
    2887             : //              const_cast<type> (expression)
    2888             : //              ::= rc <type> <expression>                               #
    2889             : //              reinterpret_cast<type> (expression)
    2890             : //              ::= st <type>                                            #
    2891             : //              sizeof (a type)
    2892             : //              ::= sz <expression>                                      #
    2893             : //              sizeof (an expression)
    2894             : //              ::= at <type>                                            #
    2895             : //              alignof (a type)
    2896             : //              ::= az <expression>                                      #
    2897             : //              alignof (an expression)
    2898             : //              ::= nx <expression>                                      #
    2899             : //              noexcept (expression)
    2900             : //              ::= <template-param>
    2901             : //              ::= <function-param>
    2902             : //              ::= dt <expression> <unresolved-name>                    #
    2903             : //              expr.name
    2904             : //              ::= pt <expression> <unresolved-name>                    #
    2905             : //              expr->name
    2906             : //              ::= ds <expression> <expression>                         #
    2907             : //              expr.*expr
    2908             : //              ::= sZ <template-param>                                  # size
    2909             : //              of a parameter pack
    2910             : //              ::= sZ <function-param>                                  # size
    2911             : //              of a function parameter pack
    2912             : //              ::= sp <expression>                                      # pack
    2913             : //              expansion
    2914             : //              ::= tw <expression>                                      # throw
    2915             : //              expression
    2916             : //              ::= tr                                                   # throw
    2917             : //              with no operand (rethrow)
    2918             : //              ::= <unresolved-name>                                    # f(p),
    2919             : //              N::f(p), ::f(p),
    2920             : //                                                                       #
    2921             : //                                                                       freestanding
    2922             : //                                                                       dependent
    2923             : //                                                                       name
    2924             : //                                                                       (e.g.,
    2925             : //                                                                       T::x),
    2926             : //                                                                       #
    2927             : //                                                                       objectless
    2928             : //                                                                       nonstatic
    2929             : //                                                                       member
    2930             : //                                                                       reference
    2931             : //              ::= <expr-primary>
    2932             : 
    2933             : template <class C>
    2934         482 : static const char *parse_expression(const char *first, const char *last,
    2935             :                                     C &db) {
    2936         482 :   if (last - first >= 2) {
    2937         482 :     const char *t = first;
    2938         482 :     bool parsed_gs = false;
    2939         482 :     if (last - first >= 4 && t[0] == 'g' && t[1] == 's') {
    2940           0 :       t += 2;
    2941           0 :       parsed_gs = true;
    2942             :     }
    2943         482 :     switch (*t) {
    2944           0 :     case 'L':
    2945           0 :       first = parse_expr_primary(first, last, db);
    2946           0 :       break;
    2947         115 :     case 'T':
    2948         115 :       first = parse_template_param(first, last, db);
    2949         115 :       break;
    2950           1 :     case 'f':
    2951           1 :       first = parse_function_param(first, last, db);
    2952           1 :       break;
    2953           0 :     case 'a':
    2954           0 :       switch (t[1]) {
    2955             :       case 'a':
    2956           0 :         t = parse_binary_expression(first + 2, last, "&&", db);
    2957           0 :         if (t != first + 2)
    2958           0 :           first = t;
    2959             :         break;
    2960             :       case 'd':
    2961           0 :         t = parse_prefix_expression(first + 2, last, "&", db);
    2962           0 :         if (t != first + 2)
    2963           0 :           first = t;
    2964             :         break;
    2965             :       case 'n':
    2966           0 :         t = parse_binary_expression(first + 2, last, "&", db);
    2967           0 :         if (t != first + 2)
    2968           0 :           first = t;
    2969             :         break;
    2970             :       case 'N':
    2971           0 :         t = parse_binary_expression(first + 2, last, "&=", db);
    2972           0 :         if (t != first + 2)
    2973           0 :           first = t;
    2974             :         break;
    2975             :       case 'S':
    2976           0 :         t = parse_binary_expression(first + 2, last, "=", db);
    2977           0 :         if (t != first + 2)
    2978           0 :           first = t;
    2979             :         break;
    2980           0 :       case 't':
    2981           0 :         first = parse_alignof_type(first, last, db);
    2982           0 :         break;
    2983           0 :       case 'z':
    2984           0 :         first = parse_alignof_expr(first, last, db);
    2985           0 :         break;
    2986             :       }
    2987             :       break;
    2988          32 :     case 'c':
    2989          32 :       switch (t[1]) {
    2990           0 :       case 'c':
    2991           0 :         first = parse_const_cast_expr(first, last, db);
    2992           0 :         break;
    2993          32 :       case 'l':
    2994          32 :         first = parse_call_expr(first, last, db);
    2995          32 :         break;
    2996             :       case 'm':
    2997           0 :         t = parse_binary_expression(first + 2, last, ",", db);
    2998           0 :         if (t != first + 2)
    2999           0 :           first = t;
    3000             :         break;
    3001             :       case 'o':
    3002           0 :         t = parse_prefix_expression(first + 2, last, "~", db);
    3003           0 :         if (t != first + 2)
    3004           0 :           first = t;
    3005             :         break;
    3006           0 :       case 'v':
    3007           0 :         first = parse_conversion_expr(first, last, db);
    3008           0 :         break;
    3009             :       }
    3010             :       break;
    3011           1 :     case 'd':
    3012           1 :       switch (t[1]) {
    3013           0 :       case 'a': {
    3014           0 :         const char *t1 = parse_expression(t + 2, last, db);
    3015           0 :         if (t1 != t + 2) {
    3016           0 :           if (db.names.empty())
    3017             :             return first;
    3018           0 :           db.names.back().first =
    3019             :               (parsed_gs ? std::string("::") : std::string()) + "delete[] " +
    3020           0 :               db.names.back().move_full();
    3021           0 :           first = t1;
    3022             :         }
    3023             :       } break;
    3024           0 :       case 'c':
    3025           0 :         first = parse_dynamic_cast_expr(first, last, db);
    3026           0 :         break;
    3027             :       case 'e':
    3028           0 :         t = parse_prefix_expression(first + 2, last, "*", db);
    3029           0 :         if (t != first + 2)
    3030           0 :           first = t;
    3031             :         break;
    3032           0 :       case 'l': {
    3033           0 :         const char *t1 = parse_expression(t + 2, last, db);
    3034           0 :         if (t1 != t + 2) {
    3035           0 :           if (db.names.empty())
    3036             :             return first;
    3037           0 :           db.names.back().first =
    3038             :               (parsed_gs ? std::string("::") : std::string()) + "delete " +
    3039           0 :               db.names.back().move_full();
    3040           0 :           first = t1;
    3041             :         }
    3042             :       } break;
    3043           0 :       case 'n':
    3044           0 :         return parse_unresolved_name(first, last, db);
    3045           0 :       case 's':
    3046           0 :         first = parse_dot_star_expr(first, last, db);
    3047           0 :         break;
    3048           1 :       case 't':
    3049           1 :         first = parse_dot_expr(first, last, db);
    3050           1 :         break;
    3051             :       case 'v':
    3052           0 :         t = parse_binary_expression(first + 2, last, "/", db);
    3053           0 :         if (t != first + 2)
    3054           0 :           first = t;
    3055             :         break;
    3056             :       case 'V':
    3057           0 :         t = parse_binary_expression(first + 2, last, "/=", db);
    3058           0 :         if (t != first + 2)
    3059           0 :           first = t;
    3060             :         break;
    3061             :       }
    3062             :       break;
    3063           0 :     case 'e':
    3064           0 :       switch (t[1]) {
    3065             :       case 'o':
    3066           0 :         t = parse_binary_expression(first + 2, last, "^", db);
    3067           0 :         if (t != first + 2)
    3068           0 :           first = t;
    3069             :         break;
    3070             :       case 'O':
    3071           0 :         t = parse_binary_expression(first + 2, last, "^=", db);
    3072           0 :         if (t != first + 2)
    3073           0 :           first = t;
    3074             :         break;
    3075             :       case 'q':
    3076           0 :         t = parse_binary_expression(first + 2, last, "==", db);
    3077           0 :         if (t != first + 2)
    3078           0 :           first = t;
    3079             :         break;
    3080             :       }
    3081             :       break;
    3082           0 :     case 'g':
    3083           0 :       switch (t[1]) {
    3084             :       case 'e':
    3085           0 :         t = parse_binary_expression(first + 2, last, ">=", db);
    3086           0 :         if (t != first + 2)
    3087           0 :           first = t;
    3088             :         break;
    3089             :       case 't':
    3090           0 :         t = parse_binary_expression(first + 2, last, ">", db);
    3091           0 :         if (t != first + 2)
    3092           0 :           first = t;
    3093             :         break;
    3094             :       }
    3095             :       break;
    3096           0 :     case 'i':
    3097           0 :       if (t[1] == 'x') {
    3098           0 :         const char *t1 = parse_expression(first + 2, last, db);
    3099           0 :         if (t1 != first + 2) {
    3100           0 :           const char *t2 = parse_expression(t1, last, db);
    3101           0 :           if (t2 != t1) {
    3102           0 :             if (db.names.size() < 2)
    3103           0 :               return first;
    3104           0 :             auto op2 = db.names.back().move_full();
    3105           0 :             db.names.pop_back();
    3106           0 :             auto op1 = db.names.back().move_full();
    3107           0 :             db.names.back() = "(" + op1 + ")[" + op2 + "]";
    3108           0 :             first = t2;
    3109           0 :           } else if (!db.names.empty())
    3110           0 :             db.names.pop_back();
    3111             :         }
    3112             :       }
    3113             :       break;
    3114           0 :     case 'l':
    3115           0 :       switch (t[1]) {
    3116             :       case 'e':
    3117           0 :         t = parse_binary_expression(first + 2, last, "<=", db);
    3118           0 :         if (t != first + 2)
    3119           0 :           first = t;
    3120             :         break;
    3121             :       case 's':
    3122           0 :         t = parse_binary_expression(first + 2, last, "<<", db);
    3123           0 :         if (t != first + 2)
    3124           0 :           first = t;
    3125             :         break;
    3126             :       case 'S':
    3127           0 :         t = parse_binary_expression(first + 2, last, "<<=", db);
    3128           0 :         if (t != first + 2)
    3129           0 :           first = t;
    3130             :         break;
    3131             :       case 't':
    3132           0 :         t = parse_binary_expression(first + 2, last, "<", db);
    3133           0 :         if (t != first + 2)
    3134           0 :           first = t;
    3135             :         break;
    3136             :       }
    3137             :       break;
    3138           0 :     case 'm':
    3139           0 :       switch (t[1]) {
    3140             :       case 'i':
    3141           0 :         t = parse_binary_expression(first + 2, last, "-", db);
    3142           0 :         if (t != first + 2)
    3143           0 :           first = t;
    3144             :         break;
    3145             :       case 'I':
    3146           0 :         t = parse_binary_expression(first + 2, last, "-=", db);
    3147           0 :         if (t != first + 2)
    3148           0 :           first = t;
    3149             :         break;
    3150             :       case 'l':
    3151           0 :         t = parse_binary_expression(first + 2, last, "*", db);
    3152           0 :         if (t != first + 2)
    3153           0 :           first = t;
    3154             :         break;
    3155             :       case 'L':
    3156           0 :         t = parse_binary_expression(first + 2, last, "*=", db);
    3157           0 :         if (t != first + 2)
    3158           0 :           first = t;
    3159             :         break;
    3160           0 :       case 'm':
    3161           0 :         if (first + 2 != last && first[2] == '_') {
    3162           0 :           t = parse_prefix_expression(first + 3, last, "--", db);
    3163           0 :           if (t != first + 3)
    3164           0 :             first = t;
    3165             :         } else {
    3166           0 :           const char *t1 = parse_expression(first + 2, last, db);
    3167           0 :           if (t1 != first + 2) {
    3168           0 :             if (db.names.empty())
    3169             :               return first;
    3170           0 :             db.names.back() = "(" + db.names.back().move_full() + ")--";
    3171           0 :             first = t1;
    3172             :           }
    3173             :         }
    3174             :         break;
    3175             :       }
    3176             :       break;
    3177           2 :     case 'n':
    3178           2 :       switch (t[1]) {
    3179           0 :       case 'a':
    3180             :       case 'w':
    3181           0 :         first = parse_new_expr(first, last, db);
    3182           0 :         break;
    3183             :       case 'e':
    3184           0 :         t = parse_binary_expression(first + 2, last, "!=", db);
    3185           0 :         if (t != first + 2)
    3186           0 :           first = t;
    3187             :         break;
    3188             :       case 'g':
    3189           0 :         t = parse_prefix_expression(first + 2, last, "-", db);
    3190           0 :         if (t != first + 2)
    3191           0 :           first = t;
    3192             :         break;
    3193             :       case 't':
    3194           6 :         t = parse_prefix_expression(first + 2, last, "!", db);
    3195           2 :         if (t != first + 2)
    3196           2 :           first = t;
    3197             :         break;
    3198           0 :       case 'x':
    3199           0 :         t = parse_noexcept_expression(first + 2, last, db);
    3200           0 :         if (t != first + 2)
    3201           0 :           first = t;
    3202             :         break;
    3203             :       }
    3204             :       break;
    3205           0 :     case 'o':
    3206           0 :       switch (t[1]) {
    3207           0 :       case 'n':
    3208           0 :         return parse_unresolved_name(first, last, db);
    3209             :       case 'o':
    3210           0 :         t = parse_binary_expression(first + 2, last, "||", db);
    3211           0 :         if (t != first + 2)
    3212           0 :           first = t;
    3213             :         break;
    3214             :       case 'r':
    3215           0 :         t = parse_binary_expression(first + 2, last, "|", db);
    3216           0 :         if (t != first + 2)
    3217           0 :           first = t;
    3218             :         break;
    3219             :       case 'R':
    3220           0 :         t = parse_binary_expression(first + 2, last, "|=", db);
    3221           0 :         if (t != first + 2)
    3222           0 :           first = t;
    3223             :         break;
    3224             :       }
    3225             :       break;
    3226           0 :     case 'p':
    3227           0 :       switch (t[1]) {
    3228             :       case 'm':
    3229           0 :         t = parse_binary_expression(first + 2, last, "->*", db);
    3230           0 :         if (t != first + 2)
    3231           0 :           first = t;
    3232             :         break;
    3233             :       case 'l':
    3234           0 :         t = parse_binary_expression(first + 2, last, "+", db);
    3235           0 :         if (t != first + 2)
    3236           0 :           first = t;
    3237             :         break;
    3238             :       case 'L':
    3239           0 :         t = parse_binary_expression(first + 2, last, "+=", db);
    3240           0 :         if (t != first + 2)
    3241           0 :           first = t;
    3242             :         break;
    3243           0 :       case 'p':
    3244           0 :         if (first + 2 != last && first[2] == '_') {
    3245           0 :           t = parse_prefix_expression(first + 3, last, "++", db);
    3246           0 :           if (t != first + 3)
    3247           0 :             first = t;
    3248             :         } else {
    3249           0 :           const char *t1 = parse_expression(first + 2, last, db);
    3250           0 :           if (t1 != first + 2) {
    3251           0 :             if (db.names.empty())
    3252             :               return first;
    3253           0 :             db.names.back() = "(" + db.names.back().move_full() + ")++";
    3254           0 :             first = t1;
    3255             :           }
    3256             :         }
    3257             :         break;
    3258             :       case 's':
    3259           0 :         t = parse_prefix_expression(first + 2, last, "+", db);
    3260           0 :         if (t != first + 2)
    3261           0 :           first = t;
    3262             :         break;
    3263           0 :       case 't':
    3264           0 :         first = parse_arrow_expr(first, last, db);
    3265           0 :         break;
    3266             :       }
    3267             :       break;
    3268           0 :     case 'q':
    3269           0 :       if (t[1] == 'u') {
    3270           0 :         const char *t1 = parse_expression(first + 2, last, db);
    3271           0 :         if (t1 != first + 2) {
    3272           0 :           const char *t2 = parse_expression(t1, last, db);
    3273           0 :           if (t2 != t1) {
    3274           0 :             const char *t3 = parse_expression(t2, last, db);
    3275           0 :             if (t3 != t2) {
    3276           0 :               if (db.names.size() < 3)
    3277           0 :                 return first;
    3278           0 :               auto op3 = db.names.back().move_full();
    3279           0 :               db.names.pop_back();
    3280           0 :               auto op2 = db.names.back().move_full();
    3281           0 :               db.names.pop_back();
    3282           0 :               auto op1 = db.names.back().move_full();
    3283           0 :               db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")";
    3284           0 :               first = t3;
    3285             :             } else {
    3286           0 :               if (db.names.size() < 2)
    3287             :                 return first;
    3288           0 :               db.names.pop_back();
    3289           0 :               db.names.pop_back();
    3290             :             }
    3291           0 :           } else if (!db.names.empty())
    3292           0 :             db.names.pop_back();
    3293             :         }
    3294             :       }
    3295             :       break;
    3296           0 :     case 'r':
    3297           0 :       switch (t[1]) {
    3298           0 :       case 'c':
    3299           0 :         first = parse_reinterpret_cast_expr(first, last, db);
    3300           0 :         break;
    3301             :       case 'm':
    3302           0 :         t = parse_binary_expression(first + 2, last, "%", db);
    3303           0 :         if (t != first + 2)
    3304           0 :           first = t;
    3305             :         break;
    3306             :       case 'M':
    3307           0 :         t = parse_binary_expression(first + 2, last, "%=", db);
    3308           0 :         if (t != first + 2)
    3309           0 :           first = t;
    3310             :         break;
    3311             :       case 's':
    3312           0 :         t = parse_binary_expression(first + 2, last, ">>", db);
    3313           0 :         if (t != first + 2)
    3314           0 :           first = t;
    3315             :         break;
    3316             :       case 'S':
    3317           0 :         t = parse_binary_expression(first + 2, last, ">>=", db);
    3318           0 :         if (t != first + 2)
    3319           0 :           first = t;
    3320             :         break;
    3321             :       }
    3322             :       break;
    3323         300 :     case 's':
    3324         300 :       switch (t[1]) {
    3325           0 :       case 'c':
    3326           0 :         first = parse_static_cast_expr(first, last, db);
    3327           0 :         break;
    3328          34 :       case 'p':
    3329          34 :         first = parse_pack_expansion(first, last, db);
    3330          34 :         break;
    3331         266 :       case 'r':
    3332         266 :         return parse_unresolved_name(first, last, db);
    3333           0 :       case 't':
    3334           0 :         first = parse_sizeof_type_expr(first, last, db);
    3335           0 :         break;
    3336           0 :       case 'z':
    3337           0 :         first = parse_sizeof_expr_expr(first, last, db);
    3338           0 :         break;
    3339           0 :       case 'Z':
    3340           0 :         if (last - t >= 3) {
    3341           0 :           switch (t[2]) {
    3342           0 :           case 'T':
    3343           0 :             first = parse_sizeof_param_pack_expr(first, last, db);
    3344           0 :             break;
    3345           0 :           case 'f':
    3346           0 :             first = parse_sizeof_function_param_pack_expr(first, last, db);
    3347           0 :             break;
    3348             :           }
    3349             :         }
    3350             :         break;
    3351             :       }
    3352             :       break;
    3353           0 :     case 't':
    3354           0 :       switch (t[1]) {
    3355           0 :       case 'e':
    3356             :       case 'i':
    3357           0 :         first = parse_typeid_expr(first, last, db);
    3358           0 :         break;
    3359           0 :       case 'r':
    3360           0 :         db.names.push_back("throw");
    3361           0 :         first += 2;
    3362           0 :         break;
    3363           0 :       case 'w':
    3364           0 :         first = parse_throw_expr(first, last, db);
    3365           0 :         break;
    3366             :       }
    3367             :       break;
    3368          31 :     case '1':
    3369             :     case '2':
    3370             :     case '3':
    3371             :     case '4':
    3372             :     case '5':
    3373             :     case '6':
    3374             :     case '7':
    3375             :     case '8':
    3376             :     case '9':
    3377          31 :       return parse_unresolved_name(first, last, db);
    3378             :     }
    3379             :   }
    3380             :   return first;
    3381             : }
    3382             : 
    3383             : // <template-arg> ::= <type>                                             # type
    3384             : // or template
    3385             : //                ::= X <expression> E                                   #
    3386             : //                expression
    3387             : //                ::= <expr-primary>                                     #
    3388             : //                simple expressions
    3389             : //                ::= J <template-arg>* E                                #
    3390             : //                argument pack
    3391             : //                ::= LZ <encoding> E                                    #
    3392             : //                extension
    3393             : 
    3394             : template <class C>
    3395       15609 : static const char *parse_template_arg(const char *first, const char *last,
    3396             :                                       C &db) {
    3397       15609 :   if (first != last) {
    3398             :     const char *t;
    3399       15609 :     switch (*first) {
    3400         381 :     case 'X':
    3401         381 :       t = parse_expression(first + 1, last, db);
    3402         381 :       if (t != first + 1) {
    3403         381 :         if (t != last && *t == 'E')
    3404         381 :           first = t + 1;
    3405             :       }
    3406             :       break;
    3407         839 :     case 'J':
    3408         839 :       t = first + 1;
    3409         839 :       if (t == last)
    3410             :         return first;
    3411        2119 :       while (*t != 'E') {
    3412        1280 :         const char *t1 = parse_template_arg(t, last, db);
    3413        1280 :         if (t1 == t)
    3414             :           return first;
    3415             :         t = t1;
    3416             :       }
    3417         839 :       first = t + 1;
    3418         839 :       break;
    3419        1405 :     case 'L':
    3420             :       // <expr-primary> or LZ <encoding> E
    3421        1405 :       if (first + 1 != last && first[1] == 'Z') {
    3422           0 :         t = parse_encoding(first + 2, last, db);
    3423           0 :         if (t != first + 2 && t != last && *t == 'E')
    3424           0 :           first = t + 1;
    3425             :       } else
    3426        1405 :         first = parse_expr_primary(first, last, db);
    3427             :       break;
    3428       12984 :     default:
    3429             :       // <type>
    3430       12984 :       first = parse_type(first, last, db);
    3431       12984 :       break;
    3432             :     }
    3433             :   }
    3434             :   return first;
    3435             : }
    3436             : 
    3437             : // <template-args> ::= I <template-arg>* E
    3438             : //     extension, the abi says <template-arg>+
    3439             : 
    3440             : template <class C>
    3441       12382 : static const char *parse_template_args(const char *first, const char *last,
    3442             :                                        C &db) {
    3443       12382 :   if (last - first >= 2 && *first == 'I') {
    3444        8702 :     if (db.tag_templates)
    3445       13950 :       db.template_param.back().clear();
    3446        8702 :     const char *t = first + 1;
    3447       25926 :     std::string args("<");
    3448       22851 :     while (*t != 'E') {
    3449       14329 :       if (db.tag_templates)
    3450       11904 :         db.template_param.emplace_back();
    3451       28658 :       size_t k0 = db.names.size();
    3452       14329 :       const char *t1 = parse_template_arg(t, last, db);
    3453       28658 :       size_t k1 = db.names.size();
    3454       14329 :       if (db.tag_templates)
    3455       11904 :         db.template_param.pop_back();
    3456       14329 :       if (t1 == t || t1 == last)
    3457         360 :         return first;
    3458       14149 :       if (db.tag_templates) {
    3459       23808 :         db.template_param.back().emplace_back();
    3460       24038 :         for (size_t k = k0; k < k1; ++k)
    3461       48536 :           db.template_param.back().back().push_back(db.names[k]);
    3462             :       }
    3463       43361 :       for (size_t k = k0; k < k1; ++k) {
    3464       14606 :         if (args.size() > 1)
    3465             :           args += ", ";
    3466       73030 :         args += db.names[k].move_full();
    3467             :       }
    3468       43361 :       for (; k1 > k0; --k1)
    3469       29212 :         if (!db.names.empty())
    3470       14606 :           db.names.pop_back();
    3471             :       t = t1;
    3472             :     }
    3473        8522 :     first = t + 1;
    3474        8522 :     if (args.back() != '>')
    3475             :       args += ">";
    3476             :     else
    3477             :       args += " >";
    3478       42610 :     db.names.push_back(std::move(args));
    3479             :   }
    3480             :   return first;
    3481             : }
    3482             : 
    3483             : // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix>
    3484             : // <unqualified-name> E
    3485             : //               ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
    3486             : //               <template-args> E
    3487             : //
    3488             : // <prefix> ::= <prefix> <unqualified-name>
    3489             : //          ::= <template-prefix> <template-args>
    3490             : //          ::= <template-param>
    3491             : //          ::= <decltype>
    3492             : //          ::= # empty
    3493             : //          ::= <substitution>
    3494             : //          ::= <prefix> <data-member-prefix>
    3495             : //  extension ::= L
    3496             : //
    3497             : // <template-prefix> ::= <prefix> <template unqualified-name>
    3498             : //                   ::= <template-param>
    3499             : //                   ::= <substitution>
    3500             : 
    3501             : template <class C>
    3502        4376 : static const char *parse_nested_name(const char *first, const char *last, C &db,
    3503             :                                      bool *ends_with_template_args) {
    3504        4376 :   if (first != last && *first == 'N') {
    3505             :     unsigned cv;
    3506        8752 :     const char *t0 = parse_cv_qualifiers(first + 1, last, cv);
    3507        4376 :     if (t0 == last)
    3508             :       return first;
    3509        4376 :     db.ref = 0;
    3510        4376 :     if (*t0 == 'R') {
    3511           0 :       db.ref = 1;
    3512           0 :       ++t0;
    3513        4376 :     } else if (*t0 == 'O') {
    3514           0 :       db.ref = 2;
    3515           0 :       ++t0;
    3516             :     }
    3517        4376 :     db.names.emplace_back();
    3518        4376 :     if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't') {
    3519        3362 :       t0 += 2;
    3520        6724 :       db.names.back().first = "std";
    3521             :     }
    3522        4376 :     if (t0 == last) {
    3523           0 :       db.names.pop_back();
    3524           0 :       return first;
    3525             :     }
    3526             :     bool pop_subs = false;
    3527             :     bool component_ends_with_template_args = false;
    3528       16886 :     while (*t0 != 'E') {
    3529       12690 :       component_ends_with_template_args = false;
    3530             :       const char *t1;
    3531       12690 :       switch (*t0) {
    3532         741 :       case 'S':
    3533         741 :         if (t0 + 1 != last && t0[1] == 't')
    3534             :           goto do_parse_unqualified_name;
    3535         741 :         t1 = parse_substitution(t0, last, db);
    3536         741 :         if (t1 != t0 && t1 != last) {
    3537        2964 :           auto name = db.names.back().move_full();
    3538         741 :           db.names.pop_back();
    3539        1482 :           if (db.names.empty())
    3540           0 :             return first;
    3541        2223 :           if (!db.names.back().first.empty()) {
    3542           0 :             db.names.back().first += "::" + name;
    3543           0 :             db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3544             :           } else
    3545        1482 :             db.names.back().first = name;
    3546         741 :           pop_subs = true;
    3547         741 :           t0 = t1;
    3548             :         } else
    3549             :           return first;
    3550             :         break;
    3551           0 :       case 'T':
    3552           0 :         t1 = parse_template_param(t0, last, db);
    3553           0 :         if (t1 != t0 && t1 != last) {
    3554           0 :           auto name = db.names.back().move_full();
    3555           0 :           db.names.pop_back();
    3556           0 :           if (db.names.empty())
    3557           0 :             return first;
    3558           0 :           if (!db.names.back().first.empty())
    3559           0 :             db.names.back().first += "::" + name;
    3560             :           else
    3561           0 :             db.names.back().first = name;
    3562           0 :           db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3563           0 :           pop_subs = true;
    3564           0 :           t0 = t1;
    3565             :         } else
    3566             :           return first;
    3567             :         break;
    3568         611 :       case 'D':
    3569         611 :         if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T')
    3570             :           goto do_parse_unqualified_name;
    3571           0 :         t1 = parse_decltype(t0, last, db);
    3572           0 :         if (t1 != t0 && t1 != last) {
    3573           0 :           auto name = db.names.back().move_full();
    3574           0 :           db.names.pop_back();
    3575           0 :           if (db.names.empty())
    3576           0 :             return first;
    3577           0 :           if (!db.names.back().first.empty())
    3578           0 :             db.names.back().first += "::" + name;
    3579             :           else
    3580           0 :             db.names.back().first = name;
    3581           0 :           db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3582           0 :           pop_subs = true;
    3583           0 :           t0 = t1;
    3584             :         } else
    3585             :           return first;
    3586             :         break;
    3587        3364 :       case 'I':
    3588        3364 :         t1 = parse_template_args(t0, last, db);
    3589        3364 :         if (t1 != t0 && t1 != last) {
    3590       12736 :           auto name = db.names.back().move_full();
    3591        3184 :           db.names.pop_back();
    3592        6368 :           if (db.names.empty())
    3593           0 :             return first;
    3594        9552 :           db.names.back().first += name;
    3595       12736 :           db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3596        3184 :           t0 = t1;
    3597        3184 :           component_ends_with_template_args = true;
    3598             :         } else
    3599             :           return first;
    3600             :         break;
    3601           0 :       case 'L':
    3602           0 :         if (++t0 == last)
    3603             :           return first;
    3604             :         break;
    3605             :       default:
    3606         611 :       do_parse_unqualified_name:
    3607        8585 :         t1 = parse_unqualified_name(t0, last, db);
    3608        8585 :         if (t1 != t0 && t1 != last) {
    3609       34340 :           auto name = db.names.back().move_full();
    3610        8585 :           db.names.pop_back();
    3611       17170 :           if (db.names.empty())
    3612           0 :             return first;
    3613       25755 :           if (!db.names.back().first.empty())
    3614       33248 :             db.names.back().first += "::" + name;
    3615             :           else
    3616         546 :             db.names.back().first = name;
    3617       34340 :           db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3618        8585 :           pop_subs = true;
    3619        8585 :           t0 = t1;
    3620             :         } else
    3621             :           return first;
    3622             :       }
    3623             :     }
    3624        4196 :     first = t0 + 1;
    3625        4196 :     db.cv = cv;
    3626        8392 :     if (pop_subs && !db.subs.empty())
    3627        4196 :       db.subs.pop_back();
    3628        4196 :     if (ends_with_template_args)
    3629        2491 :       *ends_with_template_args = component_ends_with_template_args;
    3630             :   }
    3631             :   return first;
    3632             : }
    3633             : 
    3634             : // <discriminator> := _ <non-negative number>      # when number < 10
    3635             : //                 := __ <non-negative number> _   # when number >= 10
    3636             : //  extension      := decimal-digit+               # at the end of string
    3637             : 
    3638           0 : static const char *parse_discriminator(const char *first, const char *last) {
    3639             :   // parse but ignore discriminator
    3640           0 :   if (first != last) {
    3641           0 :     if (*first == '_') {
    3642           0 :       const char *t1 = first + 1;
    3643           0 :       if (t1 != last) {
    3644           0 :         if (std::isdigit(*t1))
    3645           0 :           first = t1 + 1;
    3646           0 :         else if (*t1 == '_') {
    3647           0 :           for (++t1; t1 != last && std::isdigit(*t1); ++t1)
    3648             :             ;
    3649           0 :           if (t1 != last && *t1 == '_')
    3650           0 :             first = t1 + 1;
    3651             :         }
    3652             :       }
    3653           0 :     } else if (std::isdigit(*first)) {
    3654           0 :       const char *t1 = first + 1;
    3655           0 :       for (; t1 != last && std::isdigit(*t1); ++t1)
    3656             :         ;
    3657           0 :       if (t1 == last)
    3658           0 :         first = last;
    3659             :     }
    3660             :   }
    3661           0 :   return first;
    3662             : }
    3663             : 
    3664             : // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
    3665             : //              := Z <function encoding> E s [<discriminator>]
    3666             : //              := Z <function encoding> Ed [ <parameter number> ] _ <entity
    3667             : //              name>
    3668             : 
    3669             : template <class C>
    3670           0 : static const char *parse_local_name(const char *first, const char *last, C &db,
    3671             :                                     bool *ends_with_template_args) {
    3672           0 :   if (first != last && *first == 'Z') {
    3673           0 :     const char *t = parse_encoding(first + 1, last, db);
    3674           0 :     if (t != first + 1 && t != last && *t == 'E' && ++t != last) {
    3675           0 :       switch (*t) {
    3676           0 :       case 's':
    3677           0 :         first = parse_discriminator(t + 1, last);
    3678           0 :         if (db.names.empty())
    3679             :           return first;
    3680           0 :         db.names.back().first.append("::string literal");
    3681           0 :         break;
    3682           0 :       case 'd':
    3683           0 :         if (++t != last) {
    3684           0 :           const char *t1 = parse_number(t, last);
    3685           0 :           if (t1 != last && *t1 == '_') {
    3686           0 :             t = t1 + 1;
    3687           0 :             t1 = parse_name(t, last, db, ends_with_template_args);
    3688           0 :             if (t1 != t) {
    3689           0 :               if (db.names.size() < 2)
    3690           0 :                 return first;
    3691           0 :               auto name = db.names.back().move_full();
    3692           0 :               db.names.pop_back();
    3693           0 :               if (db.names.empty())
    3694           0 :                 return first;
    3695           0 :               db.names.back().first.append("::");
    3696           0 :               db.names.back().first.append(name);
    3697           0 :               first = t1;
    3698           0 :             } else if (!db.names.empty())
    3699           0 :               db.names.pop_back();
    3700             :           }
    3701             :         }
    3702             :         break;
    3703           0 :       default: {
    3704           0 :         const char *t1 = parse_name(t, last, db, ends_with_template_args);
    3705           0 :         if (t1 != t) {
    3706             :           // parse but ignore discriminator
    3707           0 :           first = parse_discriminator(t1, last);
    3708           0 :           if (db.names.size() < 2)
    3709           0 :             return first;
    3710           0 :           auto name = db.names.back().move_full();
    3711           0 :           db.names.pop_back();
    3712           0 :           if (db.names.empty())
    3713           0 :             return first;
    3714           0 :           db.names.back().first.append("::");
    3715           0 :           db.names.back().first.append(name);
    3716           0 :         } else if (!db.names.empty())
    3717           0 :           db.names.pop_back();
    3718             :       } break;
    3719             :       }
    3720             :     }
    3721             :   }
    3722             :   return first;
    3723             : }
    3724             : 
    3725             : // <name> ::= <nested-name> // N
    3726             : //        ::= <local-name> # See Scope Encoding below  // Z
    3727             : //        ::= <unscoped-template-name> <template-args>
    3728             : //        ::= <unscoped-name>
    3729             : 
    3730             : // <unscoped-template-name> ::= <unscoped-name>
    3731             : //                          ::= <substitution>
    3732             : 
    3733             : template <class C>
    3734       10146 : static const char *parse_name(const char *first, const char *last, C &db,
    3735             :                               bool *ends_with_template_args) {
    3736       10146 :   if (last - first >= 2) {
    3737       10146 :     const char *t0 = first;
    3738             :     // extension: ignore L here
    3739       10146 :     if (*t0 == 'L')
    3740           0 :       ++t0;
    3741       10146 :     switch (*t0) {
    3742        4376 :     case 'N': {
    3743        4376 :       const char *t1 = parse_nested_name(t0, last, db, ends_with_template_args);
    3744        4376 :       if (t1 != t0)
    3745        4196 :         first = t1;
    3746             :       break;
    3747             :     }
    3748           0 :     case 'Z': {
    3749           0 :       const char *t1 = parse_local_name(t0, last, db, ends_with_template_args);
    3750           0 :       if (t1 != t0)
    3751           0 :         first = t1;
    3752             :       break;
    3753             :     }
    3754        5770 :     default: {
    3755        5770 :       const char *t1 = parse_unscoped_name(t0, last, db);
    3756        5770 :       if (t1 != t0) {
    3757        9230 :         if (t1 != last &&
    3758        4602 :             *t1 == 'I') // <unscoped-template-name> <template-args>
    3759             :         {
    3760        6874 :           if (db.names.empty())
    3761             :             return first;
    3762       13748 :           db.subs.push_back(typename C::sub_type(1, db.names.back()));
    3763        3437 :           t0 = t1;
    3764        3437 :           t1 = parse_template_args(t0, last, db);
    3765        3437 :           if (t1 != t0) {
    3766        6874 :             if (db.names.size() < 2)
    3767           0 :               return first;
    3768       13748 :             auto tmp = db.names.back().move_full();
    3769        3437 :             db.names.pop_back();
    3770        6874 :             if (db.names.empty())
    3771           0 :               return first;
    3772       10311 :             db.names.back().first += tmp;
    3773        3437 :             first = t1;
    3774        3437 :             if (ends_with_template_args)
    3775         341 :               *ends_with_template_args = true;
    3776             :           }
    3777             :         } else // <unscoped-name>
    3778             :           first = t1;
    3779             :       } else { // try <substitution> <template-args>
    3780        1142 :         t1 = parse_substitution(t0, last, db);
    3781        1142 :         if (t1 != t0 && t1 != last && *t1 == 'I') {
    3782           0 :           t0 = t1;
    3783           0 :           t1 = parse_template_args(t0, last, db);
    3784           0 :           if (t1 != t0) {
    3785           0 :             if (db.names.size() < 2)
    3786           0 :               return first;
    3787           0 :             auto tmp = db.names.back().move_full();
    3788           0 :             db.names.pop_back();
    3789           0 :             if (db.names.empty())
    3790           0 :               return first;
    3791           0 :             db.names.back().first += tmp;
    3792           0 :             first = t1;
    3793           0 :             if (ends_with_template_args)
    3794           0 :               *ends_with_template_args = true;
    3795             :           }
    3796             :         }
    3797             :       }
    3798             :       break;
    3799             :     }
    3800             :     }
    3801             :   }
    3802             :   return first;
    3803             : }
    3804             : 
    3805             : // <call-offset> ::= h <nv-offset> _
    3806             : //               ::= v <v-offset> _
    3807             : //
    3808             : // <nv-offset> ::= <offset number>
    3809             : //               # non-virtual base override
    3810             : //
    3811             : // <v-offset>  ::= <offset number> _ <virtual offset number>
    3812             : //               # virtual base override, with vcall offset
    3813             : 
    3814           0 : static const char *parse_call_offset(const char *first, const char *last) {
    3815           0 :   if (first != last) {
    3816           0 :     switch (*first) {
    3817           0 :     case 'h': {
    3818           0 :       const char *t = parse_number(first + 1, last);
    3819           0 :       if (t != first + 1 && t != last && *t == '_')
    3820           0 :         first = t + 1;
    3821             :     } break;
    3822           0 :     case 'v': {
    3823           0 :       const char *t = parse_number(first + 1, last);
    3824           0 :       if (t != first + 1 && t != last && *t == '_') {
    3825           0 :         const char *t2 = parse_number(++t, last);
    3826           0 :         if (t2 != t && t2 != last && *t2 == '_')
    3827           0 :           first = t2 + 1;
    3828             :       }
    3829             :     } break;
    3830             :     }
    3831             :   }
    3832           0 :   return first;
    3833             : }
    3834             : 
    3835             : // <special-name> ::= TV <type>    # virtual table
    3836             : //                ::= TT <type>    # VTT structure (construction vtable index)
    3837             : //                ::= TI <type>    # typeinfo structure
    3838             : //                ::= TS <type>    # typeinfo name (null-terminated byte string)
    3839             : //                ::= Tc <call-offset> <call-offset> <base encoding>
    3840             : //                    # base is the nominal target function of thunk
    3841             : //                    # first call-offset is 'this' adjustment
    3842             : //                    # second call-offset is result adjustment
    3843             : //                ::= T <call-offset> <base encoding>
    3844             : //                    # base is the nominal target function of thunk
    3845             : //                ::= GV <object name> # Guard variable for one-time
    3846             : //                initialization
    3847             : //                                     # No <type>
    3848             : //                ::= TW <object name> # Thread-local wrapper
    3849             : //                ::= TH <object name> # Thread-local initialization
    3850             : //      extension ::= TC <first type> <number> _ <second type> # construction
    3851             : //      vtable for second-in-first
    3852             : //      extension ::= GR <object name> # reference temporary for object
    3853             : 
    3854             : template <class C>
    3855         370 : static const char *parse_special_name(const char *first, const char *last,
    3856             :                                       C &db) {
    3857         370 :   if (last - first > 2) {
    3858             :     const char *t;
    3859         370 :     switch (*first) {
    3860         370 :     case 'T':
    3861         370 :       switch (first[1]) {
    3862         253 :       case 'V':
    3863             :         // TV <type>    # virtual table
    3864         253 :         t = parse_type(first + 2, last, db);
    3865         253 :         if (t != first + 2) {
    3866         506 :           if (db.names.empty())
    3867             :             return first;
    3868         506 :           db.names.back().first.insert(0, "vtable for ");
    3869         253 :           first = t;
    3870             :         }
    3871             :         break;
    3872           0 :       case 'T':
    3873             :         // TT <type>    # VTT structure (construction vtable index)
    3874           0 :         t = parse_type(first + 2, last, db);
    3875           0 :         if (t != first + 2) {
    3876           0 :           if (db.names.empty())
    3877             :             return first;
    3878           0 :           db.names.back().first.insert(0, "VTT for ");
    3879           0 :           first = t;
    3880             :         }
    3881             :         break;
    3882         110 :       case 'I':
    3883             :         // TI <type>    # typeinfo structure
    3884         110 :         t = parse_type(first + 2, last, db);
    3885         110 :         if (t != first + 2) {
    3886         220 :           if (db.names.empty())
    3887             :             return first;
    3888         220 :           db.names.back().first.insert(0, "typeinfo for ");
    3889         110 :           first = t;
    3890             :         }
    3891             :         break;
    3892           7 :       case 'S':
    3893             :         // TS <type>    # typeinfo name (null-terminated byte string)
    3894           7 :         t = parse_type(first + 2, last, db);
    3895           7 :         if (t != first + 2) {
    3896          14 :           if (db.names.empty())
    3897             :             return first;
    3898          14 :           db.names.back().first.insert(0, "typeinfo name for ");
    3899           7 :           first = t;
    3900             :         }
    3901             :         break;
    3902           0 :       case 'c':
    3903             :         // Tc <call-offset> <call-offset> <base encoding>
    3904             :         {
    3905           0 :           const char *t0 = parse_call_offset(first + 2, last);
    3906           0 :           if (t0 == first + 2)
    3907             :             break;
    3908           0 :           const char *t1 = parse_call_offset(t0, last);
    3909           0 :           if (t1 == t0)
    3910             :             break;
    3911           0 :           t = parse_encoding(t1, last, db);
    3912           0 :           if (t != t1) {
    3913           0 :             if (db.names.empty())
    3914             :               return first;
    3915           0 :             db.names.back().first.insert(0, "covariant return thunk to ");
    3916           0 :             first = t;
    3917             :           }
    3918             :         }
    3919             :         break;
    3920           0 :       case 'C':
    3921             :         // extension ::= TC <first type> <number> _ <second type> # construction
    3922             :         // vtable for second-in-first
    3923           0 :         t = parse_type(first + 2, last, db);
    3924           0 :         if (t != first + 2) {
    3925           0 :           const char *t0 = parse_number(t, last);
    3926           0 :           if (t0 != t && t0 != last && *t0 == '_') {
    3927           0 :             const char *t1 = parse_type(++t0, last, db);
    3928           0 :             if (t1 != t0) {
    3929           0 :               if (db.names.size() < 2)
    3930           0 :                 return first;
    3931           0 :               auto left = db.names.back().move_full();
    3932           0 :               db.names.pop_back();
    3933           0 :               if (db.names.empty())
    3934           0 :                 return first;
    3935           0 :               db.names.back().first = "construction vtable for " +
    3936           0 :                                       std::move(left) + "-in-" +
    3937           0 :                                       db.names.back().move_full();
    3938           0 :               first = t1;
    3939             :             }
    3940             :           }
    3941             :         }
    3942             :         break;
    3943           0 :       case 'W':
    3944             :         // TW <object name> # Thread-local wrapper
    3945           0 :         t = parse_name(first + 2, last, db);
    3946           0 :         if (t != first + 2) {
    3947           0 :           if (db.names.empty())
    3948             :             return first;
    3949           0 :           db.names.back().first.insert(0, "thread-local wrapper routine for ");
    3950           0 :           first = t;
    3951             :         }
    3952             :         break;
    3953           0 :       case 'H':
    3954             :         // TH <object name> # Thread-local initialization
    3955           0 :         t = parse_name(first + 2, last, db);
    3956           0 :         if (t != first + 2) {
    3957           0 :           if (db.names.empty())
    3958             :             return first;
    3959           0 :           db.names.back().first.insert(
    3960             :               0, "thread-local initialization routine for ");
    3961           0 :           first = t;
    3962             :         }
    3963             :         break;
    3964           0 :       default:
    3965             :         // T <call-offset> <base encoding>
    3966             :         {
    3967           0 :           const char *t0 = parse_call_offset(first + 1, last);
    3968           0 :           if (t0 == first + 1)
    3969             :             break;
    3970           0 :           t = parse_encoding(t0, last, db);
    3971           0 :           if (t != t0) {
    3972           0 :             if (db.names.empty())
    3973             :               return first;
    3974           0 :             if (first[1] == 'v') {
    3975           0 :               db.names.back().first.insert(0, "virtual thunk to ");
    3976           0 :               first = t;
    3977             :             } else {
    3978           0 :               db.names.back().first.insert(0, "non-virtual thunk to ");
    3979           0 :               first = t;
    3980             :             }
    3981             :           }
    3982             :         }
    3983             :         break;
    3984             :       }
    3985             :       break;
    3986           0 :     case 'G':
    3987           0 :       switch (first[1]) {
    3988           0 :       case 'V':
    3989             :         // GV <object name> # Guard variable for one-time initialization
    3990           0 :         t = parse_name(first + 2, last, db);
    3991           0 :         if (t != first + 2) {
    3992           0 :           if (db.names.empty())
    3993             :             return first;
    3994           0 :           db.names.back().first.insert(0, "guard variable for ");
    3995           0 :           first = t;
    3996             :         }
    3997             :         break;
    3998           0 :       case 'R':
    3999             :         // extension ::= GR <object name> # reference temporary for object
    4000           0 :         t = parse_name(first + 2, last, db);
    4001           0 :         if (t != first + 2) {
    4002           0 :           if (db.names.empty())
    4003             :             return first;
    4004           0 :           db.names.back().first.insert(0, "reference temporary for ");
    4005           0 :           first = t;
    4006             :         }
    4007             :         break;
    4008             :       }
    4009             :       break;
    4010             :     }
    4011             :   }
    4012             :   return first;
    4013             : }
    4014             : 
    4015             : namespace {
    4016             : template <class T> class save_value {
    4017             :   T &restore_;
    4018             :   T original_value_;
    4019             : 
    4020             : public:
    4021       15980 :   save_value(T &restore) : restore_(restore), original_value_(restore) {}
    4022             : 
    4023       15440 :   ~save_value() { restore_ = std::move(original_value_); }
    4024             : 
    4025             :   save_value(const save_value &) = delete;
    4026             :   save_value &operator=(const save_value &) = delete;
    4027             : };
    4028             : }
    4029             : 
    4030             : // <encoding> ::= <function name> <bare-function-type>
    4031             : //            ::= <data name>
    4032             : //            ::= <special-name>
    4033             : 
    4034             : template <class C>
    4035        4089 : static const char *parse_encoding(const char *first, const char *last, C &db) {
    4036        4089 :   if (first != last) {
    4037       12087 :     save_value<decltype(db.encoding_depth)> su(db.encoding_depth);
    4038        4089 :     ++db.encoding_depth;
    4039       12087 :     save_value<decltype(db.tag_templates)> sb(db.tag_templates);
    4040        4089 :     if (db.encoding_depth > 1)
    4041           0 :       db.tag_templates = true;
    4042       12087 :     save_value<decltype(db.parsed_ctor_dtor_cv)> sp(db.parsed_ctor_dtor_cv);
    4043        4089 :     db.parsed_ctor_dtor_cv = false;
    4044        4089 :     switch (*first) {
    4045         370 :     case 'G':
    4046             :     case 'T':
    4047         370 :       first = parse_special_name(first, last, db);
    4048         370 :       break;
    4049        3719 :     default: {
    4050        3719 :       bool ends_with_template_args = false;
    4051        3719 :       const char *t = parse_name(first, last, db, &ends_with_template_args);
    4052        3719 :       unsigned cv = db.cv;
    4053        3719 :       unsigned ref = db.ref;
    4054        3719 :       if (t != first) {
    4055        3719 :         if (t != last && *t != 'E' && *t != '.') {
    4056       10959 :           save_value<bool> sb2(db.tag_templates);
    4057        3713 :           db.tag_templates = false;
    4058             :           const char *t2;
    4059        7246 :           std::string ret2;
    4060        7426 :           if (db.names.empty())
    4061         180 :             return first;
    4062        7426 :           const std::string &nm = db.names.back().first;
    4063        3713 :           if (nm.empty())
    4064             :             return first;
    4065        3713 :           if (!db.parsed_ctor_dtor_cv && ends_with_template_args) {
    4066         616 :             t2 = parse_type(t, last, db);
    4067         616 :             if (t2 == t)
    4068         180 :               return first;
    4069         872 :             if (db.names.size() < 2)
    4070             :               return first;
    4071        1744 :             auto ret1 = std::move(db.names.back().first);
    4072         872 :             ret2 = std::move(db.names.back().second);
    4073         436 :             if (ret2.empty())
    4074             :               ret1 += ' ';
    4075         436 :             db.names.pop_back();
    4076         872 :             if (db.names.empty())
    4077           0 :               return first;
    4078             : 
    4079        1308 :             db.names.back().first.insert(0, ret1);
    4080         436 :             t = t2;
    4081             :           }
    4082       10599 :           db.names.back().first += '(';
    4083        3533 :           if (t != last && *t == 'v') {
    4084        1530 :             ++t;
    4085             :           } else {
    4086             :             bool first_arg = true;
    4087             :             while (true) {
    4088        9152 :               size_t k0 = db.names.size();
    4089        4576 :               t2 = parse_type(t, last, db);
    4090        9152 :               size_t k1 = db.names.size();
    4091        4576 :               if (t2 == t)
    4092             :                 break;
    4093        2573 :               if (k1 > k0) {
    4094        5136 :                 std::string tmp;
    4095        5184 :                 for (size_t k = k0; k < k1; ++k) {
    4096        2616 :                   if (!tmp.empty())
    4097             :                     tmp += ", ";
    4098       13080 :                   tmp += db.names[k].move_full();
    4099             :                 }
    4100        7800 :                 for (size_t k = k0; k < k1; ++k) {
    4101        5232 :                   if (db.names.empty())
    4102           0 :                     return first;
    4103        2616 :                   db.names.pop_back();
    4104             :                 }
    4105        2568 :                 if (!tmp.empty()) {
    4106        5136 :                   if (db.names.empty())
    4107             :                     return first;
    4108        2568 :                   if (!first_arg)
    4109        1238 :                     db.names.back().first += ", ";
    4110             :                   else
    4111             :                     first_arg = false;
    4112        5136 :                   db.names.back().first += tmp;
    4113             :                 }
    4114             :               }
    4115             :               t = t2;
    4116             :             }
    4117             :           }
    4118        7066 :           if (db.names.empty())
    4119             :             return first;
    4120       10599 :           db.names.back().first += ')';
    4121        3533 :           if (cv & CV_const)
    4122         214 :             db.names.back().first.append(" const");
    4123        3533 :           if (cv & CV_volatile)
    4124           0 :             db.names.back().first.append(" volatile");
    4125        3533 :           if (cv & CV_restrict)
    4126           0 :             db.names.back().first.append(" restrict");
    4127        3533 :           if (ref == 1)
    4128           0 :             db.names.back().first.append(" &");
    4129        3533 :           else if (ref == 2)
    4130           0 :             db.names.back().first.append(" &&");
    4131       10599 :           db.names.back().first += ret2;
    4132        3533 :           first = t;
    4133             :         } else
    4134             :           first = t;
    4135             :       }
    4136        3539 :       break;
    4137             :     }
    4138             :     }
    4139             :   }
    4140             :   return first;
    4141             : }
    4142             : 
    4143             : // _block_invoke
    4144             : // _block_invoke<decimal-digit>+
    4145             : // _block_invoke_<decimal-digit>+
    4146             : 
    4147             : template <class C>
    4148           1 : static const char *parse_block_invoke(const char *first, const char *last,
    4149             :                                       C &db) {
    4150           1 :   if (last - first >= 13) {
    4151           1 :     const char test[] = "_block_invoke";
    4152           1 :     const char *t = first;
    4153          14 :     for (int i = 0; i < 13; ++i, ++t) {
    4154          13 :       if (*t != test[i])
    4155           0 :         return first;
    4156             :     }
    4157           1 :     if (t != last) {
    4158           0 :       if (*t == '_') {
    4159             :         // must have at least 1 decimal digit
    4160           0 :         if (++t == last || !std::isdigit(*t))
    4161             :           return first;
    4162           0 :         ++t;
    4163             :       }
    4164             :       // parse zero or more digits
    4165           0 :       while (t != last && isdigit(*t))
    4166           0 :         ++t;
    4167             :     }
    4168           2 :     if (db.names.empty())
    4169             :       return first;
    4170           2 :     db.names.back().first.insert(0, "invocation function for block in ");
    4171           1 :     first = t;
    4172             :   }
    4173             :   return first;
    4174             : }
    4175             : 
    4176             : // extension
    4177             : // <dot-suffix> := .<anything and everything>
    4178             : 
    4179             : template <class C>
    4180           0 : static const char *parse_dot_suffix(const char *first, const char *last,
    4181             :                                     C &db) {
    4182           0 :   if (first != last && *first == '.') {
    4183           0 :     if (db.names.empty())
    4184             :       return first;
    4185           0 :     db.names.back().first += " (" + std::string(first, last) + ")";
    4186           0 :     first = last;
    4187             :   }
    4188             :   return first;
    4189             : }
    4190             : 
    4191             : // <block-involcaton-function> ___Z<encoding>_block_invoke
    4192             : // <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+
    4193             : // <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+
    4194             : // <mangled-name> ::= _Z<encoding>
    4195             : //                ::= <type>
    4196             : 
    4197             : template <class C>
    4198        4106 : static void demangle(const char *first, const char *last, C &db, int &status) {
    4199        4106 :   if (first >= last) {
    4200           0 :     status = invalid_mangled_name;
    4201           0 :     return;
    4202             :   }
    4203        4106 :   if (*first == '_') {
    4204        4089 :     if (last - first >= 4) {
    4205        4089 :       if (first[1] == 'Z') {
    4206        4088 :         const char *t = parse_encoding(first + 2, last, db);
    4207        4088 :         if (t != first + 2 && t != last && *t == '.')
    4208           0 :           t = parse_dot_suffix(t, last, db);
    4209        4088 :         if (t != last)
    4210        2887 :           status = invalid_mangled_name;
    4211           1 :       } else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z') {
    4212           1 :         const char *t = parse_encoding(first + 4, last, db);
    4213           1 :         if (t != first + 4 && t != last) {
    4214           1 :           const char *t1 = parse_block_invoke(t, last, db);
    4215           1 :           if (t1 != last)
    4216           0 :             status = invalid_mangled_name;
    4217             :         } else
    4218           0 :           status = invalid_mangled_name;
    4219             :       } else
    4220           0 :         status = invalid_mangled_name;
    4221             :     } else
    4222           0 :       status = invalid_mangled_name;
    4223             :   } else {
    4224          17 :     const char *t = parse_type(first, last, db);
    4225          17 :     if (t != last)
    4226          15 :       status = invalid_mangled_name;
    4227             :   }
    4228        5310 :   if (status == success && db.names.empty())
    4229           0 :     status = invalid_mangled_name;
    4230             : }
    4231             : 
    4232             : namespace {
    4233      622063 : template <class StrT> struct string_pair {
    4234             :   StrT first;
    4235             :   StrT second;
    4236             : 
    4237       16713 :   string_pair() = default;
    4238       65307 :   string_pair(StrT f) : first(std::move(f)) {}
    4239             :   string_pair(StrT f, StrT s) : first(std::move(f)), second(std::move(s)) {}
    4240       44365 :   template <size_t N> string_pair(const char (&s)[N]) : first(s, N - 1) {}
    4241             : 
    4242        1204 :   size_t size() const { return first.size() + second.size(); }
    4243           0 :   bool empty() const { return first.empty() && second.empty(); }
    4244             :   StrT full() const { return first + second; }
    4245       35853 :   StrT move_full() { return std::move(first) + std::move(second); }
    4246             : };
    4247             : 
    4248        4106 : struct Db {
    4249             :   typedef std::vector<string_pair<std::string>> sub_type;
    4250             :   typedef std::vector<sub_type> template_param_type;
    4251             :   sub_type names;
    4252             :   template_param_type subs;
    4253             :   std::vector<template_param_type> template_param;
    4254             :   unsigned cv = 0;
    4255             :   unsigned ref = 0;
    4256             :   unsigned encoding_depth = 0;
    4257             :   bool parsed_ctor_dtor_cv = false;
    4258             :   bool tag_templates = true;
    4259             :   bool fix_forward_references = false;
    4260             :   bool try_to_parse_template_args = true;
    4261             : 
    4262       24636 :   Db() : subs(0, names), template_param(0, subs) {}
    4263             : };
    4264             : }
    4265             : 
    4266        4106 : char *llvm::itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
    4267             :                             int *status) {
    4268        4106 :   if (mangled_name == nullptr || (buf != nullptr && n == nullptr)) {
    4269           0 :     if (status)
    4270           0 :       *status = invalid_args;
    4271             :     return nullptr;
    4272             :   }
    4273        4106 :   size_t internal_size = buf != nullptr ? *n : 0;
    4274        8212 :   Db db;
    4275        4106 :   db.template_param.emplace_back();
    4276        4106 :   int internal_status = success;
    4277        4106 :   size_t len = std::strlen(mangled_name);
    4278        4106 :   demangle(mangled_name, mangled_name + len, db, internal_status);
    4279        5310 :   if (internal_status == success && db.fix_forward_references &&
    4280        4106 :       !db.template_param.empty() && !db.template_param.front().empty()) {
    4281           0 :     db.fix_forward_references = false;
    4282           0 :     db.tag_templates = false;
    4283           0 :     db.names.clear();
    4284           0 :     db.subs.clear();
    4285           0 :     demangle(mangled_name, mangled_name + len, db, internal_status);
    4286           0 :     if (db.fix_forward_references)
    4287           0 :       internal_status = invalid_mangled_name;
    4288             :   }
    4289        4106 :   if (internal_status == success) {
    4290        2408 :     size_t sz = db.names.back().size() + 1;
    4291        1204 :     if (sz > internal_size) {
    4292        1204 :       char *newbuf = static_cast<char *>(std::realloc(buf, sz));
    4293        1204 :       if (newbuf == nullptr) {
    4294           0 :         internal_status = memory_alloc_failure;
    4295           0 :         buf = nullptr;
    4296             :       } else {
    4297        1204 :         buf = newbuf;
    4298        1204 :         if (n != nullptr)
    4299           0 :           *n = sz;
    4300             :       }
    4301             :     }
    4302        1204 :     if (buf != nullptr) {
    4303        3612 :       db.names.back().first += db.names.back().second;
    4304        3612 :       std::memcpy(buf, db.names.back().first.data(), sz - 1);
    4305        1204 :       buf[sz - 1] = char(0);
    4306             :     }
    4307             :   } else
    4308             :     buf = nullptr;
    4309        4106 :   if (status)
    4310          34 :     *status = internal_status;
    4311             :   return buf;
    4312             : }

Generated by: LCOV version 1.13