mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Add a Microsoft Demangler.
This adds initial support for a demangling library (LLVMDemangle) and tool (llvm-undname) for demangling Microsoft names. This doesn't cover 100% of cases and there are some known limitations which I intend to address in followup patches, at least until such time that we have (near) 100% test coverage matching up with all of the test cases in clang/test/CodeGenCXX/mangle-ms-*. Differential Revision: https://reviews.llvm.org/D49552 llvm-svn: 337584
This commit is contained in:
parent
b9adc67df4
commit
0bef0a2efc
@ -16,7 +16,7 @@ namespace llvm {
|
||||
/// The mangled_name is demangled into buf and returned. If the buffer is not
|
||||
/// large enough, realloc is used to expand it.
|
||||
///
|
||||
/// The *status will be set to a value from the enumeration
|
||||
/// The *status will be set to a value from the following enumeration
|
||||
enum : int {
|
||||
demangle_unknown_error = -4,
|
||||
demangle_invalid_args = -3,
|
||||
@ -27,6 +27,8 @@ enum : int {
|
||||
|
||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
|
||||
/// "Partial" demangler. This supports demangling a string into an AST
|
||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||
|
@ -1,6 +1,7 @@
|
||||
add_llvm_library(LLVMDemangle
|
||||
ItaniumDemangle.cpp
|
||||
|
||||
MicrosoftDemangle.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
"${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"
|
||||
)
|
||||
|
1533
lib/Demangle/MicrosoftDemangle.cpp
Normal file
1533
lib/Demangle/MicrosoftDemangle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
230
test/Demangle/ms-basic.test
Normal file
230
test/Demangle/ms-basic.test
Normal file
@ -0,0 +1,230 @@
|
||||
; RUN: llvm-undname < %s | FileCheck %s
|
||||
|
||||
; CHECK-NOT: Invalid mangled name
|
||||
|
||||
?x@@3HA
|
||||
; CHECK: int x
|
||||
|
||||
?x@@3PEAHEA
|
||||
; CHECK: int *x
|
||||
|
||||
?x@@3PEAPEAHEA
|
||||
; CHECK: int **x
|
||||
|
||||
?x@@3PEAY02HEA
|
||||
; CHECK: int (*x)[3]
|
||||
|
||||
?x@@3PEAY124HEA
|
||||
; CHECK: int (*x)[3][5]
|
||||
|
||||
?x@@3PEAY02$$CBHEA
|
||||
; CHECK: int const (*x)[3]
|
||||
|
||||
?x@@3PEAEEA
|
||||
; CHECK: unsigned char *x
|
||||
|
||||
?x@@3PEAY1NKM@5HEA
|
||||
; CHECK: int (*x)[3500][6]
|
||||
|
||||
?x@@YAXMH@Z
|
||||
; CHECK: void __cdecl x(float, int)
|
||||
|
||||
?x@@3P6AHMNH@ZEA
|
||||
; CHECK: int __cdecl (*x)(float, double, int)
|
||||
|
||||
?x@@3P6AHP6AHM@ZN@ZEA
|
||||
; CHECK: int __cdecl (*x)(int __cdecl (*)(float), double)
|
||||
|
||||
?x@@3P6AHP6AHM@Z0@ZEA
|
||||
; CHECK: int __cdecl (*x)(int __cdecl (*)(float), int __cdecl (*)(float))
|
||||
|
||||
?x@ns@@3HA
|
||||
; CHECK: int ns::x
|
||||
|
||||
; Microsoft's undname doesn't handle Q correctly or the multiple occurrences
|
||||
; of the const modifier. So the results here differ, but ours are correct.
|
||||
?x@@3PEAHEA
|
||||
; CHECK: int *x
|
||||
|
||||
?x@@3PEBHEB
|
||||
; CHECK: int const *x
|
||||
|
||||
?x@@3QEAHEA
|
||||
; CHECK: int *const x
|
||||
|
||||
?x@@3QEBHEB
|
||||
; CHECK: int const *const x
|
||||
|
||||
|
||||
?x@@3AEBHEB
|
||||
; CHECK: int const &x
|
||||
|
||||
?x@@3PEAUty@@EA
|
||||
; CHECK: struct ty *x
|
||||
|
||||
?x@@3PEATty@@EA
|
||||
; CHECK: union ty *x
|
||||
|
||||
?x@@3PEAUty@@EA
|
||||
; CHECK: struct ty *x
|
||||
|
||||
?x@@3PEAW4ty@@EA
|
||||
; CHECK: enum ty *x
|
||||
|
||||
?x@@3PEAVty@@EA
|
||||
; CHECK: class ty *x
|
||||
|
||||
?x@@3PEAV?$tmpl@H@@EA
|
||||
; CHECK: class tmpl<int> *x
|
||||
|
||||
?x@@3PEAU?$tmpl@H@@EA
|
||||
; CHECK: struct tmpl<int> *x
|
||||
|
||||
?x@@3PEAT?$tmpl@H@@EA
|
||||
; CHECK: union tmpl<int> *x
|
||||
|
||||
?instance@@3Vklass@@A
|
||||
; CHECK: class klass instance
|
||||
|
||||
?instance$initializer$@@3P6AXXZEA
|
||||
; CHECK: void __cdecl (*instance$initializer$)(void)
|
||||
|
||||
??0klass@@QEAA@XZ
|
||||
; CHECK: __cdecl klass::klass(void)
|
||||
|
||||
??1klass@@QEAA@XZ
|
||||
; CHECK: __cdecl klass::~klass(void)
|
||||
|
||||
?x@@YAHPEAVklass@@AEAV1@@Z
|
||||
; CHECK: int __cdecl x(class klass *, class klass &)
|
||||
|
||||
?x@ns@@3PEAV?$klass@HH@1@EA
|
||||
; CHECK: class ns::klass<int, int> *ns::x
|
||||
|
||||
?fn@?$klass@H@ns@@QEBAIXZ
|
||||
; CHECK: unsigned int __cdecl ns::klass<int>::fn(void) const
|
||||
|
||||
|
||||
??4klass@@QEAAAEBV0@AEBV0@@Z
|
||||
; CHECK: class klass const &__cdecl klass::operator=(class klass const &)
|
||||
|
||||
??7klass@@QEAA_NXZ
|
||||
; CHECK: bool __cdecl klass::operator!(void)
|
||||
|
||||
??8klass@@QEAA_NAEBV0@@Z
|
||||
; CHECK: bool __cdecl klass::operator==(class klass const &)
|
||||
|
||||
??9klass@@QEAA_NAEBV0@@Z
|
||||
; CHECK: bool __cdecl klass::operator!=(class klass const &)
|
||||
|
||||
??Aklass@@QEAAH_K@Z
|
||||
; CHECK: int __cdecl klass::operator[](unsigned __int64)
|
||||
|
||||
??Cklass@@QEAAHXZ
|
||||
; CHECK: int __cdecl klass::operator->(void)
|
||||
|
||||
??Dklass@@QEAAHXZ
|
||||
; CHECK: int __cdecl klass::operator*(void)
|
||||
|
||||
??Eklass@@QEAAHXZ
|
||||
; CHECK: int __cdecl klass::operator++(void)
|
||||
|
||||
??Eklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator++(int)
|
||||
|
||||
??Fklass@@QEAAHXZ
|
||||
; CHECK: int __cdecl klass::operator--(void)
|
||||
|
||||
??Fklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator--(int)
|
||||
|
||||
??Hklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator+(int)
|
||||
|
||||
??Gklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator-(int)
|
||||
|
||||
??Iklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator&(int)
|
||||
|
||||
??Jklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator->*(int)
|
||||
|
||||
??Kklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator/(int)
|
||||
|
||||
??Mklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator<(int)
|
||||
|
||||
??Nklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator<=(int)
|
||||
|
||||
??Oklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator>(int)
|
||||
|
||||
??Pklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator>=(int)
|
||||
|
||||
??Qklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator,(int)
|
||||
|
||||
??Rklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator()(int)
|
||||
|
||||
??Sklass@@QEAAHXZ
|
||||
; CHECK: int __cdecl klass::operator~(void)
|
||||
|
||||
??Tklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator^(int)
|
||||
|
||||
??Uklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator|(int)
|
||||
|
||||
??Vklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator&&(int)
|
||||
|
||||
??Wklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator||(int)
|
||||
|
||||
??Xklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator*=(int)
|
||||
|
||||
??Yklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator+=(int)
|
||||
|
||||
??Zklass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator-=(int)
|
||||
|
||||
??_0klass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator/=(int)
|
||||
|
||||
??_1klass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator%=(int)
|
||||
|
||||
??_2klass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator>>=(int)
|
||||
|
||||
??_3klass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator<<=(int)
|
||||
|
||||
??_6klass@@QEAAHH@Z
|
||||
; CHECK: int __cdecl klass::operator^=(int)
|
||||
|
||||
??6@YAAEBVklass@@AEBV0@H@Z
|
||||
; CHECK: class klass const &__cdecl operator<<(class klass const &, int)
|
||||
|
||||
??5@YAAEBVklass@@AEBV0@_K@Z
|
||||
; CHECK: class klass const &__cdecl operator>>(class klass const &, unsigned __int64)
|
||||
|
||||
??2@YAPEAX_KAEAVklass@@@Z
|
||||
; CHECK: void *__cdecl operator new(unsigned __int64, class klass &)
|
||||
|
||||
??_U@YAPEAX_KAEAVklass@@@Z
|
||||
; CHECK: void *__cdecl operator new[](unsigned __int64, class klass &)
|
||||
|
||||
??3@YAXPEAXAEAVklass@@@Z
|
||||
; CHECK: void __cdecl operator delete(void *, class klass &)
|
||||
|
||||
??_V@YAXPEAXAEAVklass@@@Z
|
||||
; CHECK: void __cdecl operator delete[](void *, class klass &)
|
||||
|
363
test/Demangle/ms-mangle.test
Normal file
363
test/Demangle/ms-mangle.test
Normal file
@ -0,0 +1,363 @@
|
||||
; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
|
||||
; RUN: llvm-undname < %s | FileCheck %s
|
||||
|
||||
; CHECK-NOT: Invalid mangled name
|
||||
|
||||
?k@@3PTfoo@@DT1
|
||||
|
||||
|
||||
?a@@3HA
|
||||
; CHECK: int a
|
||||
|
||||
?b@N@@3HA
|
||||
; CHECK: int N::b
|
||||
|
||||
?anonymous@?A@N@@3HA
|
||||
; CHECK: int N::`anonymous namespace'::anonymous
|
||||
|
||||
?_c@@YAHXZ
|
||||
; CHECK: int __cdecl _c(void)
|
||||
|
||||
?d@foo@@0FB
|
||||
; CHECK: static short const foo::d
|
||||
|
||||
?e@foo@@1JC
|
||||
; CHECK: static long volatile foo::e
|
||||
|
||||
?f@foo@@2DD
|
||||
; CHECK: static char const volatile foo::f
|
||||
|
||||
??0foo@@QAE@XZ
|
||||
; CHECK: __thiscall foo::foo(void)
|
||||
|
||||
??0foo@@QEAA@XZ
|
||||
; CHECK: __cdecl foo::foo(void)
|
||||
|
||||
??1foo@@QAE@XZ
|
||||
; CHECK: __thiscall foo::~foo(void)
|
||||
|
||||
??1foo@@QEAA@XZ
|
||||
; CHECK: __cdecl foo::~foo(void)
|
||||
|
||||
??0foo@@QAE@H@Z
|
||||
; CHECK: __thiscall foo::foo(int)
|
||||
|
||||
??0foo@@QEAA@H@Z
|
||||
; CHECK: __cdecl foo::foo(int)
|
||||
|
||||
??0foo@@QAE@PAD@Z
|
||||
; CHECK: __thiscall foo::foo(char *)
|
||||
|
||||
??0foo@@QEAA@PEAD@Z
|
||||
; CHECK: __cdecl foo::foo(char *)
|
||||
|
||||
?bar@@YA?AVfoo@@XZ
|
||||
; CHECK: class foo __cdecl bar(void)
|
||||
|
||||
?bar@@YA?AVfoo@@XZ
|
||||
; CHECK: class foo __cdecl bar(void)
|
||||
|
||||
??Hfoo@@QAEHH@Z
|
||||
; CHECK: int __thiscall foo::operator+(int)
|
||||
|
||||
??Hfoo@@QEAAHH@Z
|
||||
; CHECK: int __cdecl foo::operator+(int)
|
||||
|
||||
?static_method@foo@@SAPAV1@XZ
|
||||
; CHECK: static class foo *__cdecl foo::static_method(void)
|
||||
|
||||
?static_method@foo@@SAPEAV1@XZ
|
||||
; CHECK: static class foo *__cdecl foo::static_method(void)
|
||||
|
||||
?g@bar@@2HA
|
||||
; CHECK: static int bar::g
|
||||
|
||||
; undname returns `int *h1`, but it is a bug in their demangler. Their mangler
|
||||
; correctly mangles `int *h1` as ?h1@3PAHA and `int * const h1` as ?h1@3QAHA
|
||||
?h1@@3QAHA
|
||||
; CHECK: int *const h1
|
||||
|
||||
?h2@@3QBHB
|
||||
; CHECK: int const *const h2
|
||||
|
||||
?h3@@3QIAHIA
|
||||
; CHECK: int * __restrict const h3
|
||||
|
||||
?h3@@3QEIAHEIA
|
||||
; CHECK: int * __restrict const h3
|
||||
|
||||
?i@@3PAY0BE@HA
|
||||
; CHECK: int (*i)[20]
|
||||
|
||||
?FunArr@@3PAY0BE@P6AHHH@ZA
|
||||
; CHECK: int __cdecl (*(*FunArr)[20])(int, int)
|
||||
|
||||
?j@@3P6GHCE@ZA
|
||||
; CHECK: int __stdcall (*j)(signed char, unsigned char)
|
||||
|
||||
|
||||
; FIXME: We don't handle member pointers yet.
|
||||
; ?k@@3PTfoo@@DT1
|
||||
; FIXME: char const volatile foo::*k
|
||||
|
||||
; ?k@@3PETfoo@@DET1
|
||||
; FIXME: char const volatile foo::*k
|
||||
|
||||
; ?l@@3P8foo@@AEHH@ZQ1
|
||||
; FIXME: int __thiscall (foo::*l)(int)
|
||||
|
||||
?g_cInt@@3HB
|
||||
; CHECK: int const g_cInt
|
||||
|
||||
?g_vInt@@3HC
|
||||
; CHECK: int volatile g_vInt
|
||||
|
||||
?g_cvInt@@3HD
|
||||
; CHECK: int const volatile g_cvInt
|
||||
|
||||
?beta@@YI_N_J_W@Z
|
||||
; CHECK: bool __fastcall beta(__int64, wchar_t)
|
||||
|
||||
?beta@@YA_N_J_W@Z
|
||||
; CHECK: bool __cdecl beta(__int64, wchar_t)
|
||||
|
||||
?alpha@@YGXMN@Z
|
||||
; CHECK: void __stdcall alpha(float, double)
|
||||
|
||||
?alpha@@YAXMN@Z
|
||||
; CHECK: void __cdecl alpha(float, double)
|
||||
|
||||
?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
|
||||
; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
|
||||
|
||||
?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
|
||||
; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
|
||||
|
||||
?delta@@YAXQAHABJ@Z
|
||||
; CHECK: void __cdecl delta(int *const, long const &)
|
||||
|
||||
?delta@@YAXQEAHAEBJ@Z
|
||||
; CHECK: void __cdecl delta(int *const, long const &)
|
||||
|
||||
?epsilon@@YAXQAY19BE@H@Z
|
||||
; CHECK: void __cdecl epsilon(int (*const)[10][20])
|
||||
|
||||
?epsilon@@YAXQEAY19BE@H@Z
|
||||
; CHECK: void __cdecl epsilon(int (*const)[10][20])
|
||||
|
||||
?zeta@@YAXP6AHHH@Z@Z
|
||||
; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
|
||||
|
||||
?zeta@@YAXP6AHHH@Z@Z
|
||||
; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
|
||||
|
||||
??2@YAPAXI@Z
|
||||
; CHECK: void *__cdecl operator new(unsigned int)
|
||||
|
||||
??3@YAXPAX@Z
|
||||
; CHECK: void __cdecl operator delete(void *)
|
||||
|
||||
??_U@YAPAXI@Z
|
||||
; CHECK: void *__cdecl operator new[](unsigned int)
|
||||
|
||||
??_V@YAXPAX@Z
|
||||
; CHECK: void __cdecl operator delete[](void *)
|
||||
|
||||
?color1@@3PANA
|
||||
; CHECK: double *color1
|
||||
|
||||
?color2@@3QBNB
|
||||
; CHECK: double const *const color2
|
||||
|
||||
; FIXME-EXTRACONST: These tests fails because we print an extra const inside the parens.
|
||||
; ?color3@@3QAY02$$CBNA
|
||||
; FIXME-EXTRACONST: double const (*color3)[3]
|
||||
|
||||
; ?color4@@3QAY02$$CBNA
|
||||
; FIXME-EXTRACONST: double const (*color4)[3]
|
||||
|
||||
; FIXME-MEMBERPTR: We don't support member pointers yet.
|
||||
; ?memptr1@@3RESB@@HES1
|
||||
; FIXME-MEMBERPTR: volatile int B::*memptr2
|
||||
|
||||
; ?memptr2@@3PESB@@HES1
|
||||
; FIXME: volatile int B::*memptr2
|
||||
|
||||
; ?memptr3@@3REQB@@HEQ1
|
||||
; FIXME-MEMBERPTR: int B::* volatile memptr3
|
||||
|
||||
; ?funmemptr1@@3RESB@@R6AHXZES1
|
||||
; FIXME-MEMBERPTR: int __cdecl (* volatile B::* volatile funmemptr1)(void)
|
||||
|
||||
; ?funmemptr2@@3PESB@@R6AHXZES1
|
||||
; FIXME-MEMBERPTR: int __cdecl (* volatile B::*funmemptr2)(void)
|
||||
|
||||
; ?funmemptr3@@3REQB@@P6AHXZEQ1
|
||||
; FIXME-MEMBERPTR: int __cdecl (* B::*volatile funmemptr3)(void)
|
||||
|
||||
; ?memptrtofun1@@3R8B@@EAAXXZEQ1
|
||||
; FIXME-MEMBERPTR: void __cdecl (B::*volatile memptrtofun1)(void)
|
||||
|
||||
; ?memptrtofun2@@3P8B@@EAAXXZEQ1
|
||||
; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun2)(void)
|
||||
|
||||
; ?memptrtofun3@@3P8B@@EAAXXZEQ1
|
||||
; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun3)(void)
|
||||
|
||||
; ?memptrtofun4@@3R8B@@EAAHXZEQ1
|
||||
; FIXME-MEMBERPTR: int __cdecl (B::* volatile memptrtofun4)(void)
|
||||
|
||||
; ?memptrtofun5@@3P8B@@EAA?CHXZEQ1
|
||||
; FIXME-MEMBERPTR: int volatile __cdecl (B::*memptrtofun5)(void)
|
||||
|
||||
; ?memptrtofun6@@3P8B@@EAA?BHXZEQ1
|
||||
; FIXME-MEMBERPTR: int const __cdecl (B::*memptrtofun6)(void)
|
||||
|
||||
; ?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1
|
||||
; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*volatile memptrtofun7)(void))(void)
|
||||
|
||||
; ?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1
|
||||
; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*memptrtofun8)(void))(void)
|
||||
|
||||
; ?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1
|
||||
; FIXME-MEMBERPTR: int __cdecl(*(__cdecl B::*memptrtofun9)(void))(void)
|
||||
|
||||
|
||||
?fooE@@YA?AW4E@@XZ
|
||||
; CHECK: enum E __cdecl fooE(void)
|
||||
|
||||
?fooE@@YA?AW4E@@XZ
|
||||
; CHECK: enum E __cdecl fooE(void)
|
||||
|
||||
?fooX@@YA?AVX@@XZ
|
||||
; CHECK: class X __cdecl fooX(void)
|
||||
|
||||
?fooX@@YA?AVX@@XZ
|
||||
; CHECK: class X __cdecl fooX(void)
|
||||
|
||||
?s0@PR13182@@3PADA
|
||||
; CHECK: char *PR13182::s0
|
||||
|
||||
?s1@PR13182@@3PADA
|
||||
; CHECK: char *PR13182::s1
|
||||
|
||||
?s2@PR13182@@3QBDB
|
||||
; CHECK: char const *const PR13182::s2
|
||||
|
||||
?s3@PR13182@@3QBDB
|
||||
; CHECK: char const *const PR13182::s3
|
||||
|
||||
?s4@PR13182@@3RCDC
|
||||
; CHECK: char volatile *volatile PR13182::s4
|
||||
|
||||
?s5@PR13182@@3SDDD
|
||||
; CHECK: char const volatile *const volatile PR13182::s5
|
||||
|
||||
; undname adds an extra const in here, but it seems like their bug.
|
||||
?s6@PR13182@@3PBQBDB
|
||||
; CHECK: char const *const *PR13182::s6
|
||||
|
||||
; FIXME-EXTERNC: We don't properly support static locals in extern c functions yet.
|
||||
; ?local@?1??extern_c_func@@9@4HA
|
||||
; FIXME-EXTERNC: int `extern_c_func'::`2'::local
|
||||
|
||||
; ?local@?1??extern_c_func@@9@4HA
|
||||
; FIXME-EXTERNC: int `extern_c_func'::`2'::local
|
||||
|
||||
??2OverloadedNewDelete@@SAPAXI@Z
|
||||
; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned int)
|
||||
|
||||
|
||||
??_UOverloadedNewDelete@@SAPAXI@Z
|
||||
; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned int)
|
||||
|
||||
??3OverloadedNewDelete@@SAXPAX@Z
|
||||
; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
|
||||
|
||||
|
||||
??_VOverloadedNewDelete@@SAXPAX@Z
|
||||
; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
|
||||
|
||||
??HOverloadedNewDelete@@QAEHH@Z
|
||||
; CHECK: int __thiscall OverloadedNewDelete::operator+(int)
|
||||
|
||||
??2OverloadedNewDelete@@SAPEAX_K@Z
|
||||
; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned __int64)
|
||||
|
||||
??_UOverloadedNewDelete@@SAPEAX_K@Z
|
||||
; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned __int64)
|
||||
|
||||
??3OverloadedNewDelete@@SAXPEAX@Z
|
||||
; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
|
||||
|
||||
|
||||
??_VOverloadedNewDelete@@SAXPEAX@Z
|
||||
; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
|
||||
|
||||
??HOverloadedNewDelete@@QEAAHH@Z
|
||||
; CHECK: int __cdecl OverloadedNewDelete::operator+(int)
|
||||
|
||||
|
||||
??2TypedefNewDelete@@SAPAXI@Z
|
||||
; CHECK: static void *__cdecl TypedefNewDelete::operator new(unsigned int)
|
||||
|
||||
|
||||
??_UTypedefNewDelete@@SAPAXI@Z
|
||||
; CHECK: static void *__cdecl TypedefNewDelete::operator new[](unsigned int)
|
||||
|
||||
??3TypedefNewDelete@@SAXPAX@Z
|
||||
; CHECK: static void __cdecl TypedefNewDelete::operator delete(void *)
|
||||
|
||||
??_VTypedefNewDelete@@SAXPAX@Z
|
||||
; CHECK: static void __cdecl TypedefNewDelete::operator delete[](void *)
|
||||
|
||||
?vector_func@@YQXXZ
|
||||
; CHECK: void __vectorcall vector_func(void)
|
||||
|
||||
; FIXME-EXTERNC: We don't support extern C funcs currently.
|
||||
; ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ
|
||||
; FIXME-EXTERNC: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)
|
||||
|
||||
; ?overloaded_fn@@$$J0YAXXZ
|
||||
; FIXME-EXTERNC: extern \"C\" void __cdecl overloaded_fn(void)
|
||||
|
||||
|
||||
?f@UnnamedType@@YAXUT2@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
|
||||
|
||||
?f@UnnamedType@@YAXPAUT4@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4 *)
|
||||
|
||||
?f@UnnamedType@@YAXUT4@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
|
||||
|
||||
?f@UnnamedType@@YAXUT5@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
|
||||
|
||||
?f@UnnamedType@@YAXUT2@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
|
||||
|
||||
?f@UnnamedType@@YAXUT4@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
|
||||
|
||||
?f@UnnamedType@@YAXUT5@S@1@@Z
|
||||
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
|
||||
|
||||
?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z
|
||||
; CHECK: void __cdecl Atomic::f(struct __clang::_Atomic<int>)
|
||||
|
||||
?f@Complex@@YAXU?$_Complex@H@__clang@@@Z
|
||||
; CHECK: void __cdecl Complex::f(struct __clang::_Complex<int>)
|
||||
|
||||
?f@Float16@@YAXU_Float16@__clang@@@Z
|
||||
; CHECK: void __cdecl Float16::f(struct __clang::_Float16)
|
||||
|
||||
|
||||
??0?$L@H@NS@@QEAA@XZ
|
||||
; CHECK: __cdecl NS::L<int>::L<int>(void)
|
||||
|
||||
??0Bar@Foo@@QEAA@XZ
|
||||
; CHECK: __cdecl Foo::Bar::Bar(void)
|
||||
|
||||
??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ
|
||||
; CHECK: __thiscall PR26029::L<class PR26029::H<int *>>::L<class PR26029::H<int *>>(void)
|
17
test/Demangle/ms-windows.test
Normal file
17
test/Demangle/ms-windows.test
Normal file
@ -0,0 +1,17 @@
|
||||
; See clang/test/CodeGenCXX/mangle-windows.cpp
|
||||
; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
|
||||
; RUN: llvm-undname < %s | FileCheck %s
|
||||
|
||||
; CHECK-NOT: Invalid mangled name
|
||||
|
||||
?bar@Foo@@SGXXZ
|
||||
; CHECK: static void __stdcall Foo::bar(void)
|
||||
|
||||
?bar@Foo@@QAGXXZ
|
||||
; CHECK: void __stdcall Foo::bar(void)
|
||||
|
||||
?f2@@YIXXZ
|
||||
; CHECK: void __fastcall f2(void)
|
||||
|
||||
?f1@@YGXXZ
|
||||
; CHECK: void __stdcall f1(void)
|
@ -50,6 +50,7 @@ subdirectories =
|
||||
llvm-rtdyld
|
||||
llvm-size
|
||||
llvm-split
|
||||
llvm-undname
|
||||
opt
|
||||
verify-uselistorder
|
||||
|
||||
|
8
tools/llvm-undname/CMakeLists.txt
Normal file
8
tools/llvm-undname/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Demangle
|
||||
Support
|
||||
)
|
||||
|
||||
add_llvm_tool(llvm-undname
|
||||
llvm-undname.cpp
|
||||
)
|
23
tools/llvm-undname/LLVMBuild.txt
Normal file
23
tools/llvm-undname/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===- ./tools/llvm-undname/LLVMBuild.txt -----------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Tool
|
||||
name = llvm-undname
|
||||
parent = Tools
|
||||
required_libraries = Demangle Support
|
||||
|
79
tools/llvm-undname/llvm-undname.cpp
Normal file
79
tools/llvm-undname/llvm-undname.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
//===-- llvm-undname.cpp - Microsoft ABI name undecorator
|
||||
//------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This utility works like the windows undname utility. It converts mangled
|
||||
// Microsoft symbol names into pretty C/C++ human-readable names.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
cl::list<std::string> Symbols(cl::Positional, cl::desc("<input symbols>"),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static void demangle(const std::string &S) {
|
||||
int Status;
|
||||
char *ResultBuf = microsoftDemangle(S.c_str(), nullptr, nullptr, &Status);
|
||||
if (Status == llvm::demangle_success) {
|
||||
outs() << ResultBuf << "\n";
|
||||
outs().flush();
|
||||
} else {
|
||||
errs() << "Error: Invalid mangled name\n";
|
||||
}
|
||||
std::free(ResultBuf);
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
InitLLVM X(argc, argv);
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv, "llvm-undname\n");
|
||||
|
||||
if (Symbols.empty()) {
|
||||
while (true) {
|
||||
std::string LineStr;
|
||||
std::getline(std::cin, LineStr);
|
||||
if (std::cin.eof())
|
||||
break;
|
||||
|
||||
StringRef Line(LineStr);
|
||||
Line = Line.trim();
|
||||
if (Line.empty() || Line.startswith("#") || Line.startswith(";"))
|
||||
continue;
|
||||
|
||||
// If the user is manually typing in these decorated names, don't echo
|
||||
// them to the terminal a second time. If they're coming from redirected
|
||||
// input, however, then we should display the input line so that the
|
||||
// mangled and demangled name can be easily correlated in the output.
|
||||
if (!sys::Process::StandardInIsUserInput())
|
||||
outs() << Line << "\n";
|
||||
demangle(Line);
|
||||
outs() << "\n";
|
||||
}
|
||||
} else {
|
||||
for (StringRef S : Symbols) {
|
||||
outs() << S << "\n";
|
||||
demangle(S);
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user