266 lines · cpp
1// RUN: %clang_cc1 -std=c++14 -triple i686-pc-win32 -fms-extensions -DMSABI -verify %s2// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -verify %s3// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -fms-extensions -verify %s4 5typedef void void_fun_t();6typedef void __cdecl cdecl_fun_t();7 8// Pointers to free functions9void free_func_default(); // expected-note 2 {{previous declaration is here}}10void __cdecl free_func_cdecl(); // expected-note 2 {{previous declaration is here}}11void __stdcall free_func_stdcall(); // expected-note 2 {{previous declaration is here}}12void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}}13void __vectorcall free_func_vectorcall(); // expected-note 2 {{previous declaration is here}}14 15void __cdecl free_func_default();16void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}17void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}}18 19void free_func_cdecl();20void __stdcall free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}21void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}}22 23void free_func_stdcall();24void __cdecl free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}}25void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}}26 27void __cdecl free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}}28void __stdcall free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}}29void free_func_fastcall();30 31void __cdecl free_func_vectorcall(); // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}32void __stdcall free_func_vectorcall(); // expected-error {{function declared 'stdcall' here was previously declared 'vectorcall'}}33void free_func_vectorcall();34 35// Overloaded functions may have different calling conventions36void __fastcall free_func_default(int);37void __cdecl free_func_default(int *);38 39void __thiscall free_func_cdecl(char *);40void __cdecl free_func_cdecl(double);41 42typedef void void_fun_t();43typedef void __cdecl cdecl_fun_t();44 45// Pointers to member functions46struct S {47 void member_default1(); // expected-note {{previous declaration is here}}48 void member_default2();49 void __cdecl member_cdecl1();50 void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}}51 void __thiscall member_thiscall1();52 void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}}53 void __vectorcall member_vectorcall1();54 void __vectorcall member_vectorcall2(); // expected-note {{previous declaration is here}}55 56 // Typedefs carrying the __cdecl convention are adjusted to __thiscall.57 void_fun_t member_typedef_default; // expected-note {{previous declaration is here}}58 cdecl_fun_t member_typedef_cdecl1; // expected-note {{previous declaration is here}}59 cdecl_fun_t __cdecl member_typedef_cdecl2;60 void_fun_t __stdcall member_typedef_stdcall;61 62 // Static member functions can't be __thiscall63 static void static_member_default1();64 static void static_member_default2();65 static void static_member_default3(); // expected-note {{previous declaration is here}}66 static void __cdecl static_member_cdecl1();67 static void __cdecl static_member_cdecl2(); // expected-note {{previous declaration is here}}68 static void __stdcall static_member_stdcall1();69 static void __stdcall static_member_stdcall2();70 71 // Variadic functions can't be other than default or __cdecl72 void member_variadic_default(int x, ...);73 void __cdecl member_variadic_cdecl(int x, ...);74 75 static void static_member_variadic_default(int x, ...);76 static void __cdecl static_member_variadic_cdecl(int x, ...);77 78 // Structors can't be other than default in MS ABI environment79#ifdef MSABI80 __vectorcall S(); // expected-warning {{vectorcall calling convention is not supported on constructor/destructor}}81#endif82};83 84void __cdecl S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}85void __thiscall S::member_default2() {}86 87void __cdecl S::member_typedef_default() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}88void __cdecl S::member_typedef_cdecl1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}89void __cdecl S::member_typedef_cdecl2() {}90void __stdcall S::member_typedef_stdcall() {}91 92void S::member_cdecl1() {}93void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}}94 95void S::member_thiscall1() {}96void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}}97 98void S::member_vectorcall1() {}99void __cdecl S::member_vectorcall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}100 101void S::static_member_default1() {}102void __cdecl S::static_member_default2() {}103void __stdcall S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}104 105void S::static_member_cdecl1() {}106void __stdcall S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}107 108void __cdecl S::member_variadic_default(int x, ...) { (void)x; }109void S::member_variadic_cdecl(int x, ...) { (void)x; }110 111void __cdecl S::static_member_variadic_default(int x, ...) { (void)x; }112void S::static_member_variadic_cdecl(int x, ...) { (void)x; }113 114// Declare a template using a calling convention.115template <class CharT> inline int __cdecl mystrlen(const CharT *str) {116 int i;117 for (i = 0; str[i]; i++) { }118 return i;119}120extern int sse_strlen(const char *str);121template <> inline int __cdecl mystrlen(const char *str) {122 return sse_strlen(str);123}124void use_tmpl(const char *str, const int *ints) {125 mystrlen(str);126 mystrlen(ints);127}128 129struct MixedCCStaticOverload {130 static void overloaded(int a);131 static void __stdcall overloaded(short a);132};133 134void MixedCCStaticOverload::overloaded(int a) {}135void MixedCCStaticOverload::overloaded(short a) {}136 137// Friend function decls are cdecl by default, not thiscall. Friend method138// decls should always be redeclarations, because the class cannot be139// incomplete.140struct FriendClass {141 void friend_method() {}142};143void __stdcall friend_stdcall1() {}144class MakeFriendDecls {145 int x;146 friend void FriendClass::friend_method();147 friend void friend_default();148 friend void friend_stdcall1();149 friend void __stdcall friend_stdcall2();150 friend void friend_stdcall3(); // expected-note {{previous declaration is here}}151};152void friend_default() {}153void __stdcall friend_stdcall3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}154void __stdcall friend_stdcall2() {}155 156// Test functions with multiple attributes.157void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attribute(int x);158void multi_attribute(int x) { __builtin_unreachable(); }159 160 161// expected-error@+3 {{vectorcall and cdecl attributes are not compatible}}162// expected-error@+2 {{stdcall and cdecl attributes are not compatible}}163// expected-error@+1 {{fastcall and cdecl attributes are not compatible}}164void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x);165 166template <typename T> void __stdcall StdcallTemplate(T) {}167template <> void StdcallTemplate<int>(int) {}168template <> void __stdcall StdcallTemplate<short>(short) {}169 170// FIXME: Note the template, not the implicit instantiation.171// expected-error@+2 {{function declared 'cdecl' here was previously declared 'stdcall}}172// expected-note@+1 {{previous declaration is here}}173template <> void __cdecl StdcallTemplate<long>(long) {}174 175struct ExactlyInt {176 template <typename T> static int cast_to_int(T) {177 return T::this_is_not_an_int();178 }179};180template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; }181 182namespace test2 {183 class foo {184 template <typename T> void bar(T v);185 };186 extern template void foo::bar(const void *);187}188 189namespace test3 {190 struct foo {191 typedef void bar();192 };193 bool zed(foo::bar *);194 void bah() {}195 void baz() { zed(bah); }196}197 198namespace test4 {199 class foo {200 template <typename T> static void bar(T v);201 };202 extern template void foo::bar(const void *);203}204 205namespace test5 {206 template <class T>207 class valarray {208 void bar();209 };210 extern template void valarray<int>::bar();211}212 213namespace test6 {214 struct foo {215 int bar();216 };217 typedef int bar_t();218 void zed(bar_t foo::*) {219 }220 void baz() {221 zed(&foo::bar);222 }223}224 225namespace test7 {226 template <typename T>227 struct S {228 void f(T t) {229 t = 42;230 }231 };232 template<> void S<void*>::f(void*);233 void g(S<void*> s, void* p) {234 s.f(p);235 }236}237 238namespace test8 {239 template <typename T>240 struct S {241 void f(T t) { // expected-note {{previous declaration is here}}242 t = 42; // expected-error {{incompatible integer to pointer conversion assigning to 'void *' from 'int'}}243 }244 };245 template<> void __cdecl S<void*>::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}246 void g(S<void*> s, void* p) {247 s.f(p); // expected-note {{in instantiation of member function 'test8::S<void *>::f' requested here}}248 }249}250 251namespace test9 {252 // Used to fail when we forgot to make lambda call operators use __thiscall.253 template <typename F>254 decltype(auto) deduce(F f) {255 return &decltype(f)::operator();256 }257 template <typename C, typename R, typename A>258 decltype(auto) signaturehelper(R (C::*f)(A) const) {259 return R();260 }261 void f() {262 auto l = [](int x) { return x * 2; };263 decltype(signaturehelper(deduce(l))) p;264 }265}266