Allow both MSVC and Itanium mangling schemes.

Summary:
LLDB on Windows should now be able to demangle Linux/Android symbols.

Also updated CxaDemangle.cpp to be compatible with MSVC.

Depends on D9949, D9954, D10048.

Reviewers: zturner, emaste, clayborg

Reviewed By: clayborg

Subscribers: tberghammer, lldb-commits

Differential Revision: http://reviews.llvm.org/D10040

llvm-svn: 238460
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 87b2379..a307bac 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -41,6 +41,13 @@
         ePreferDemangledWithoutArguments
     };
 
+    enum ManglingScheme
+    {
+        eManglingSchemeNone = 0,
+        eManglingSchemeMSVC,
+        eManglingSchemeItanium
+    };
+
     //----------------------------------------------------------------------
     /// Default constructor.
     ///
diff --git a/lldb/source/Core/CxaDemangle.cpp b/lldb/source/Core/CxaDemangle.cpp
index 5c05db9..16cdb02 100644
--- a/lldb/source/Core/CxaDemangle.cpp
+++ b/lldb/source/Core/CxaDemangle.cpp
@@ -8,9 +8,18 @@
 // - Stripped GCC attributes()
 // - Removed extern "C" from the cxa_demangle function
 // - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning
+// - Implemented missing rebind, construct, destroy in malloc_alloc
+// - Replaced noexcept, constexpr, alignas with their LLVM_* equivalents
+// - Included win32.h for snprintf implementation for MSVC
+// - Removed constexpr member initialization for MSVC
+// - Changed argument to alignas() to a literal for MSVC
 //----------------------------------------------------------------------
 
-#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below
+#if defined(_MSC_VER)
+#include "lldb/Host/windows/win32.h" // snprintf
+#endif
+#include "llvm/Support/Compiler.h"   // LLVM_{NOEXCEPT, CONSTEXPR, ALIGNAS}
+#undef _LIBCPP_EXTERN_TEMPLATE       // Avoid warning below
 
 //===-------------------------- cxa_demangle.cpp --------------------------===//
 //
@@ -152,20 +161,20 @@
 {
     static const size_t mangled_size = 8;
     static const size_t max_demangled_size = 24;
-    static constexpr const char* spec = "%af";
+    static const char* spec;
 };
 
-constexpr const char* float_data<float>::spec;
+const char* float_data<float>::spec = "%af";
 
 template <>
 struct float_data<double>
 {
     static const size_t mangled_size = 16;
     static const size_t max_demangled_size = 32;
-    static constexpr const char* spec = "%a";
+    static const char* spec;
 };
 
-constexpr const char* float_data<double>::spec;
+const char* float_data<double>::spec = "%a";
 
 template <>
 struct float_data<long double>
@@ -176,10 +185,10 @@
     static const size_t mangled_size = 20;  // May need to be adjusted to 16 or 24 on other platforms
 #endif
     static const size_t max_demangled_size = 40;
-    static constexpr const char* spec = "%LaL";
+    static const char* spec;
 };
 
-constexpr const char* float_data<long double>::spec;
+const char* float_data<long double>::spec = "%LaL";
 
 template <class Float, class C>
 const char*
@@ -4722,27 +4731,27 @@
 class arena
 {
     static const std::size_t alignment = 16;
-    alignas(alignment) char buf_[N];
+    LLVM_ALIGNAS(16) char buf_[N];
     char* ptr_;
 
     std::size_t 
-    align_up(std::size_t n) noexcept
+    align_up(std::size_t n) LLVM_NOEXCEPT
         {return (n + (alignment-1)) & ~(alignment-1);}
 
     bool
-    pointer_in_buffer(char* p) noexcept
+    pointer_in_buffer(char* p) LLVM_NOEXCEPT
         {return buf_ <= p && p <= buf_ + N;}
 
 public:
-    arena() noexcept : ptr_(buf_) {}
+    arena() LLVM_NOEXCEPT : ptr_(buf_) {}
     ~arena() {ptr_ = nullptr;}
     arena(const arena&) = delete;
     arena& operator=(const arena&) = delete;
 
     char* allocate(std::size_t n);
-    void deallocate(char* p, std::size_t n) noexcept;
+    void deallocate(char* p, std::size_t n) LLVM_NOEXCEPT;
 
-    static constexpr std::size_t size() {return N;}
+    static LLVM_CONSTEXPR std::size_t size() {return N;}
     std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);}
     void reset() {ptr_ = buf_;}
 };
