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