<div dir="ltr">Can you take a look at this build failure?  <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__lab.llvm.org-3A8011_builders_lldb-2Dx86-2Dwindows-2Dmsvc_builds_6224_steps_build_logs_stdio&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=_tFxCmw_SSoNtO67S88sN3WMap11Wpnmh-rqe8uL6Fw&e=">http://lab.llvm.org:8011/builders/lldb-x86-windows-msvc/builds/6224/steps/build/logs/stdio</a><br></div><br><div class="gmail_quote"><div dir="ltr">On Thu, May 28, 2015 at 12:33 PM Chaoren Lin <<a href="mailto:chaorenl@google.com">chaorenl@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chaoren<br>
Date: Thu May 28 14:15:15 2015<br>
New Revision: 238459<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D238459-26view-3Drev&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=bg7rKRx-NFUjaotSUda713X0gtnxvVHeZmJWqeshlYE&e=" target="_blank">http://llvm.org/viewvc/llvm-project?rev=238459&view=rev</a><br>
Log:<br>
Move inlined cxa_demangle.cpp to a separate file.<br>
<br>
Summary: In preparation for some changes to make this compatible with MSVC.<br>
<br>
Reviewers: emaste, zturner, clayborg<br>
<br>
Reviewed By: clayborg<br>
<br>
Subscribers: lldb-commits<br>
<br>
Differential Revision: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D9949&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=bRjE8o6hVgeECYjJCX5zMUEEG7Ao1j0hrvi0CFhaMHY&e=" target="_blank">http://reviews.llvm.org/D9949</a><br>
<br>
Added:<br>
    lldb/trunk/include/lldb/Core/CxaDemangle.h<br>
    lldb/trunk/include/lldb/Core/FastDemangle.h<br>
    lldb/trunk/source/Core/CxaDemangle.cpp<br>
      - copied, changed from r238454, lldb/trunk/source/Core/Mangled.cpp<br>
Modified:<br>
    lldb/trunk/source/Core/CMakeLists.txt<br>
    lldb/trunk/source/Core/Mangled.cpp<br>