@@ -4763,7 +4772,7 @@
 
 template <std::size_t N>
 void
-arena<N>::deallocate(char* p, std::size_t n) noexcept
+arena<N>::deallocate(char* p, std::size_t n) LLVM_NOEXCEPT
 {
     if (pointer_in_buffer(p))
     {
@@ -4785,9 +4794,9 @@
 public:
     template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;};
 
-    short_alloc(arena<N>& a) noexcept : a_(a) {}
+    short_alloc(arena<N>& a) LLVM_NOEXCEPT : a_(a) {}
     template <class U>
-        short_alloc(const short_alloc<U, N>& a) noexcept
+        short_alloc(const short_alloc<U, N>& a) LLVM_NOEXCEPT
             : a_(a.a_) {}
     short_alloc(const short_alloc&) = default;
     short_alloc& operator=(const short_alloc&) = delete;
@@ -4796,7 +4805,7 @@
     {
         return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
     }
-    void deallocate(T* p, std::size_t n) noexcept
+    void deallocate(T* p, std::size_t n) LLVM_NOEXCEPT
     {
         a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
     }
@@ -4804,7 +4813,7 @@
     template <class T1, std::size_t N1, class U, std::size_t M>
     friend
     bool
-    operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;
+    operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT;
 
     template <class U, std::size_t M> friend class short_alloc;
 };
@@ -4812,7 +4821,7 @@
 template <class T, std::size_t N, class U, std::size_t M>
 inline
 bool
-operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
+operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT
 {
     return N == M && &x.a_ == &y.a_;
 }
@@ -4820,7 +4829,7 @@
 template <class T, std::size_t N, class U, std::size_t M>
 inline
 bool
-operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
+operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT
 {
     return !(x == y);
 }
@@ -4832,22 +4841,39 @@
     typedef T value_type;
 
     malloc_alloc() = default;
-    template <class U> malloc_alloc(const malloc_alloc<U>&) noexcept {}
+    template <class U> malloc_alloc(const malloc_alloc<U>&) LLVM_NOEXCEPT {}
 
     T* allocate(std::size_t n)
     {
         return static_cast<T*>(std::malloc(n*sizeof(T)));
     }
-    void deallocate(T* p, std::size_t) noexcept
+    void deallocate(T* p, std::size_t) LLVM_NOEXCEPT
     {
         std::free(p);
     }
+    template<class Other>
+    struct rebind
+    {
+        typedef malloc_alloc<Other> other;
+    };
+    void construct(T *p)
+    {
+        ::new (p) T();
+    }
+    void construct(T *p, const T& t)
+    {
+        ::new (p) T(t);
+    }
+    void destroy(T *p)
+    {
+        p->~T();
+    }
 };
 
 template <class T, class U>
 inline
 bool
-operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) noexcept
+operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) LLVM_NOEXCEPT
 {
     return true;
 }
@@ -4855,7 +4881,7 @@
 template <class T, class U>
 inline
 bool
-operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) noexcept
+operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) LLVM_NOEXCEPT
 {
     return !(x == y);
 }
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 48d1182..d277db7 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -13,6 +13,7 @@
 #if defined(_MSC_VER)
 #include "lldb/Host/windows/windows.h"
 #include <Dbghelp.h>
+#define LLDB_USE_BUILTIN_DEMANGLER
 #elif defined (__FreeBSD__)
 #define LLDB_USE_BUILTIN_DEMANGLER
 #else
@@ -44,16 +45,23 @@
 
 using namespace lldb_private;
 
