diff options
Diffstat (limited to 'test/SemaCXX/decl-microsoft-call-conv.cpp')
-rw-r--r-- | test/SemaCXX/decl-microsoft-call-conv.cpp | 143 |
1 files changed, 125 insertions, 18 deletions
diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index 3175af7..9f14632 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -1,21 +1,24 @@ // RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -fms-extensions -verify %s +typedef void void_fun_t(); +typedef void __cdecl cdecl_fun_t(); + // Pointers to free functions -void free_func_default(); -void __cdecl free_func_cdecl(); -void __stdcall free_func_stdcall(); // expected-note {{previous declaration is here}} +void free_func_default(); // expected-note 2 {{previous declaration is here}} +void __cdecl free_func_cdecl(); // expected-note 2 {{previous declaration is here}} +void __stdcall free_func_stdcall(); // expected-note 2 {{previous declaration is here}} void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}} -void __cdecl free_func_default(); // expected-note 2 {{previous declaration is here}} +void __cdecl free_func_default(); void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}} -void free_func_cdecl(); // expected-note 2 {{previous declaration is here}} +void free_func_cdecl(); void __stdcall free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}} +void free_func_stdcall(); void __cdecl free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}} -void free_func_stdcall(); // expected-note {{previous declaration is here}} void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}} void __cdecl free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}} @@ -29,6 +32,8 @@ void __cdecl free_func_default(int *); void __thiscall free_func_cdecl(char *); void __cdecl free_func_cdecl(double); +typedef void void_fun_t(); +typedef void __cdecl cdecl_fun_t(); // Pointers to member functions struct S { @@ -38,10 +43,17 @@ struct S { void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}} void __thiscall member_thiscall1(); void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}} - + + // Typedefs carrying the __cdecl convention are adjusted to __thiscall. + void_fun_t member_typedef_default; // expected-note {{previous declaration is here}} + cdecl_fun_t member_typedef_cdecl1; // expected-note {{previous declaration is here}} + cdecl_fun_t __cdecl member_typedef_cdecl2; + void_fun_t __stdcall member_typedef_stdcall; + // Static member functions can't be __thiscall static void static_member_default1(); - static void static_member_default2(); // expected-note {{previous declaration is here}} + static void static_member_default2(); + static void static_member_default3(); // expected-note {{previous declaration is here}} static void __cdecl static_member_cdecl1(); static void __cdecl static_member_cdecl2(); // expected-note {{previous declaration is here}} static void __stdcall static_member_stdcall1(); @@ -58,29 +70,124 @@ struct S { void __cdecl S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} void __thiscall S::member_default2() {} +void __cdecl S::member_typedef_default() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} +void __cdecl S::member_typedef_cdecl1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} +void __cdecl S::member_typedef_cdecl2() {} +void __stdcall S::member_typedef_stdcall() {} + void S::member_cdecl1() {} void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}} void S::member_thiscall1() {} void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}} -void __cdecl S::static_member_default1() {} -void __stdcall S::static_member_default2() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} +void S::static_member_default1() {} +void __cdecl S::static_member_default2() {} +void __stdcall S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} void S::static_member_cdecl1() {} void __stdcall S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} -void __cdecl S::member_variadic_default(int x, ...) { - (void)x; +void __cdecl S::member_variadic_default(int x, ...) { (void)x; } +void S::member_variadic_cdecl(int x, ...) { (void)x; } + +void __cdecl S::static_member_variadic_default(int x, ...) { (void)x; } +void S::static_member_variadic_cdecl(int x, ...) { (void)x; } + +// Declare a template using a calling convention. +template <class CharT> inline int __cdecl mystrlen(const CharT *str) { + int i; + for (i = 0; str[i]; i++) { } + return i; } -void S::member_variadic_cdecl(int x, ...) { - (void)x; +extern int sse_strlen(const char *str); +template <> inline int __cdecl mystrlen(const char *str) { + return sse_strlen(str); +} +void use_tmpl(const char *str, const int *ints) { + mystrlen(str); + mystrlen(ints); +} + +struct MixedCCStaticOverload { + static void overloaded(int a); + static void __stdcall overloaded(short a); +}; + +void MixedCCStaticOverload::overloaded(int a) {} +void MixedCCStaticOverload::overloaded(short a) {} + +// Friend function decls are cdecl by default, not thiscall. Friend method +// decls should always be redeclarations, because the class cannot be +// incomplete. +struct FriendClass { + void friend_method() {} +}; +void __stdcall friend_stdcall1() {} +class MakeFriendDecls { + int x; + friend void FriendClass::friend_method(); + friend void friend_default(); + friend void friend_stdcall1(); + friend void __stdcall friend_stdcall2(); + friend void friend_stdcall3(); // expected-note {{previous declaration is here}} +}; +void friend_default() {} +void __stdcall friend_stdcall3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} +void __stdcall friend_stdcall2() {} + +// Test functions with multiple attributes. +void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attribute(int x); +void multi_attribute(int x) { __builtin_unreachable(); } + + +// expected-error@+2 {{stdcall and cdecl attributes are not compatible}} +// expected-error@+1 {{fastcall and cdecl attributes are not compatible}} +void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x); + +template <typename T> void __stdcall StdcallTemplate(T) {} +template <> void StdcallTemplate<int>(int) {} +template <> void __stdcall StdcallTemplate<short>(short) {} + +// FIXME: Note the template, not the implicit instantiation. +// expected-error@+2 {{function declared 'cdecl' here was previously declared 'stdcall}} +// expected-note@+1 {{previous declaration is here}} +template <> void __cdecl StdcallTemplate<long>(long) {} + +struct ExactlyInt { + template <typename T> static int cast_to_int(T) { + return T::this_is_not_an_int(); + } +}; +template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; } + +namespace test2 { + class foo { + template <typename T> void bar(T v); + }; + extern template void foo::bar(const void *); } -void __cdecl S::static_member_variadic_default(int x, ...) { - (void)x; +namespace test3 { + struct foo { + typedef void bar(); + }; + bool zed(foo::bar *); + void bah() {} + void baz() { zed(bah); } } -void S::static_member_variadic_cdecl(int x, ...) { - (void)x; + +namespace test4 { + class foo { + template <typename T> static void bar(T v); + }; + extern template void foo::bar(const void *); } +namespace test5 { + template <class T> + class valarray { + void bar(); + }; + extern template void valarray<int>::bar(); +} |