<br>
Added: lldb/trunk/include/lldb/Core/CxaDemangle.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lldb_trunk_include_lldb_Core_CxaDemangle.h-3Frev-3D238459-26view-3Dauto&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=K-L-2-TiOWHdL_chBnaR6yjMxDpNAzMUzxt9Uju9vFQ&e=" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/CxaDemangle.h?rev=238459&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Core/CxaDemangle.h (added)<br>
+++ lldb/trunk/include/lldb/Core/CxaDemangle.h Thu May 28 14:15:15 2015<br>
@@ -0,0 +1,21 @@<br>
+//===-- CxaDemangle.h -------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef liblldb_CxaDemangle_h_<br>
+#define liblldb_CxaDemangle_h_<br>
+<br>
+namespace lldb_private<br>
+{<br>
+<br>
+    char*<br>
+    __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);<br>
+<br>
+}<br>
+<br>
+#endif<br>
<br>
Added: lldb/trunk/include/lldb/Core/FastDemangle.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lldb_trunk_include_lldb_Core_FastDemangle.h-3Frev-3D238459-26view-3Dauto&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=VeRS-xokbuLzoNxrbIaKkCQSkjcwWAyKVpI-NfZxWyQ&e=" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FastDemangle.h?rev=238459&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Core/FastDemangle.h (added)<br>
+++ lldb/trunk/include/lldb/Core/FastDemangle.h Thu May 28 14:15:15 2015<br>
@@ -0,0 +1,24 @@<br>
+//===-- FastDemangle.h ------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef liblldb_FastDemangle_h_<br>
+#define liblldb_FastDemangle_h_<br>
+<br>
+namespace lldb_private<br>
+{<br>
+<br>
+    char *<br>
+    FastDemangle(const char *mangled_name);<br>
+<br>
+    char *<br>
+    FastDemangle(const char *mangled_name, long mangled_name_length);<br>
+<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: lldb/trunk/source/Core/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lldb_trunk_source_Core_CMakeLists.txt-3Frev-3D238459-26r1-3D238458-26r2-3D238459-26view-3Ddiff&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=wmin5J01rdboQi7FBcyUA92L_kWsSDhIH--NG3-bs6M&e=" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/CMakeLists.txt?rev=238459&r1=238458&r2=238459&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Core/CMakeLists.txt (original)<br>
+++ lldb/trunk/source/Core/CMakeLists.txt Thu May 28 14:15:15 2015<br>
@@ -14,6 +14,7 @@ add_lldb_library(lldbCore<br>
   ConnectionMachPort.cpp<br>
   ConnectionSharedMemory.cpp<br>
   ConstString.cpp<br>
+  CxaDemangle.cpp<br>
   DataBufferHeap.cpp<br>
   DataBufferMemoryMap.cpp<br>
   DataEncoder.cpp<br>
<br>
Copied: lldb/trunk/source/Core/CxaDemangle.cpp (from r238454, lldb/trunk/source/Core/Mangled.cpp)<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lldb_trunk_source_Core_CxaDemangle.cpp-3Fp2-3Dlldb_trunk_source_Core_CxaDemangle.cpp-26p1-3Dlldb_trunk_source_Core_Mangled.cpp-26r1-3D238454-26r2-3D238459-26rev-3D238459-26view-3Ddiff&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=_zTteKvyj4iDd-L31EKI83KX2sac4VNPSueu5W6p2ow&e=" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/CxaDemangle.cpp?p2=lldb/trunk/source/Core/CxaDemangle.cpp&p1=lldb/trunk/source/Core/Mangled.cpp&r1=238454&r2=238459&rev=238459&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Core/Mangled.cpp (original)<br>
+++ lldb/trunk/source/Core/CxaDemangle.cpp Thu May 28 14:15:15 2015<br>
@@ -1,45 +1,12 @@<br>
-//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-<br>
-// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h<br>
-#include <cstddef><br>
-#if defined(_MSC_VER)<br>
-#include "lldb/Host/windows/windows.h"<br>
-#include <Dbghelp.h><br>
-#elif defined (__FreeBSD__)<br>
-#define LLDB_USE_BUILTIN_DEMANGLER<br>
-#else<br>
-#include <cxxabi.h><br>
-#endif<br>
-<br>
-#ifdef LLDB_USE_BUILTIN_DEMANGLER<br>
-<br>
-// Provide a fast-path demangler implemented in FastDemangle.cpp until it can<br>
-// replace the existing C++ demangler with a complete implementation<br>
-namespace lldb_private<br>
-{<br>
-    extern char * FastDemangle (const char * mangled_name,<br>
-                                long mangled_name_length);<br>
-}<br>
-<br>
 //----------------------------------------------------------------------<br>
 // Inlined copy of:<br>
 // <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_svn_llvm-2Dproject_libcxxabi_trunk_src_cxa-5Fdemangle.cpp&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=NMLNYG7odaaL2HGGoY4kXEIjc0rs3cdDXWfL7dvmwEc&e=" target="_blank">http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp</a><br>
-// revision 199944.<br>
+// revision 238263.<br>
 //<br>
 // Changes include:<br>
-// - remove the "__cxxabiv1" namespace<br>
-// - stripped GCC attributes()<br>
-// - removed extern "C" from the cxa_demangle function<br>
-// - Changed the scope of the unnamed namespace to include cxa_demangle<br>
-//   function.<br>
+// - Renamed the "__cxxabiv1" namespace to "lldb_private"<br>
+// - Stripped GCC attributes()<br>
+// - Removed extern "C" from the cxa_demangle function<br>
 // - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning<br>
 //----------------------------------------------------------------------<br>
<br>
@@ -65,6 +32,8 @@ namespace lldb_private<br>
 #include <cstring><br>
 #include <cctype><br>
<br>
+namespace lldb_private<br>
+{<br>
<br>
 namespace<br>
 {<br>
@@ -83,7 +52,8 @@ template <class C><br>
 template <class C><br>
     const char* parse_encoding(const char* first, const char* last, C& db);<br>
 template <class C><br>
-    const char* parse_name(const char* first, const char* last, C& db);<br>
+    const char* parse_name(const char* first, const char* last, C& db,<br>
+                           bool* ends_with_template_args = 0);<br>
 template <class C><br>
     const char* parse_expression(const char* first, const char* last, C& db);<br>
 template <class C><br>
@@ -99,51 +69,51 @@ template <class C><br>
 void<br>
 print_stack(const C& db)<br>
 {<br>
-    printf("---------\n");<br>
-    printf("names:\n");<br>
+    fprintf(stderr, "---------\n");<br>
+    fprintf(stderr, "names:\n");<br>
     for (auto& s : db.names)<br>
-        printf("{%s#%s}\n", s.first.c_str(), s.second.c_str());<br>
+        fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str());<br>
     int i = -1;<br>
-    printf("subs:\n");<br>
+    fprintf(stderr, "subs:\n");<br>
     for (auto& v : db.subs)<br>
     {<br>
         if (i >= 0)<br>
-            printf("S%i_ = {", i);<br>
+            fprintf(stderr, "S%i_ = {", i);<br>
         else<br>
-            printf("S_  = {");<br>
+            fprintf(stderr, "S_  = {");<br>
         for (auto& s : v)<br>
-            printf("{%s#%s}", s.first.c_str(), s.second.c_str());<br>
-        printf("}\n");<br>
+            fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());<br>
+        fprintf(stderr, "}\n");<br>
         ++i;<br>
     }<br>
-    printf("template_param:\n");<br>
+    fprintf(stderr, "template_param:\n");<br>
     for (auto& t : db.template_param)<br>
     {<br>
-        printf("--\n");<br>
+        fprintf(stderr, "--\n");<br>
         i = -1;<br>
         for (auto& v : t)<br>
         {<br>
             if (i >= 0)<br>
-                printf("T%i_ = {", i);<br>
+                fprintf(stderr, "T%i_ = {", i);<br>
             else<br>
-                printf("T_  = {");<br>
+                fprintf(stderr, "T_  = {");<br>
             for (auto& s : v)<br>
-                printf("{%s#%s}", s.first.c_str(), s.second.c_str());<br>
-            printf("}\n");<br>
+                fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str());<br>
+            fprintf(stderr, "}\n");<br>
             ++i;<br>
         }<br>
     }<br>
-    printf("---------\n\n");<br>
+    fprintf(stderr, "---------\n\n");<br>
 }<br>
<br>
 template <class C><br>
 void<br>
 print_state(const char* msg, const char* first, const char* last, const C& db)<br>
 {<br>
-    printf("%s: ", msg);<br>
+    fprintf(stderr, "%s: ", msg);<br>
     for (; first != last; ++first)<br>
-        printf("%c", *first);<br>
-    printf("\n");<br>
+        fprintf(stderr, "%c", *first);<br>
+    fprintf(stderr, "\n");<br>
     print_stack(db);<br>
 }<br>
<br>
@@ -200,7 +170,11 @@ constexpr const char* float_data<double><br>
 template <><br>
 struct float_data<long double><br>
 {<br>
+#if defined(__arm__)<br>
+    static const size_t mangled_size = 16;<br>
+#else<br>
     static const size_t mangled_size = 20;  // May need to be adjusted to 16 or 24 on other platforms<br>
+#endif<br>
     static const size_t max_demangled_size = 40;<br>
     static constexpr const char* spec = "%LaL";<br>
 };<br>
@@ -235,7 +209,7 @@ parse_floating_number(const char* first,<br>
         }<br>
         if (*t == 'E')<br>
         {<br>
-#if __LITTLE_ENDIAN__<br>
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__<br>
             std::reverse(buf, e);<br>
 #endif<br>
             char num[float_data<Float>::max_demangled_size] = {0};<br>
@@ -397,6 +371,7 @@ parse_substitution(const char* first, co<br>
 //                ::= Di   # char32_t<br>
 //                ::= Ds   # char16_t<br>
 //                ::= Da   # auto (in dependent new-expressions)<br>
+//                ::= Dc   # decltype(auto)<br>
 //                ::= Dn   # std::nullptr_t (i.e., decltype(nullptr))<br>
 //                ::= u <source-name>    # vendor extended type<br>
<br>
@@ -532,6 +507,10 @@ parse_builtin_type(const char* first, co<br>
                     db.names.push_back("auto");<br>
                     first += 2;<br>
                     break;<br>
+                case 'c':<br>
+                    db.names.push_back("decltype(auto)");<br>
+                    first += 2;<br>
+                    break;<br>
                 case 'n':<br>
                     db.names.push_back("std::nullptr_t");<br>
                     first += 2;<br>
@@ -1610,10 +1589,9 @@ parse_function_type(const char* first, c<br>
         const char* t = first+1;<br>
         if (t != last)<br>
         {<br>
-            bool externC = false;<br>
             if (*t == 'Y')<br>
             {<br>
-                externC = true;<br>
+                /* extern "C" */<br>
                 if (++t == last)<br>
                     return first;<br>
             }<br>
@@ -1707,7 +1685,7 @@ parse_pointer_to_member_type(const char*<br>
                 auto func = std::move(db.names.back());<br>
                 db.names.pop_back();<br>
                 auto class_type = std::move(db.names.back());<br>
-                if (func.second.front() == '(')<br>
+                if (!func.second.empty() && func.second.front() == '(')<br>
                 {<br>
                     db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*";<br>
                     db.names.back().second = ")" + std::move(func.second);<br>
@@ -2054,7 +2032,8 @@ parse_type(const char* first, const char<br>
                                     db.names[k].first += " (";<br>
                                     db.names[k].second.insert(0, ")");<br>
                                 }<br>
-                                else if (db.names[k].second.front() == '(')<br>
+                                else if (!db.names[k].second.empty() &&<br>
+                                          db.names[k].second.front() == '(')<br>
                                 {<br>
                                     db.names[k].first += "(";<br>
                                     db.names[k].second.insert(0, ")");<br>
@@ -2081,7 +2060,8 @@ parse_type(const char* first, const char<br>
                                     db.names[k].first += " (";<br>
                                     db.names[k].second.insert(0, ")");<br>
                                 }<br>
-                                else if (db.names[k].second.front() == '(')<br>
+                                else if (!db.names[k].second.empty() &&<br>
+                                          db.names[k].second.front() == '(')<br>
                                 {<br>
                                     db.names[k].first += "(";<br>
                                     db.names[k].second.insert(0, ")");<br>
@@ -2115,7 +2095,8 @@ parse_type(const char* first, const char<br>
                                     db.names[k].first += " (";<br>
                                     db.names[k].second.insert(0, ")");<br>
                                 }<br>
-                                else if (db.names[k].second.front() == '(')<br>
+                                else if (!db.names[k].second.empty() &&<br>
+                                          db.names[k].second.front() == '(')<br>
                                 {<br>
                                     db.names[k].first += "(";<br>
                                     db.names[k].second.insert(0, ")");<br>
@@ -3933,7 +3914,8 @@ parse_template_args(const char* first, c<br>
<br>
 template <class C><br>
 const char*<br>
-parse_nested_name(const char* first, const char* last, C& db)<br>
+parse_nested_name(const char* first, const char* last, C& db,<br>
+                  bool* ends_with_template_args)<br>
 {<br>
     if (first != last && *first == 'N')<br>
     {<br>
@@ -3941,15 +3923,15 @@ parse_nested_name(const char* first, con<br>
         const char* t0 = parse_cv_qualifiers(first+1, last, cv);<br>
         if (t0 == last)<br>
             return first;<br>
-        unsigned ref = 0;<br>
+        db.ref = 0;<br>
         if (*t0 == 'R')<br>
         {<br>
-            ref = 1;<br>
+            db.ref = 1;<br>
             ++t0;<br>
         }<br>
         else if (*t0 == 'O')<br>
         {<br>
-            ref = 2;<br>
+            db.ref = 2;<br>
             ++t0;<br>
         }<br>
         db.names.emplace_back();<br>
@@ -3964,8 +3946,10 @@ parse_nested_name(const char* first, con<br>
             return first;<br>
         }<br>
         bool pop_subs = false;<br>
+        bool component_ends_with_template_args = false;<br>
         while (*t0 != 'E')<br>
         {<br>
+            component_ends_with_template_args = false;<br>
             const char* t1;<br>
             switch (*t0)<br>
             {<br>
@@ -4035,6 +4019,7 @@ parse_nested_name(const char* first, con<br>
                     db.names.back().first += name;<br>
                     db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator()));<br>
                     t0 = t1;<br>
+                    component_ends_with_template_args = true;<br>
                 }<br>
                 else<br>
                     return first;<br>
@@ -4063,10 +4048,11 @@ parse_nested_name(const char* first, con<br>
             }<br>
         }<br>
         first = t0 + 1;<br>
-        db.ref = ref;<br>
         <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__db.cv&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=BrftCSn9PqBxw3tytbgnk-GR30HQG7KCY9tr81m6ySA&e=" target="_blank">db.cv</a> = cv;<br>
         if (pop_subs && !db.subs.empty())<br>
             db.subs.pop_back();<br>
+        if (ends_with_template_args)<br>
+            *ends_with_template_args = component_ends_with_template_args;<br>
     }<br>
     return first;<br>
 }<br>
@@ -4114,7 +4100,8 @@ parse_discriminator(const char* first, c<br>
<br>
 template <class C><br>
 const char*<br>
-parse_local_name(const char* first, const char* last, C& db)<br>
+parse_local_name(const char* first, const char* last, C& db,<br>
+                 bool* ends_with_template_args)<br>
 {<br>
     if (first != last && *first == 'Z')<br>
     {<br>
@@ -4136,7 +4123,8 @@ parse_local_name(const char* first, cons<br>
                     if (t1 != last && *t1 == '_')<br>
                     {<br>
                         t = t1 + 1;<br>
-                        t1 = parse_name(t, last, db);<br>
+                        t1 = parse_name(t, last, db,<br>
+                                        ends_with_template_args);<br>
                         if (t1 != t)<br>
                         {<br>
                             if (db.names.size() < 2)<br>
@@ -4154,7 +4142,8 @@ parse_local_name(const char* first, cons<br>
                 break;<br>
             default:<br>
                 {<br>
-                    const char* t1 = parse_name(t, last, db);<br>
+                    const char* t1 = parse_name(t, last, db,<br>
+                                                ends_with_template_args);<br>
                     if (t1 != t)<br>
                     {<br>
                         // parse but ignore discriminator<br>
@@ -4186,7 +4175,8 @@ parse_local_name(const char* first, cons<br>
<br>
 template <class C><br>
 const char*<br>
-parse_name(const char* first, const char* last, C& db)<br>
+parse_name(const char* first, const char* last, C& db,<br>
+           bool* ends_with_template_args)<br>
 {<br>
     if (last - first >= 2)<br>
     {<br>
@@ -4198,14 +4188,16 @@ parse_name(const char* first, const char<br>
         {<br>
         case 'N':<br>
           {<br>
-            const char* t1 = parse_nested_name(t0, last, db);<br>
+            const char* t1 = parse_nested_name(t0, last, db,<br>
+                                               ends_with_template_args);<br>
             if (t1 != t0)<br>
                 first = t1;<br>
             break;<br>
           }<br>
         case 'Z':<br>
           {<br>
-            const char* t1 = parse_local_name(t0, last, db);<br>
+            const char* t1 = parse_local_name(t0, last, db,<br>
+                                              ends_with_template_args);<br>
             if (t1 != t0)<br>
                 first = t1;<br>
             break;<br>
@@ -4230,6 +4222,8 @@ parse_name(const char* first, const char<br>
                         db.names.pop_back();<br>
                         db.names.back().first += tmp;<br>
                         first = t1;<br>
+                        if (ends_with_template_args)<br>
+                            *ends_with_template_args = true;<br>
                     }<br>
                 }<br>
                 else   // <unscoped-name><br>
@@ -4250,6 +4244,8 @@ parse_name(const char* first, const char<br>
                         db.names.pop_back();<br>
                         db.names.back().first += tmp;<br>
                         first = t1;<br>
+                        if (ends_with_template_args)<br>
+                            *ends_with_template_args = true;<br>
                     }<br>
                 }<br>
             }<br>
@@ -4423,7 +4419,7 @@ parse_special_name(const char* first, co<br>
                 {<br>
                     if (db.names.empty())<br>
                         return first;<br>
-                    if (first[1] == 'v')<br>
+                    if (first[2] == 'v')<br>
                     {<br>
                         db.names.back().first.insert(0, "virtual thunk to ");<br>
                         first = t;<br>
@@ -4513,7 +4509,9 @@ parse_encoding(const char* first, const<br>
             break;<br>
         default:<br>
           {<br>
-            const char* t = parse_name(first, last, db);<br>
+            bool ends_with_template_args = false;<br>
+            const char* t = parse_name(first, last, db,<br>
+                                       &ends_with_template_args);<br>
             unsigned cv = <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__db.cv&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=BrftCSn9PqBxw3tytbgnk-GR30HQG7KCY9tr81m6ySA&e=" target="_blank">db.cv</a>;<br>
             unsigned ref = db.ref;<br>
             if (t != first)<br>
@@ -4529,8 +4527,7 @@ parse_encoding(const char* first, const<br>
                     const typename C::String& nm = db.names.back().first;<br>
                     if (nm.empty())<br>
                         return first;<br>
-                    if (!db.parsed_ctor_dtor_cv && nm.back() == '>' && nm[nm.size()-2] != '-'<br>
-                                                                    && nm[nm.size()-2] != '>')<br>
+                    if (!db.parsed_ctor_dtor_cv && ends_with_template_args)<br>
                     {<br>
                         t2 = parse_type(t, last, db);<br>
                         if (t2 == t)<br>
@@ -4730,7 +4727,7 @@ class arena<br>
<br>
     std::size_t<br>
     align_up(std::size_t n) noexcept<br>
-        {return n + (alignment-1) & ~(alignment-1);}<br>
+        {return (n + (alignment-1)) & ~(alignment-1);}<br>
<br>
     bool<br>
     pointer_in_buffer(char* p) noexcept<br>
@@ -4866,32 +4863,33 @@ operator!=(const malloc_alloc<T>& x, con<br>
 const size_t bs = 4 * 1024;<br>
 template <class T> using Alloc = short_alloc<T, bs>;<br>
 template <class T> using Vector = std::vector<T, Alloc<T>>;<br>
-using String = std::basic_string<char, std::char_traits<char>, malloc_alloc<char>>;<br>
<br>
+template <class StrT><br>
 struct string_pair<br>
 {<br>
-    String first;<br>
-    String second;<br>
+    StrT first;<br>
+    StrT second;<br>
<br>
     string_pair() = default;<br>
-    string_pair(String f) : first(std::move(f)) {}<br>
-    string_pair(String f, String s)<br>
+    string_pair(StrT f) : first(std::move(f)) {}<br>
+    string_pair(StrT f, StrT s)<br>
         : first(std::move(f)), second(std::move(s)) {}<br>
     template <size_t N><br>
         string_pair(const char (&s)[N]) : first(s, N-1) {}<br>
<br>
     size_t size() const {return first.size() + second.size();}<br>
-    String full() const {return first + second;}<br>
-    String move_full() {return std::move(first) + std::move(second);}<br>
+    StrT full() const {return first + second;}<br>
+    StrT move_full() {return std::move(first) + std::move(second);}<br>
 };<br>
<br>
 struct Db<br>
 {<br>
-    typedef ::String String;<br>
-    typedef Vector<string_pair> sub_type;<br>
+    typedef std::basic_string<char, std::char_traits<char>,<br>
+                              malloc_alloc<char>> String;<br>
+    typedef Vector<string_pair<String>> sub_type;<br>
     typedef Vector<sub_type> template_param_type;<br>
-    Vector<string_pair> names;<br>
-    Vector<sub_type> subs;<br>
+    sub_type names;<br>
+    template_param_type subs;<br>
     Vector<template_param_type> template_param;<br>
     unsigned cv;<br>
     unsigned ref;<br>
@@ -4909,6 +4907,8 @@ struct Db<br>
     {}<br>
 };<br>
<br>
+}  // unnamed namespace<br>
+<br>
 char*<br>
 __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status)<br>
 {<br>
@@ -4976,410 +4976,4 @@ __cxa_demangle(const char* mangled_name,<br>
     return buf;<br>
 }<br>
<br>
-}<br>
-#endif<br>
-<br>
-<br>
-#include "llvm/ADT/DenseMap.h"<br>
-<br>
-#include "lldb/Core/ConstString.h"<br>
-#include "lldb/Core/Mangled.h"<br>
-#include "lldb/Core/RegularExpression.h"<br>
-#include "lldb/Core/Stream.h"<br>
-#include "lldb/Core/Timer.h"<br>
-#include "lldb/Target/CPPLanguageRuntime.h"<br>
-#include <ctype.h><br>
-#include <string.h><br>
-#include <stdlib.h><br>
-<br>
-<br>
-using namespace lldb_private;<br>
-<br>
-static inline bool<br>
-cstring_is_mangled (const char *s)<br>
-{<br>
-    if (s)<br>
-#if defined(_MSC_VER)<br>
-        return (s[0] == '?');<br>
-#else<br>
-        return (s[0] == '_' && s[1] == 'Z');<br>
-#endif<br>
-    return false;<br>
-}<br>
-<br>
-static const ConstString &<br>
-get_demangled_name_without_arguments (const Mangled *obj)<br>
-{<br>
-    // This pair is <mangled name, demangled name without function arguments><br>
-    static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;<br>
-<br>
-    // Need to have the mangled & demangled names we're currently examining as statics<br>
-    // so we can return a const ref to them at the end of the func if we don't have<br>
-    // anything better.<br>
-    static ConstString g_last_mangled;<br>
-    static ConstString g_last_demangled;<br>
-<br>
-    ConstString mangled = obj->GetMangledName ();<br>
-    ConstString demangled = obj->GetDemangledName ();<br>
-<br>
-    if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)<br>
-    {<br>
-        return g_most_recent_mangled_to_name_sans_args.second;<br>
-    }<br>
-<br>
-    g_last_demangled = demangled;<br>
-    g_last_mangled = mangled;<br>
-<br>
-    const char *mangled_name_cstr = mangled.GetCString();<br>
-<br>
-    if (demangled && mangled_name_cstr && mangled_name_cstr[0])<br>
-    {<br>
-        if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&<br>
-            (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name<br>
-            mangled_name_cstr[2] != 'G' && // avoid guard variables<br>
-            mangled_name_cstr[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)<br>
-        {<br>
-            CPPLanguageRuntime::MethodName cxx_method (demangled);<br>
-            if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty())<br>
-            {<br>
-                std::string shortname = cxx_method.GetContext().str();<br>
-                shortname += "::";<br>
-                shortname += cxx_method.GetBasename().str();<br>
-                ConstString result(shortname.c_str());<br>
-                g_most_recent_mangled_to_name_sans_args.first = mangled;<br>
-                g_most_recent_mangled_to_name_sans_args.second = result;<br>
-                return g_most_recent_mangled_to_name_sans_args.second;<br>
-            }<br>
-        }<br>
-    }<br>
-<br>
-    if (demangled)<br>
-        return g_last_demangled;<br>
-    return g_last_mangled;<br>
-}<br>
-<br>
-#pragma mark Mangled<br>
-//----------------------------------------------------------------------<br>
-// Default constructor<br>
-//----------------------------------------------------------------------<br>
-Mangled::Mangled () :<br>
-    m_mangled(),<br>
-    m_demangled()<br>
-{<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Constructor with an optional string and a boolean indicating if it is<br>
-// the mangled version.<br>
-//----------------------------------------------------------------------<br>
-Mangled::Mangled (const ConstString &s, bool mangled) :<br>
-    m_mangled(),<br>
-    m_demangled()<br>
-{<br>
-    if (s)<br>
-        SetValue(s, mangled);<br>
-}<br>
-<br>
-Mangled::Mangled (const ConstString &s) :<br>
-    m_mangled(),<br>
-    m_demangled()<br>
-{<br>
-    if (s)<br>
-        SetValue(s);<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Destructor<br>
-//----------------------------------------------------------------------<br>
-Mangled::~Mangled ()<br>
-{<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Convert to pointer operator. This allows code to check any Mangled<br>
-// objects to see if they contain anything valid using code such as:<br>
-//<br>
-//  Mangled mangled(...);<br>
-//  if (mangled)<br>
-//  { ...<br>
-//----------------------------------------------------------------------<br>
-Mangled::operator void* () const<br>
-{<br>
-    return (m_mangled) ? const_cast<Mangled*>(this) : NULL;<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Logical NOT operator. This allows code to check any Mangled<br>
-// objects to see if they are invalid using code such as:<br>
-//<br>
-//  Mangled mangled(...);<br>
-//  if (!file_spec)<br>
-//  { ...<br>
-//----------------------------------------------------------------------<br>
-bool<br>
-Mangled::operator! () const<br>
-{<br>
-    return !m_mangled;<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Clear the mangled and demangled values.<br>
-//----------------------------------------------------------------------<br>
-void<br>
-Mangled::Clear ()<br>
-{<br>
-    m_mangled.Clear();<br>
-    m_demangled.Clear();<br>
-}<br>
-<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Compare the the string values.<br>
-//----------------------------------------------------------------------<br>
-int<br>
-Mangled::Compare (const Mangled& a, const Mangled& b)<br>
-{<br>
-    return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));<br>
-}<br>
-<br>
-<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Set the string value in this objects. If "mangled" is true, then<br>
-// the mangled named is set with the new value in "s", else the<br>
-// demangled name is set.<br>
-//----------------------------------------------------------------------<br>
-void<br>
-Mangled::SetValue (const ConstString &s, bool mangled)<br>
-{<br>
-    if (s)<br>
-    {<br>
-        if (mangled)<br>
-        {<br>
-            m_demangled.Clear();<br>
-            m_mangled = s;<br>
-        }<br>
-        else<br>
-        {<br>
-            m_demangled = s;<br>
-            m_mangled.Clear();<br>
-        }<br>
-    }<br>
-    else<br>
-    {<br>
-        m_demangled.Clear();<br>
-        m_mangled.Clear();<br>
-    }<br>
-}<br>
-<br>
-void<br>
-Mangled::SetValue (const ConstString &name)<br>
-{<br>
-    if (name)<br>
-    {<br>
-        if (cstring_is_mangled(name.GetCString()))<br>
-        {<br>
-            m_demangled.Clear();<br>
-            m_mangled = name;<br>
-        }<br>
-        else<br>
-        {<br>
-            m_demangled = name;<br>
-            m_mangled.Clear();<br>
-        }<br>
-    }<br>
-    else<br>
-    {<br>
-        m_demangled.Clear();<br>
-        m_mangled.Clear();<br>
-    }<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Generate the demangled name on demand using this accessor. Code in<br>
-// this class will need to use this accessor if it wishes to decode<br>
-// the demangled name. The result is cached and will be kept until a<br>
-// new string value is supplied to this object, or until the end of the<br>
-// object's lifetime.<br>
-//----------------------------------------------------------------------<br>
-const ConstString&<br>
-Mangled::GetDemangledName () const<br>
-{<br>
-    // Check to make sure we have a valid mangled name and that we<br>
-    // haven't already decoded our mangled name.<br>
-    if (m_mangled && !m_demangled)<br>
-    {<br>
-        // We need to generate and cache the demangled name.<br>
-        Timer scoped_timer (__PRETTY_FUNCTION__,<br>
-                            "Mangled::GetDemangledName (m_mangled = %s)",<br>
-                            m_mangled.GetCString());<br>
-<br>
-        // Don't bother running anything that isn't mangled<br>
-        const char *mangled_cstr = m_mangled.GetCString();<br>
-        if (cstring_is_mangled(mangled_cstr))<br>
-        {<br>
-            if (!m_mangled.GetMangledCounterpart(m_demangled))<br>
-            {<br>
-                // We didn't already mangle this name, demangle it and if all goes well<br>
-                // add it to our map.<br>
-#ifdef LLDB_USE_BUILTIN_DEMANGLER<br>
-                // Try to use the fast-path demangler first for the<br>
-                // performance win, falling back to the full demangler only<br>
-                // when necessary<br>
-                char *demangled_name = FastDemangle (mangled_cstr,<br>
-                                                     m_mangled.GetLength());<br>
-                if (!demangled_name)<br>
-                    demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);<br>
-#elif defined(_MSC_VER)<br>
-                char *demangled_name = (char *)::malloc(1024);<br>
-                ::ZeroMemory(demangled_name, 1024);<br>
-                DWORD result = ::UnDecorateSymbolName(mangled_cstr, demangled_name, 1023,<br>
-                                                      UNDNAME_NO_ACCESS_SPECIFIERS |       // Strip public, private, protected keywords<br>
-                                                          UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords<br>
-                                                          UNDNAME_NO_THROW_SIGNATURES |    // Strip throw() specifications<br>
-                                                          UNDNAME_NO_MEMBER_TYPE |         // Strip virtual, static, etc specifiers<br>
-                                                          UNDNAME_NO_MS_KEYWORDS           // Strip all MS extension keywords<br>
-                                                      );<br>
-                if (result == 0)<br>
-                {<br>
-                    free (demangled_name);<br>
-                    demangled_name = nullptr;<br>
-                }<br>
-#else<br>
-                char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);<br>
-#endif<br>
-<br>
-                if (demangled_name)<br>
-                {<br>
-                    m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);<br>
-                    free (demangled_name);<br>
-                }<br>
-            }<br>
-        }<br>
-        if (!m_demangled)<br>
-        {<br>
-            // Set the demangled string to the empty string to indicate we<br>
-            // tried to parse it once and failed.<br>
-            m_demangled.SetCString("");<br>
-        }<br>
-    }<br>
-<br>
-    return m_demangled;<br>
-}<br>
-<br>
-<br>
-bool<br>
-Mangled::NameMatches (const RegularExpression& regex) const<br>
-{<br>
-    if (m_mangled && regex.Execute (m_mangled.AsCString()))<br>
-        return true;<br>
-<br>
-    if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))<br>
-        return true;<br>
-    return false;<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Get the demangled name if there is one, else return the mangled name.<br>
-//----------------------------------------------------------------------<br>
-const ConstString&<br>
-Mangled::GetName (Mangled::NamePreference preference) const<br>
-{<br>
-    if (preference == ePreferDemangledWithoutArguments)<br>
-    {<br>
-        // Call the accessor to make sure we get a demangled name in case<br>
-        // it hasn't been demangled yet...<br>
-        GetDemangledName();<br>
-<br>
-        return get_demangled_name_without_arguments (this);<br>
-    }<br>
-    if (preference == ePreferDemangled)<br>
-    {<br>
-        // Call the accessor to make sure we get a demangled name in case<br>
-        // it hasn't been demangled yet...<br>
-        if (GetDemangledName())<br>
-            return m_demangled;<br>
-        return m_mangled;<br>
-    }<br>
-    else<br>
-    {<br>
-        if (m_mangled)<br>
-            return m_mangled;<br>
-        return GetDemangledName();<br>
-    }<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Dump a Mangled object to stream "s". We don't force our<br>
-// demangled name to be computed currently (we don't use the accessor).<br>
-//----------------------------------------------------------------------<br>
-void<br>
-Mangled::Dump (Stream *s) const<br>
-{<br>
-    if (m_mangled)<br>
-    {<br>
-        *s << ", mangled = " << m_mangled;<br>
-    }<br>
-    if (m_demangled)<br>
-    {<br>
-        const char * demangled = m_demangled.AsCString();<br>
-        s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");<br>
-    }<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Dumps a debug version of this string with extra object and state<br>
-// information to stream "s".<br>
-//----------------------------------------------------------------------<br>
-void<br>
-Mangled::DumpDebug (Stream *s) const<br>
-{<br>
-    s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2),<br>
-              static_cast<const void*>(this));<br>
-    m_mangled.DumpDebug(s);<br>
-    s->Printf(", demangled = ");<br>
-    m_demangled.DumpDebug(s);<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Return the size in byte that this object takes in memory. The size<br>
-// includes the size of the objects it owns, and not the strings that<br>
-// it references because they are shared strings.<br>
-//----------------------------------------------------------------------<br>
-size_t<br>
-Mangled::MemorySize () const<br>
-{<br>
-    return m_mangled.MemorySize() + m_demangled.MemorySize();<br>
-}<br>
-<br>
-lldb::LanguageType<br>
-Mangled::GetLanguage ()<br>
-{<br>
-    ConstString mangled = GetMangledName();<br>
-    if (mangled)<br>
-    {<br>
-        if (GetDemangledName())<br>
-        {<br>
-            if (cstring_is_mangled(mangled.GetCString()))<br>
-                return lldb::eLanguageTypeC_plus_plus;<br>
-        }<br>
-    }<br>
-    return  lldb::eLanguageTypeUnknown;<br>
-}<br>
-<br>
-//----------------------------------------------------------------------<br>
-// Dump OBJ to the supplied stream S.<br>
-//----------------------------------------------------------------------<br>
-Stream&<br>
-operator << (Stream& s, const Mangled& obj)<br>
-{<br>
-    if (obj.GetMangledName())<br>
-        s << "mangled = '" << obj.GetMangledName() << "'";<br>
-<br>
-    const ConstString& demangled = obj.GetDemangledName();<br>
-    if (demangled)<br>
-        s << ", demangled = '" << demangled << '\'';<br>
-    else<br>
-        s << ", demangled = <error>";<br>
-    return s;<br>
-}<br>
+}  // lldb_private<br>
<br>
Modified: lldb/trunk/source/Core/Mangled.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lldb_trunk_source_Core_Mangled.cpp-3Frev-3D238459-26r1-3D238458-26r2-3D238459-26view-3Ddiff&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=5j0OxLFy4-GN_HlMDFYF31uNTxIRTTTbMRPSzCMlhR4&e=" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Mangled.cpp?rev=238459&r1=238458&r2=238459&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Core/Mangled.cpp (original)<br>
+++ lldb/trunk/source/Core/Mangled.cpp Thu May 28 14:15:15 2015<br>
@@ -23,4960 +23,9 @@<br>
<br>
 // Provide a fast-path demangler implemented in FastDemangle.cpp until it can<br>
 // replace the existing C++ demangler with a complete implementation<br>
-namespace lldb_private<br>
-{<br>
-    extern char * FastDemangle (const char * mangled_name,<br>
-                                long mangled_name_length);<br>
-}<br>
+#include "lldb/Core/FastDemangle.h"<br>
+#include "lldb/Core/CxaDemangle.h"<br>
<br>
-//----------------------------------------------------------------------<br>
-// Inlined copy of:<br>
-// <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_svn_llvm-2Dproject_libcxxabi_trunk_src_cxa-5Fdemangle.cpp&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=MEqT8U_n7oNfuDW5NRbY3ZV384ZquXIYFPWmprwUdKM&m=0xAJMsvRrvSmiEj-EefCMI4And3-u0-8nppxEkiBpIo&s=NMLNYG7odaaL2HGGoY4kXEIjc0rs3cdDXWfL7dvmwEc&e=" target="_blank">http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp</a><br>
-// revision 199944.<br>
-//<br>
-// Changes include:<br>
-// - remove the "__cxxabiv1" namespace<br>
-// - stripped GCC attributes()<br>
-// - removed extern "C" from the cxa_demangle function<br>
-// - Changed the scope of the unnamed namespace to include cxa_demangle<br>
-//   function.<br>
-// - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning<br>
-//----------------------------------------------------------------------<br>
-<br>
-#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below<br>
-<br>
-//===-------------------------- cxa_demangle.cpp --------------------------===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is dual licensed under the MIT and the University of Illinois Open<br>
-// Source Licenses. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#define _LIBCPP_EXTERN_TEMPLATE(...)<br>
-#define _LIBCPP_NO_EXCEPTIONS<br>
-<br>
-#include <vector><br>
-#include <algorithm><br>
-#include <string><br>
-#include <numeric><br>
-#include <cstdlib><br>
-#include <cstring><br>
-#include <cctype><br>
-<br>
-<br>
-namespace<br>
-{<br>
-<br>
-enum<br>
-{<br>
-    unknown_error = -4,<br>
-    invalid_args = -3,<br>
-    invalid_mangled_name,<br>
-    memory_alloc_failure,<br>
-    success<br>
-};<br>
-<br>
-template <class C><br>
-    const char* parse_type(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_encoding(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_name(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_expression(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_template_args(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_operator_name(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_unqualified_name(const char* first, const char* last, C& db);<br>
-template <class C><br>
-    const char* parse_decltype(const char* first, const char* last, C& db);<br>
-<br>
-template <class C><br>
-void<br>
-print_stack(const C& db)<br>
-{<br>
-    printf("---------\n");<br>
-    printf("names:\n");<br>
-    for (auto& s : db.names)<br>
-        printf("{%s#%s}\n", s.first.c_str(), s.second.c_str());<br>
-    int i = -1;<br>
-    printf("subs:\n");<br>
-    for (auto& v : db.subs)<br>
-    {<br>
-        if (i >= 0)<br>
-            printf("S%i_ = {", i);<br>
-        else<br>
-            printf("S_  = {");<br>
-        for (auto& s : v)<br>
-            printf("{%s#%s}", s.first.c_str(), s.second.c_str());<br>
-        printf("}\n");<br>
-        ++i;<br>
-    }<br>
-    printf("template_param:\n");<br>
-    for (auto& t : db.template_param)<br>
-    {<br>
-        printf("--\n");<br>
-        i = -1;<br>
-        for (auto& v : t)<br>
-        {<br>
-            if (i >= 0)<br>
-                printf("T%i_ = {", i);<br>
-            else<br>
-                printf("T_  = {");<br>
-            for (auto& s : v)<br>
-                printf("{%s#%s}", s.first.c_str(), s.second.c_str());<br>
-            printf("}\n");<br>
-            ++i;<br>
-        }<br>
-    }<br>
-    printf("---------\n\n");<br>
-}<br>
-<br>
-template <class C><br>
-void<br>
-print_state(const char* msg, const char* first, const char* last, const C& db)<br>
-{<br>
-    printf("%s: ", msg);<br>
-    for (; first != last; ++first)<br>
-        printf("%c", *first);<br>
-    printf("\n");<br>
-    print_stack(db);<br>
-}<br>
-<br>
-// <number> ::= [n] <non-negative decimal integer><br>
-<br>
-const char*<br>
-parse_number(const char* first, const char* last)<br>
-{<br>
-    if (first != last)<br>
-    {<br>
-        const char* t = first;<br>
-        if (*t == 'n')<br>
-            ++t;<br>
-        if (t != last)<br>
-        {<br>
-            if (*t == '0')<br>
-            {<br>
-                first = t+1;<br>
-            }<br>
-            else if ('1' <= *t && *t <= '9')<br>
-            {<br>
-                first = t+1;<br>
-                while (first != last && std::isdigit(*first))<br>
-                    ++first;<br>
-            }<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-template <class Float><br>
-struct float_data;<br>
-<br>
-template <><br>
-struct float_data<float><br>
-{<br>
-    static const size_t mangled_size = 8;<br>
-    static const size_t max_demangled_size = 24;<br>
-    static constexpr const char* spec = "%af";<br>
-};<br>
-<br>
-constexpr const char* float_data<float>::spec;<br>
-<br>
-template <><br>
-struct float_data<double><br>
-{<br>
-    static const size_t mangled_size = 16;<br>
-    static const size_t max_demangled_size = 32;<br>
-    static constexpr const char* spec = "%a";<br>
-};<br>
-<br>
-constexpr const char* float_data<double>::spec;<br>
-<br>
-template <><br>
-struct float_data<long double><br>
-{<br>
-    static const size_t mangled_size = 20;  // May need to be adjusted to 16 or 24 on other platforms<br>
-    static const size_t max_demangled_size = 40;<br>
-    static constexpr const char* spec = "%LaL";<br>
-};<br>
-<br>
-constexpr const char* float_data<long double>::spec;<br>
-<br>
-template <class Float, class C><br>
-const char*<br>
-parse_floating_number(const char* first, const char* last, C& db)<br>
-{<br>
-    const size_t N = float_data<Float>::mangled_size;<br>
-    if (static_cast<std::size_t>(last - first) > N)<br>
-    {<br>
-        last = first + N;<br>
-        union<br>
-        {<br>
-            Float value;<br>
-            char buf[sizeof(Float)];<br>
-        };<br>
-        const char* t = first;<br>
-        char* e = buf;<br>
-        for (; t != last; ++t, ++e)<br>
-        {<br>
-            if (!isxdigit(*t))<br>
-                return first;<br>
-            unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :<br>
-                                        static_cast<unsigned>(*t - 'a' + 10);<br>
-            ++t;<br>
-            unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') :<br>
-                                        static_cast<unsigned>(*t - 'a' + 10);<br>
-            *e = static_cast<char>((d1 << 4) + d0);<br>
-        }<br>
-        if (*t == 'E')<br>
-        {<br>
-#if __LITTLE_ENDIAN__<br>
-            std::reverse(buf, e);<br>
-#endif<br>
-            char num[float_data<Float>::max_demangled_size] = {0};<br>
-            int n = snprintf(num, sizeof(num), float_data<Float>::spec, value);<br>
-            if (static_cast<std::size_t>(n) >= sizeof(num))<br>
-                return first;<br>
-            db.names.push_back(typename C::String(num, static_cast<std::size_t>(n)));<br>
-            first = t+1;<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// <source-name> ::= <positive length number> <identifier><br>
-<br>
-template <class C><br>
-const char*<br>
-parse_source_name(const char* first, const char* last, C& db)<br>
-{<br>
-    if (first != last)<br>
-    {<br>
-        char c = *first;<br>
-        if (isdigit(c) && first+1 != last)<br>
-        {<br>
-            const char* t = first+1;<br>
-            size_t n = static_cast<size_t>(c - '0');<br>
-            for (c = *t; isdigit(c); c = *t)<br>
-            {<br>
-                n = n * 10 + static_cast<size_t>(c - '0');<br>
-                if (++t == last)<br>
-                    return first;<br>
-            }<br>
-            if (static_cast<size_t>(last - t) >= n)<br>
-            {<br>
-                typename C::String r(t, n);<br>
-                if (r.substr(0, 10) == "_GLOBAL__N")<br>
-                    db.names.push_back("(anonymous namespace)");<br>
-                else<br>
-                    db.names.push_back(std::move(r));<br>
-                first = t + n;<br>
-            }<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// <substitution> ::= S <seq-id> _<br>
-//                ::= S_<br>
-// <substitution> ::= Sa # ::std::allocator<br>
-// <substitution> ::= Sb # ::std::basic_string<br>
-// <substitution> ::= Ss # ::std::basic_string < char,<br>
-//                                               ::std::char_traits<char>,<br>
-//                                               ::std::allocator<char> ><br>
-// <substitution> ::= Si # ::std::basic_istream<char,  std::char_traits<char> ><br>
-// <substitution> ::= So # ::std::basic_ostream<char,  std::char_traits<char> ><br>
-// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> ><br>
-<br>
-template <class C><br>
-const char*<br>
-parse_substitution(const char* first, const char* last, C& db)<br>
-{<br>
-    if (last - first >= 2)<br>
-    {<br>
-        if (*first == 'S')<br>
-        {<br>
-            switch (first[1])<br>
-            {<br>
-            case 'a':<br>
-                db.names.push_back("std::allocator");<br>
-                first += 2;<br>
-                break;<br>
-            case 'b':<br>
-                db.names.push_back("std::basic_string");<br>
-                first += 2;<br>
-                break;<br>
-            case 's':<br>
-                db.names.push_back("std::string");<br>
-                first += 2;<br>
-                break;<br>
-            case 'i':<br>
-                db.names.push_back("std::istream");<br>
-                first += 2;<br>
-                break;<br>
-            case 'o':<br>
-                db.names.push_back("std::ostream");<br>
-                first += 2;<br>
-                break;<br>
-            case 'd':<br>
-                db.names.push_back("std::iostream");<br>
-                first += 2;<br>
-                break;<br>
-            case '_':<br>
-                if (!db.subs.empty())<br>
-                {<br>
-                    for (const auto& n : db.subs.front())<br>
-                        db.names.push_back(n);<br>
-                    first += 2;<br>
-                }<br>
-                break;<br>
-            default:<br>
-                if (std::isdigit(first[1]) || std::isupper(first[1]))<br>
-                {<br>
-                    size_t sub = 0;<br>
-                    const char* t = first+1;<br>
-                    if (std::isdigit(*t))<br>
-                        sub = static_cast<size_t>(*t - '0');<br>
-                    else<br>
-                        sub = static_cast<size_t>(*t - 'A') + 10;<br>
-                    for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t)<br>
-                    {<br>
-                        sub *= 36;<br>
-                        if (std::isdigit(*t))<br>
-                            sub += static_cast<size_t>(*t - '0');<br>
-                        else<br>
-                            sub += static_cast<size_t>(*t - 'A') + 10;<br>
-                    }<br>
-                    if (t == last || *t != '_')<br>
-                        return first;<br>
-                    ++sub;<br>
-                    if (sub < db.subs.size())<br>
-                    {<br>
-                        for (const auto& n : db.subs[sub])<br>
-                            db.names.push_back(n);<br>
-                        first = t+1;<br>
-                    }<br>
-                }<br>
-                break;<br>
-            }<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// <builtin-type> ::= v    # void<br>
-//                ::= w    # wchar_t<br>
-//                ::= b    # bool<br>
-//                ::= c    # char<br>
-//                ::= a    # signed char<br>
-//                ::= h    # unsigned char<br>
-//                ::= s    # short<br>
-//                ::= t    # unsigned short<br>
-//                ::= i    # int<br>
-//                ::= j    # unsigned int<br>
-//                ::= l    # long<br>
-//                ::= m    # unsigned long<br>
-//                ::= x    # long long, __int64<br>
-//                ::= y    # unsigned long long, __int64<br>
-//                ::= n    # __int128<br>
-//                ::= o    # unsigned __int128<br>
-//                ::= f    # float<br>
-//                ::= d    # double<br>
-//                ::= e    # long double, __float80<br>
-//                ::= g    # __float128<br>
-//                ::= z    # ellipsis<br>
-//                ::= Dd   # IEEE 754r decimal floating point (64 bits)<br>
-//                ::= De   # IEEE 754r decimal floating point (128 bits)<br>
-//                ::= Df   # IEEE 754r decimal floating point (32 bits)<br>
-//                ::= Dh   # IEEE 754r half-precision floating point (16 bits)<br>
-//                ::= Di   # char32_t<br>
-//                ::= Ds   # char16_t<br>
-//                ::= Da   # auto (in dependent new-expressions)<br>
-//                ::= Dn   # std::nullptr_t (i.e., decltype(nullptr))<br>
-//                ::= u <source-name>    # vendor extended type<br>
-<br>
-template <class C><br>
-const char*<br>
-parse_builtin_type(const char* first, const char* last, C& db)<br>
-{<br>
-    if (first != last)<br>
-    {<br>
-        switch (*first)<br>
-        {<br>
-        case 'v':<br>
-            db.names.push_back("void");<br>
-            ++first;<br>
-            break;<br>
-        case 'w':<br>
-            db.names.push_back("wchar_t");<br>
-            ++first;<br>
-            break;<br>
-        case 'b':<br>
-            db.names.push_back("bool");<br>
-            ++first;<br>
-            break;<br>
-        case 'c':<br>
-            db.names.push_back("char");<br>
-            ++first;<br>
-            break;<br>
-        case 'a':<br>
-            db.names.push_back("signed char");<br>
-            ++first;<br>
-            break;<br>
-        case 'h':<br>
-            db.names.push_back("unsigned char");<br>
-            ++first;<br>
-            break;<br>
-        case 's':<br>
-            db.names.push_back("short");<br>
-            ++first;<br>
-            break;<br>
-        case 't':<br>
-            db.names.push_back("unsigned short");<br>
-            ++first;<br>
-            break;<br>
-        case 'i':<br>
-            db.names.push_back("int");<br>
-            ++first;<br>
-            break;<br>
-        case 'j':<br>
-            db.names.push_back("unsigned int");<br>
-            ++first;<br>
-            break;<br>
-        case 'l':<br>
-            db.names.push_back("long");<br>
-            ++first;<br>
-            break;<br>
-        case 'm':<br>
-            db.names.push_back("unsigned long");<br>
-            ++first;<br>
-            break;<br>
-        case 'x':<br>
-            db.names.push_back("long long");<br>
-            ++first;<br>
-            break;<br>
-        case 'y':<br>
-            db.names.push_back("unsigned long long");<br>
-            ++first;<br>
-            break;<br>
-        case 'n':<br>
-            db.names.push_back("__int128");<br>
-            ++first;<br>
-            break;<br>
-        case 'o':<br>
-            db.names.push_back("unsigned __int128");<br>
-            ++first;<br>
-            break;<br>
-        case 'f':<br>
-            db.names.push_back("float");<br>
-            ++first;<br>
-            break;<br>
-        case 'd':<br>
-            db.names.push_back("double");<br>
-            ++first;<br>
-            break;<br>
-        case 'e':<br>
-            db.names.push_back("long double");<br>
-            ++first;<br>
-            break;<br>
-        case 'g':<br>
-            db.names.push_back("__float128");<br>
-            ++first;<br>
-            break;<br>
-        case 'z':<br>
-            db.names.push_back("...");<br>
-            ++first;<br>
-            break;<br>
-        case 'u':<br>
-            {<br>
-                const char*t = parse_source_name(first+1, last, db);<br>
-                if (t != first+1)<br>
-                    first = t;<br>
-            }<br>
-            break;<br>
-        case 'D':<br>
-            if (first+1 != last)<br>
-            {<br>
-                switch (first[1])<br>
-                {<br>
-                case 'd':<br>
-                    db.names.push_back("decimal64");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'e':<br>
-                    db.names.push_back("decimal128");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'f':<br>
-                    db.names.push_back("decimal32");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'h':<br>
-                    db.names.push_back("decimal16");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'i':<br>
-                    db.names.push_back("char32_t");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 's':<br>
-                    db.names.push_back("char16_t");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'a':<br>
-                    db.names.push_back("auto");<br>
-                    first += 2;<br>
-                    break;<br>
-                case 'n':<br>
-                    db.names.push_back("std::nullptr_t");<br>
-                    first += 2;<br>
-                    break;<br>
-                }<br>
-            }<br>
-            break;<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// <CV-qualifiers> ::= [r] [V] [K]<br>
-<br>
-const char*<br>
-parse_cv_qualifiers(const char* first, const char* last, unsigned& cv)<br>
-{<br>
-    cv = 0;<br>
-    if (first != last)<br>
-    {<br>
-        if (*first == 'r')<br>
-        {<br>
-            cv |= 4;<br>
-            ++first;<br>
-        }<br>
-        if (*first == 'V')<br>
-        {<br>
-            cv |= 2;<br>
-            ++first;<br>
-        }<br>
-        if (*first == 'K')<br>
-        {<br>
-            cv |= 1;<br>
-            ++first;<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// <template-param> ::= T_    # first template parameter<br>
-//                  ::= T <parameter-2 non-negative number> _<br>
-<br>
-template <class C><br>
-const char*<br>
-parse_template_param(const char* first, const char* last, C& db)<br>
-{<br>
-    if (last - first >= 2)<br>
-    {<br>
-        if (*first == 'T')<br>
-        {<br>
-            if (first[1] == '_')<br>
-            {<br>
-                if (db.template_param.empty())<br>
-                    return first;<br>
-                if (!db.template_param.back().empty())<br>
-                {<br>
-                    for (auto& t : db.template_param.back().front())<br>
-                        db.names.push_back(t);<br>
-                    first += 2;<br>
-                }<br>
-                else<br>
-                {<br>
-                    db.names.push_back("T_");<br>
-                    first += 2;<br>
-                    db.fix_forward_references = true;<br>
-                }<br>
-            }<br>
-            else if (isdigit(first[1]))<br>
-            {<br>
-                const char* t = first+1;<br>
-                size_t sub = static_cast<size_t>(*t - '0');<br>
-                for (++t; t != last && isdigit(*t); ++t)<br>
-                {<br>
-                    sub *= 10;<br>
-                    sub += static_cast<size_t>(*t - '0');<br>
-                }<br>
-                if (t == last || *t != '_' || db.template_param.empty())<br>
-                    return first;<br>
-                ++sub;<br>
-                if (sub < db.template_param.back().size())<br>
-                {<br>
-                    for (auto& temp : db.template_param.back()[sub])<br>
-                        db.names.push_back(temp);<br>
-                    first = t+1;<br>
-                }<br>
-                else<br>
-                {<br>
-                    db.names.push_back(typename C::String(first, t+1));<br>
-                    first = t+1;<br>
-                    db.fix_forward_references = true;<br>
-                }<br>
-            }<br>
-        }<br>
-    }<br>
-    return first;<br>
-}<br>
-<br>
-// cc <type> <expression>                               # const_cast<type> (expression)<br>
-<br>
-template <class C><br>
-const char*<br>
-parse_const_cast_expr(const char* first, c</blockquote></div>