summaryrefslogtreecommitdiffstats
path: root/test/SemaCXX/calling-conv-compat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX/calling-conv-compat.cpp')
-rw-r--r--test/SemaCXX/calling-conv-compat.cpp387
1 files changed, 387 insertions, 0 deletions
diff --git a/test/SemaCXX/calling-conv-compat.cpp b/test/SemaCXX/calling-conv-compat.cpp
new file mode 100644
index 0000000..2d52386
--- /dev/null
+++ b/test/SemaCXX/calling-conv-compat.cpp
@@ -0,0 +1,387 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -cxx-abi microsoft -verify -triple i686-pc-win32 %s
+
+// Pointers to free functions
+void free_func_default();
+void __cdecl free_func_cdecl();
+void __stdcall free_func_stdcall();
+void __fastcall free_func_fastcall();
+
+typedef void ( *fptr_default)();
+typedef void (__cdecl *fptr_cdecl)();
+typedef void (__stdcall *fptr_stdcall)();
+typedef void (__fastcall *fptr_fastcall)();
+
+// expected-note@+4 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}}
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((stdcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((fastcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}}
+void cb_fptr_default(fptr_default ptr);
+// expected-note@+4 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}}
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((stdcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((fastcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}}
+void cb_fptr_cdecl(fptr_cdecl ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}}
+void cb_fptr_stdcall(fptr_stdcall ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}}
+void cb_fptr_fastcall(fptr_fastcall ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'const fptr_default' (aka 'void (*const)()') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'const fptr_default' (aka 'void (*const)()') for 1st argument}}
+void cb_fptr_const_default(const fptr_default ptr);
+
+void call_free_func() {
+ cb_fptr_default(free_func_default);
+ cb_fptr_default(free_func_cdecl);
+ cb_fptr_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_default'}}
+ cb_fptr_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_default'}}
+ cb_fptr_default(&free_func_default);
+ cb_fptr_default(&free_func_cdecl);
+ cb_fptr_default(&free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_default'}}
+ cb_fptr_default(&free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_default'}}
+
+ cb_fptr_cdecl(free_func_default);
+ cb_fptr_cdecl(free_func_cdecl);
+ cb_fptr_cdecl(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}}
+ cb_fptr_cdecl(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}}
+ cb_fptr_cdecl(&free_func_default);
+ cb_fptr_cdecl(&free_func_cdecl);
+ cb_fptr_cdecl(&free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}}
+ cb_fptr_cdecl(&free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}}
+
+ cb_fptr_stdcall(free_func_default); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}}
+ cb_fptr_stdcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}}
+ cb_fptr_stdcall(free_func_stdcall);
+ cb_fptr_stdcall(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}}
+
+ cb_fptr_fastcall(free_func_default); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}}
+ cb_fptr_fastcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}}
+ cb_fptr_fastcall(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}}
+ cb_fptr_fastcall(free_func_fastcall);
+
+ cb_fptr_const_default(free_func_default);
+ cb_fptr_const_default(free_func_cdecl);
+ cb_fptr_const_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_const_default'}}
+ cb_fptr_const_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_const_default'}}
+
+}
+
+// Pointers to variadic functions
+// variadic function can't declared stdcall or fastcall
+void free_func_variadic_default(int, ...);
+void __cdecl free_func_variadic_cdecl(int, ...);
+
+typedef void ( *fptr_variadic_default)(int, ...);
+typedef void (__cdecl *fptr_variadic_cdecl)(int, ...);
+
+void cb_fptr_variadic_default(fptr_variadic_default ptr);
+void cb_fptr_variadic_cdecl(fptr_variadic_cdecl ptr);
+
+void call_free_variadic_func() {
+ cb_fptr_variadic_default(free_func_variadic_default);
+ cb_fptr_variadic_default(free_func_variadic_cdecl);
+ cb_fptr_variadic_default(&free_func_variadic_default);
+ cb_fptr_variadic_default(&free_func_variadic_cdecl);
+
+ cb_fptr_variadic_cdecl(free_func_variadic_default);
+ cb_fptr_variadic_cdecl(free_func_variadic_cdecl);
+ cb_fptr_variadic_cdecl(&free_func_variadic_default);
+ cb_fptr_variadic_cdecl(&free_func_variadic_cdecl);
+}
+
+// References to functions
+typedef void ( &fref_default)();
+typedef void (__cdecl &fref_cdecl)();
+typedef void (__stdcall &fref_stdcall)();
+typedef void (__fastcall &fref_fastcall)();
+
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_default' (aka 'void (&)()') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_default' (aka 'void (&)()') for 1st argument}}
+void cb_fref_default(fref_default ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_cdecl' (aka 'void (&)()') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_cdecl' (aka 'void (&)()') for 1st argument}}
+void cb_fref_cdecl(fref_cdecl ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}}
+void cb_fref_stdcall(fref_stdcall ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}}
+void cb_fref_fastcall(fref_fastcall ptr);
+
+void call_free_func_ref() {
+ cb_fref_default(free_func_default);
+ cb_fref_default(free_func_cdecl);
+ cb_fref_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_default'}}
+ cb_fref_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_default'}}
+
+ cb_fref_cdecl(free_func_default);
+ cb_fref_cdecl(free_func_cdecl);
+ cb_fref_cdecl(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_cdecl'}}
+ cb_fref_cdecl(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_cdecl'}}
+
+ cb_fref_stdcall(free_func_default); // expected-error {{no matching function for call to 'cb_fref_stdcall'}}
+ cb_fref_stdcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fref_stdcall'}}
+ cb_fref_stdcall(free_func_stdcall);
+ cb_fref_stdcall(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_stdcall'}}
+
+ cb_fref_fastcall(free_func_default); // expected-error {{no matching function for call to 'cb_fref_fastcall'}}
+ cb_fref_fastcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fref_fastcall'}}
+ cb_fref_fastcall(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_fastcall'}}
+ cb_fref_fastcall(free_func_fastcall);
+}
+
+// References to variadic functions
+// variadic function can't declared stdcall or fastcall
+typedef void ( &fref_variadic_default)(int, ...);
+typedef void (__cdecl &fref_variadic_cdecl)(int, ...);
+
+void cb_fref_variadic_default(fptr_variadic_default ptr);
+void cb_fref_variadic_cdecl(fptr_variadic_cdecl ptr);
+
+void call_free_variadic_func_ref() {
+ cb_fref_variadic_default(free_func_variadic_default);
+ cb_fref_variadic_default(free_func_variadic_cdecl);
+
+ cb_fref_variadic_cdecl(free_func_variadic_default);
+ cb_fref_variadic_cdecl(free_func_variadic_cdecl);
+}
+
+// Pointers to members
+namespace NonVariadic {
+
+struct A {
+ void member_default();
+ void __cdecl member_cdecl();
+ void __thiscall member_thiscall();
+};
+
+struct B : public A {
+};
+
+struct C {
+ void member_default();
+ void __cdecl member_cdecl();
+ void __thiscall member_thiscall();
+};
+
+typedef void ( A::*memb_a_default)();
+typedef void (__cdecl A::*memb_a_cdecl)();
+typedef void (__thiscall A::*memb_a_thiscall)();
+typedef void ( B::*memb_b_default)();
+typedef void (__cdecl B::*memb_b_cdecl)();
+typedef void (__thiscall B::*memb_b_thiscall)();
+typedef void ( C::*memb_c_default)();
+typedef void (__cdecl C::*memb_c_cdecl)();
+typedef void (__thiscall C::*memb_c_thiscall)();
+
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_a_default(memb_a_default ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}}
+void cb_memb_a_cdecl(memb_a_cdecl ptr);
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_a_thiscall(memb_a_thiscall ptr);
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_b_default(memb_b_default ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}}
+void cb_memb_b_cdecl(memb_b_cdecl ptr);
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_b_thiscall(memb_b_thiscall ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_c_default(memb_c_default ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}}
+void cb_memb_c_cdecl(memb_c_cdecl ptr);
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}}
+void cb_memb_c_thiscall(memb_c_thiscall ptr);
+
+void call_member() {
+ cb_memb_a_default(&A::member_default);
+ cb_memb_a_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_a_default'}}
+ cb_memb_a_default(&A::member_thiscall);
+
+ cb_memb_a_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_a_cdecl'}}
+ cb_memb_a_cdecl(&A::member_cdecl);
+ cb_memb_a_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_a_cdecl'}}
+
+ cb_memb_a_thiscall(&A::member_default);
+ cb_memb_a_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_a_thiscall'}}
+ cb_memb_a_thiscall(&A::member_thiscall);
+}
+
+void call_member_inheritance() {
+ cb_memb_b_default(&A::member_default);
+ cb_memb_b_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_b_default'}}
+ cb_memb_b_default(&A::member_thiscall);
+ cb_memb_c_default(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_default'}}
+ cb_memb_c_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_default'}}
+ cb_memb_c_default(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_default'}}
+
+ cb_memb_b_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_b_cdecl'}}
+ cb_memb_b_cdecl(&A::member_cdecl);
+ cb_memb_b_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_b_cdecl'}}
+ cb_memb_c_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}}
+ cb_memb_c_cdecl(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}}
+ cb_memb_c_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}}
+
+ cb_memb_b_thiscall(&A::member_default);
+ cb_memb_b_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_b_thiscall'}}
+ cb_memb_b_thiscall(&A::member_thiscall);
+ cb_memb_c_thiscall(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}}
+ cb_memb_c_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}}
+ cb_memb_c_thiscall(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}}
+}
+} // end namespace NonVariadic
+
+namespace Variadic {
+struct A {
+ void member_default(int, ...);
+ void __cdecl member_cdecl(int, ...);
+ void __thiscall member_thiscall(int, ...); // expected-error {{variadic function cannot use thiscall calling convention}}
+};
+
+struct B : public A {
+};
+
+struct C {
+ void member_default(int, ...);
+ void __cdecl member_cdecl(int, ...);
+};
+
+typedef void ( A::*memb_a_default)(int, ...);
+typedef void (__cdecl A::*memb_a_cdecl)(int, ...);
+typedef void ( B::*memb_b_default)(int, ...);
+typedef void (__cdecl B::*memb_b_cdecl)(int, ...);
+typedef void ( C::*memb_c_default)(int, ...);
+typedef void (__cdecl C::*memb_c_cdecl)(int, ...);
+
+void cb_memb_a_default(memb_a_default ptr);
+void cb_memb_a_cdecl(memb_a_cdecl ptr);
+void cb_memb_b_default(memb_b_default ptr);
+void cb_memb_b_cdecl(memb_b_cdecl ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}}
+void cb_memb_c_default(memb_c_default ptr);
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+void cb_memb_c_cdecl(memb_c_cdecl ptr);
+
+void call_member() {
+ cb_memb_a_default(&A::member_default);
+ cb_memb_a_default(&A::member_cdecl);
+
+ cb_memb_a_cdecl(&A::member_default);
+ cb_memb_a_cdecl(&A::member_cdecl);
+}
+
+void call_member_inheritance() {
+ cb_memb_b_default(&A::member_default);
+ cb_memb_b_default(&A::member_cdecl);
+ cb_memb_c_default(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_default'}}
+ cb_memb_c_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_default'}}
+
+ cb_memb_b_cdecl(&A::member_default);
+ cb_memb_b_cdecl(&A::member_cdecl);
+ cb_memb_c_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}}
+ cb_memb_c_cdecl(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}}
+}
+} // end namespace Variadic
+
+namespace MultiChunkDecls {
+
+// Try to test declarators that have multiple DeclaratorChunks.
+struct A {
+ void __thiscall member_thiscall(int);
+};
+
+void (A::*return_mptr(short))(int) {
+ return &A::member_thiscall;
+}
+
+void (A::*(*return_fptr_mptr(char))(short))(int) {
+ return return_mptr;
+}
+
+typedef void (A::*mptr_t)(int);
+mptr_t __stdcall return_mptr_std(short) {
+ return &A::member_thiscall;
+}
+
+void (A::*(*return_fptr_std_mptr(char))(short))(int) {
+ return return_mptr_std; // expected-error {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'mptr_t (short) __attribute__((stdcall))'}}
+}
+
+void call_return() {
+ A o;
+ void (A::*(*fptr)(short))(int) = return_fptr_mptr('a');
+ void (A::*mptr)(int) = fptr(1);
+ (o.*mptr)(2);
+}
+
+} // end namespace MultiChunkDecls
+
+namespace MemberPointers {
+
+struct A {
+ void __thiscall method_thiscall();
+ void __cdecl method_cdecl();
+ void __stdcall method_stdcall();
+ void __fastcall method_fastcall();
+};
+
+void ( A::*mp1)() = &A::method_thiscall;
+void (__cdecl A::*mp2)() = &A::method_cdecl;
+void (__stdcall A::*mp3)() = &A::method_stdcall;
+void (__fastcall A::*mp4)() = &A::method_fastcall;
+
+// Use a typedef to form the member pointer and verify that cdecl is adjusted.
+typedef void ( fun_default)();
+typedef void (__cdecl fun_cdecl)();
+typedef void (__stdcall fun_stdcall)();
+typedef void (__fastcall fun_fastcall)();
+
+// FIXME: Adjust cdecl to thiscall when forming a member pointer.
+//fun_default A::*td1 = &A::method_thiscall;
+fun_cdecl A::*td2 = &A::method_cdecl;
+fun_stdcall A::*td3 = &A::method_stdcall;
+fun_fastcall A::*td4 = &A::method_fastcall;
+
+// Round trip the function type through a template, and verify that only cdecl
+// gets adjusted.
+template<typename Fn> struct X {
+ typedef Fn A::*p;
+};
+
+// FIXME: Adjust cdecl to thiscall when forming a member pointer.
+//X<void ()>::p tmpl1 = &A::method_thiscall;
+//X<void __cdecl ()>::p tmpl2 = &A::method_thiscall;
+X<void __stdcall ()>::p tmpl3 = &A::method_stdcall;
+X<void __fastcall ()>::p tmpl4 = &A::method_fastcall;
+
+} // end namespace MemberPointers
+
+// Test that lambdas that capture nothing convert to cdecl function pointers.
+namespace Lambdas {
+
+void pass_fptr_cdecl (void (__cdecl *fp)());
+void pass_fptr_stdcall (void (__stdcall *fp)()); // expected-note {{candidate function not viable}}
+void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note {{candidate function not viable}}
+
+void conversion_to_fptr() {
+ pass_fptr_cdecl ([]() { } );
+ pass_fptr_stdcall ([]() { } ); // expected-error {{no matching function for call}}
+ pass_fptr_fastcall([]() { } ); // expected-error {{no matching function for call}}
+}
+
+}
OpenPOWER on IntegriCloud