diff options
author | John McCall <rjmccall@apple.com> | 2012-08-25 01:12:56 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-08-25 01:12:56 +0000 |
commit | 2612e9f1d0a356a303097bea9faf53fdb213c50c (patch) | |
tree | a683a72e786b6a698a12558b5c6fa886b58c3307 | |
parent | 3682f1ea9c7fddc7dcbc590891158ba40f7fca16 (diff) |
Fix the mangling of function pointers in the MS ABI.
Patch by Timur Iskhodzhanov!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162638 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-ms-template-callback.cpp | 72 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-ms.cpp | 4 |
3 files changed, 82 insertions, 2 deletions
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index e2cee7f52c..7263190f46 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1059,6 +1059,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, SourceRange) { // Structors only appear in decls, so at this point we know it's not a // structor type. + // FIXME: This may not be lambda-friendly. + Out << "$$A6"; mangleType(T, NULL, false, false); } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, @@ -1214,7 +1216,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, if (CC == CC_Default) { if (IsInstMethod) { const FunctionProtoType *FPT = - T->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(); + T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>(); bool isVariadic = FPT->isVariadic(); CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic); } else { @@ -1497,7 +1499,9 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T, SourceRange Range) { Out << "_E"; - mangleType(T->getPointeeType(), Range); + + QualType pointee = T->getPointeeType(); + mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false); } void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T, diff --git a/test/CodeGenCXX/mangle-ms-template-callback.cpp b/test/CodeGenCXX/mangle-ms-template-callback.cpp new file mode 100644 index 0000000000..6878148751 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-template-callback.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s + +template<typename Signature> +class C; + +template<typename Ret> +class C<Ret(void)> {}; +typedef C<void(void)> C0; + +template<typename Ret, typename Arg1> +class C<Ret(Arg1)> {}; + +template<typename Ret, typename Arg1, typename Arg2> +class C<Ret(Arg1, Arg2)> {}; + +C0 callback_void; +// CHECK: "\01?callback_void@@3V?$C@$$A6AXXZ@@A" + +volatile C0 callback_void_volatile; +// CHECK: "\01?callback_void_volatile@@3V?$C@$$A6AXXZ@@C" + +class Type {}; + +C<int(void)> callback_int; +// CHECK: "\01?callback_int@@3V?$C@$$A6AHXZ@@A" +C<Type(void)> callback_Type; +// CHECK: "\01?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A" + +C<void(int)> callback_void_int; +// CHECK: "\01?callback_void_int@@3V?$C@$$A6AXH@Z@@A" +C<int(int)> callback_int_int; +// CHECK: "\01?callback_int_int@@3V?$C@$$A6AHH@Z@@A" +C<void(Type)> callback_void_Type; +// CHECK: "\01?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A" + +void foo(C0 c) {} +// CHECK: "\01?foo@@YAXV?$C@$$A6AXXZ@@@Z" + +// Here be dragons! +// Let's face the magic of template partial specialization... + +void function(C<void(void)>) {} +// CHECK: "\01?function@@YAXV?$C@$$A6AXXZ@@@Z" + +template<typename Ret> class C<Ret(*)(void)> {}; +void function_pointer(C<void(*)(void)>) {} +// CHECK: "\01?function_pointer@@YAXV?$C@P6AXXZ@@@Z" + +// Block equivalent to the previous definitions. +template<typename Ret> class C<Ret(^)(void)> {}; +void block(C<void(^)(void)>) {} +// CHECK: "\01?block@@YAXV?$C@P_EAXXZ@@@Z" +// FYI blocks are not present in MSVS, so we're free to choose the spec. + +template<typename T> class C<void (T::*)(void)> {}; +class Z { + public: + void method() {} +}; +void member_pointer(C<void (Z::*)(void)>) {} +// CHECK: "\01?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z" + +template<typename T> void bar(T) {} + +void call_bar() { + bar<int (*)(int)>(0); +// CHECK: "\01??$bar@P6AHH@Z@@YAXP6AHH@Z@Z" + + bar<int (^)(int)>(0); +// CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z" +// FYI blocks are not present in MSVS, so we're free to choose the spec. +} diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index f392c1701e..ef210f54cd 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -128,6 +128,10 @@ void zeta(int (*)(int, int)) {} void eta(int (^)(int, int)) {} // CHECK: @"\01?eta@@YAXP_EAHHH@Z@Z" +typedef int theta_arg(int,int); +void theta(theta_arg^ block) {} +// CHECK: @"\01?theta@@YAXP_EAHHH@Z@Z" + void operator_new_delete() { char *ptr = new char; // CHECK: @"\01??2@YAPAXI@Z" |