-static inline bool
-cstring_is_mangled (const char *s)
+static inline Mangled::ManglingScheme
+cstring_mangling_scheme(const char *s)
 {
     if (s)
-#if defined(_MSC_VER)
-        return (s[0] == '?');
-#else
-        return (s[0] == '_' && s[1] == 'Z');
-#endif
-    return false;
+    {
+        if (s[0] == '?')
+            return Mangled::eManglingSchemeMSVC;
+        if (s[0] == '_' && s[1] == 'Z')
+            return Mangled::eManglingSchemeItanium;
+    }
+    return Mangled::eManglingSchemeNone;
+}
+
+static inline bool
+cstring_is_mangled(const char *s)
+{
+    return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
 }
 
 static const ConstString &
@@ -264,45 +272,58 @@
                             m_mangled.GetCString());
 
         // Don't bother running anything that isn't mangled
-        const char *mangled_cstr = m_mangled.GetCString();
-        if (cstring_is_mangled(mangled_cstr))
+        const char *mangled_name = m_mangled.GetCString();
+        ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
+        if (mangling_scheme != eManglingSchemeNone &&
+            !m_mangled.GetMangledCounterpart(m_demangled))
         {
-            if (!m_mangled.GetMangledCounterpart(m_demangled))
+            // We didn't already mangle this name, demangle it and if all goes well
+            // add it to our map.
+            char *demangled_name = nullptr;
+            switch (mangling_scheme)
             {
-                // We didn't already mangle this name, demangle it and if all goes well
-                // add it to our map.
-#ifdef LLDB_USE_BUILTIN_DEMANGLER
-                // Try to use the fast-path demangler first for the
-                // performance win, falling back to the full demangler only
-                // when necessary
-                char *demangled_name = FastDemangle (mangled_cstr,
-                                                     m_mangled.GetLength());
-                if (!demangled_name)
-                    demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
-#elif defined(_MSC_VER)
-                char *demangled_name = (char *)::malloc(1024);
-                ::ZeroMemory(demangled_name, 1024);
-                DWORD result = ::UnDecorateSymbolName(mangled_cstr, demangled_name, 1023,
-                                                      UNDNAME_NO_ACCESS_SPECIFIERS |       // Strip public, private, protected keywords
-                                                          UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords
-                                                          UNDNAME_NO_THROW_SIGNATURES |    // Strip throw() specifications
-                                                          UNDNAME_NO_MEMBER_TYPE |         // Strip virtual, static, etc specifiers
-                                                          UNDNAME_NO_MS_KEYWORDS           // Strip all MS extension keywords
-                                                      );
-                if (result == 0)
+                case eManglingSchemeMSVC:
                 {
-                    free (demangled_name);
-                    demangled_name = nullptr;
-                }
-#else
-                char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
+#if defined(_MSC_VER)
+                    const size_t demangled_length = 2048;
+                    demangled_name = static_cast<char *>(::malloc(demangled_length));
+                    ::ZeroMemory(demangled_name, demangled_length);
+                    DWORD result = ::UnDecorateSymbolName(mangled_name, demangled_name, demangled_length,
+                            UNDNAME_NO_ACCESS_SPECIFIERS   | // Strip public, private, protected keywords
+                            UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords
+                            UNDNAME_NO_THROW_SIGNATURES    | // Strip throw() specifications
+                            UNDNAME_NO_MEMBER_TYPE         | // Strip virtual, static, etc specifiers
+                            UNDNAME_NO_MS_KEYWORDS           // Strip all MS extension keywords
+                        );
+                    if (result == 0)
+                    {
+                        free(demangled_name);
+                        demangled_name = nullptr;
+                    }
 #endif
-
-                if (demangled_name)
-                {
-                    m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
-                    free (demangled_name);
+                    break;
                 }
+                case eManglingSchemeItanium:
+                {
+#ifdef LLDB_USE_BUILTIN_DEMANGLER
+                    // Try to use the fast-path demangler first for the
+                    // performance win, falling back to the full demangler only
+                    // when necessary
+                    demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
+                    if (!demangled_name)
+                        demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL);
+#else
+                    demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
+#endif
+                    break;
+                }
+                case eManglingSchemeNone:
+                    break;
+            }
+            if (demangled_name)
+            {
+                m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
+                free(demangled_name);
             }
         }
         if (!m_demangled)