xref: /minix3/external/bsd/llvm/dist/clang/test/SemaCXX/decl-microsoft-call-conv.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -fms-extensions -verify %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc typedef void void_fun_t();
4*f4a2713aSLionel Sambuc typedef void __cdecl cdecl_fun_t();
5*f4a2713aSLionel Sambuc 
6*f4a2713aSLionel Sambuc // Pointers to free functions
7*f4a2713aSLionel Sambuc void            free_func_default(); // expected-note 2 {{previous declaration is here}}
8*f4a2713aSLionel Sambuc void __cdecl    free_func_cdecl(); // expected-note 2 {{previous declaration is here}}
9*f4a2713aSLionel Sambuc void __stdcall  free_func_stdcall(); // expected-note 2 {{previous declaration is here}}
10*f4a2713aSLionel Sambuc void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}}
11*f4a2713aSLionel Sambuc 
12*f4a2713aSLionel Sambuc void __cdecl    free_func_default();
13*f4a2713aSLionel Sambuc void __stdcall  free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
14*f4a2713aSLionel Sambuc void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}}
15*f4a2713aSLionel Sambuc 
16*f4a2713aSLionel Sambuc void            free_func_cdecl();
17*f4a2713aSLionel Sambuc void __stdcall  free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}
18*f4a2713aSLionel Sambuc void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}}
19*f4a2713aSLionel Sambuc 
20*f4a2713aSLionel Sambuc void            free_func_stdcall();
21*f4a2713aSLionel Sambuc void __cdecl    free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}}
22*f4a2713aSLionel Sambuc void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}}
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc void __cdecl    free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}}
25*f4a2713aSLionel Sambuc void __stdcall  free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}}
26*f4a2713aSLionel Sambuc void            free_func_fastcall();
27*f4a2713aSLionel Sambuc 
28*f4a2713aSLionel Sambuc // Overloaded functions may have different calling conventions
29*f4a2713aSLionel Sambuc void __fastcall free_func_default(int);
30*f4a2713aSLionel Sambuc void __cdecl    free_func_default(int *);
31*f4a2713aSLionel Sambuc 
32*f4a2713aSLionel Sambuc void __thiscall free_func_cdecl(char *);
33*f4a2713aSLionel Sambuc void __cdecl    free_func_cdecl(double);
34*f4a2713aSLionel Sambuc 
35*f4a2713aSLionel Sambuc typedef void void_fun_t();
36*f4a2713aSLionel Sambuc typedef void __cdecl cdecl_fun_t();
37*f4a2713aSLionel Sambuc 
38*f4a2713aSLionel Sambuc // Pointers to member functions
39*f4a2713aSLionel Sambuc struct S {
40*f4a2713aSLionel Sambuc   void            member_default1(); // expected-note {{previous declaration is here}}
41*f4a2713aSLionel Sambuc   void            member_default2();
42*f4a2713aSLionel Sambuc   void __cdecl    member_cdecl1();
43*f4a2713aSLionel Sambuc   void __cdecl    member_cdecl2(); // expected-note {{previous declaration is here}}
44*f4a2713aSLionel Sambuc   void __thiscall member_thiscall1();
45*f4a2713aSLionel Sambuc   void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}}
46*f4a2713aSLionel Sambuc 
47*f4a2713aSLionel Sambuc   // Typedefs carrying the __cdecl convention are adjusted to __thiscall.
48*f4a2713aSLionel Sambuc   void_fun_t           member_typedef_default; // expected-note {{previous declaration is here}}
49*f4a2713aSLionel Sambuc   cdecl_fun_t          member_typedef_cdecl1;  // expected-note {{previous declaration is here}}
50*f4a2713aSLionel Sambuc   cdecl_fun_t __cdecl  member_typedef_cdecl2;
51*f4a2713aSLionel Sambuc   void_fun_t __stdcall member_typedef_stdcall;
52*f4a2713aSLionel Sambuc 
53*f4a2713aSLionel Sambuc   // Static member functions can't be __thiscall
54*f4a2713aSLionel Sambuc   static void            static_member_default1();
55*f4a2713aSLionel Sambuc   static void            static_member_default2();
56*f4a2713aSLionel Sambuc   static void            static_member_default3(); // expected-note {{previous declaration is here}}
57*f4a2713aSLionel Sambuc   static void __cdecl    static_member_cdecl1();
58*f4a2713aSLionel Sambuc   static void __cdecl    static_member_cdecl2(); // expected-note {{previous declaration is here}}
59*f4a2713aSLionel Sambuc   static void __stdcall  static_member_stdcall1();
60*f4a2713aSLionel Sambuc   static void __stdcall  static_member_stdcall2();
61*f4a2713aSLionel Sambuc 
62*f4a2713aSLionel Sambuc   // Variadic functions can't be other than default or __cdecl
63*f4a2713aSLionel Sambuc   void            member_variadic_default(int x, ...);
64*f4a2713aSLionel Sambuc   void __cdecl    member_variadic_cdecl(int x, ...);
65*f4a2713aSLionel Sambuc 
66*f4a2713aSLionel Sambuc   static void            static_member_variadic_default(int x, ...);
67*f4a2713aSLionel Sambuc   static void __cdecl    static_member_variadic_cdecl(int x, ...);
68*f4a2713aSLionel Sambuc };
69*f4a2713aSLionel Sambuc 
70*f4a2713aSLionel Sambuc void __cdecl    S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
71*f4a2713aSLionel Sambuc void __thiscall S::member_default2() {}
72*f4a2713aSLionel Sambuc 
73*f4a2713aSLionel Sambuc void __cdecl   S::member_typedef_default() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
74*f4a2713aSLionel Sambuc void __cdecl   S::member_typedef_cdecl1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
75*f4a2713aSLionel Sambuc void __cdecl   S::member_typedef_cdecl2() {}
76*f4a2713aSLionel Sambuc void __stdcall S::member_typedef_stdcall() {}
77*f4a2713aSLionel Sambuc 
78*f4a2713aSLionel Sambuc void            S::member_cdecl1() {}
79*f4a2713aSLionel Sambuc void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}}
80*f4a2713aSLionel Sambuc 
81*f4a2713aSLionel Sambuc void            S::member_thiscall1() {}
82*f4a2713aSLionel Sambuc void __cdecl    S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}}
83*f4a2713aSLionel Sambuc 
84*f4a2713aSLionel Sambuc void            S::static_member_default1() {}
85*f4a2713aSLionel Sambuc void __cdecl    S::static_member_default2() {}
86*f4a2713aSLionel Sambuc void __stdcall  S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
87*f4a2713aSLionel Sambuc 
88*f4a2713aSLionel Sambuc void            S::static_member_cdecl1() {}
89*f4a2713aSLionel Sambuc void __stdcall  S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}
90*f4a2713aSLionel Sambuc 
91*f4a2713aSLionel Sambuc void __cdecl    S::member_variadic_default(int x, ...) { (void)x; }
92*f4a2713aSLionel Sambuc void            S::member_variadic_cdecl(int x, ...) { (void)x; }
93*f4a2713aSLionel Sambuc 
94*f4a2713aSLionel Sambuc void __cdecl    S::static_member_variadic_default(int x, ...) { (void)x; }
95*f4a2713aSLionel Sambuc void            S::static_member_variadic_cdecl(int x, ...) { (void)x; }
96*f4a2713aSLionel Sambuc 
97*f4a2713aSLionel Sambuc // Declare a template using a calling convention.
98*f4a2713aSLionel Sambuc template <class CharT> inline int __cdecl mystrlen(const CharT *str) {
99*f4a2713aSLionel Sambuc   int i;
100*f4a2713aSLionel Sambuc   for (i = 0; str[i]; i++) { }
101*f4a2713aSLionel Sambuc   return i;
102*f4a2713aSLionel Sambuc }
103*f4a2713aSLionel Sambuc extern int sse_strlen(const char *str);
104*f4a2713aSLionel Sambuc template <> inline int __cdecl mystrlen(const char *str) {
105*f4a2713aSLionel Sambuc   return sse_strlen(str);
106*f4a2713aSLionel Sambuc }
107*f4a2713aSLionel Sambuc void use_tmpl(const char *str, const int *ints) {
108*f4a2713aSLionel Sambuc   mystrlen(str);
109*f4a2713aSLionel Sambuc   mystrlen(ints);
110*f4a2713aSLionel Sambuc }
111*f4a2713aSLionel Sambuc 
112*f4a2713aSLionel Sambuc struct MixedCCStaticOverload {
113*f4a2713aSLionel Sambuc   static void overloaded(int a);
114*f4a2713aSLionel Sambuc   static void __stdcall overloaded(short a);
115*f4a2713aSLionel Sambuc };
116*f4a2713aSLionel Sambuc 
117*f4a2713aSLionel Sambuc void MixedCCStaticOverload::overloaded(int a) {}
118*f4a2713aSLionel Sambuc void MixedCCStaticOverload::overloaded(short a) {}
119*f4a2713aSLionel Sambuc 
120*f4a2713aSLionel Sambuc // Friend function decls are cdecl by default, not thiscall.  Friend method
121*f4a2713aSLionel Sambuc // decls should always be redeclarations, because the class cannot be
122*f4a2713aSLionel Sambuc // incomplete.
123*f4a2713aSLionel Sambuc struct FriendClass {
124*f4a2713aSLionel Sambuc   void friend_method() {}
125*f4a2713aSLionel Sambuc };
126*f4a2713aSLionel Sambuc void __stdcall friend_stdcall1() {}
127*f4a2713aSLionel Sambuc class MakeFriendDecls {
128*f4a2713aSLionel Sambuc   int x;
129*f4a2713aSLionel Sambuc   friend void FriendClass::friend_method();
130*f4a2713aSLionel Sambuc   friend void              friend_default();
131*f4a2713aSLionel Sambuc   friend void              friend_stdcall1();
132*f4a2713aSLionel Sambuc   friend void __stdcall    friend_stdcall2();
133*f4a2713aSLionel Sambuc   friend void              friend_stdcall3(); // expected-note {{previous declaration is here}}
134*f4a2713aSLionel Sambuc };
135*f4a2713aSLionel Sambuc void           friend_default() {}
136*f4a2713aSLionel Sambuc void __stdcall friend_stdcall3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
137*f4a2713aSLionel Sambuc void __stdcall friend_stdcall2() {}
138*f4a2713aSLionel Sambuc 
139*f4a2713aSLionel Sambuc // Test functions with multiple attributes.
140*f4a2713aSLionel Sambuc void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attribute(int x);
141*f4a2713aSLionel Sambuc void multi_attribute(int x) { __builtin_unreachable(); }
142*f4a2713aSLionel Sambuc 
143*f4a2713aSLionel Sambuc 
144*f4a2713aSLionel Sambuc // expected-error@+2 {{stdcall and cdecl attributes are not compatible}}
145*f4a2713aSLionel Sambuc // expected-error@+1 {{fastcall and cdecl attributes are not compatible}}
146*f4a2713aSLionel Sambuc void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x);
147*f4a2713aSLionel Sambuc 
148*f4a2713aSLionel Sambuc template <typename T> void __stdcall StdcallTemplate(T) {}
149*f4a2713aSLionel Sambuc template <> void StdcallTemplate<int>(int) {}
150*f4a2713aSLionel Sambuc template <> void __stdcall StdcallTemplate<short>(short) {}
151*f4a2713aSLionel Sambuc 
152*f4a2713aSLionel Sambuc // FIXME: Note the template, not the implicit instantiation.
153*f4a2713aSLionel Sambuc // expected-error@+2 {{function declared 'cdecl' here was previously declared 'stdcall}}
154*f4a2713aSLionel Sambuc // expected-note@+1 {{previous declaration is here}}
155*f4a2713aSLionel Sambuc template <> void __cdecl StdcallTemplate<long>(long) {}
156*f4a2713aSLionel Sambuc 
157*f4a2713aSLionel Sambuc struct ExactlyInt {
158*f4a2713aSLionel Sambuc   template <typename T> static int cast_to_int(T) {
159*f4a2713aSLionel Sambuc     return T::this_is_not_an_int();
160*f4a2713aSLionel Sambuc   }
161*f4a2713aSLionel Sambuc };
162*f4a2713aSLionel Sambuc template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; }
163*f4a2713aSLionel Sambuc 
164*f4a2713aSLionel Sambuc namespace test2 {
165*f4a2713aSLionel Sambuc   class foo {
166*f4a2713aSLionel Sambuc     template <typename T> void bar(T v);
167*f4a2713aSLionel Sambuc   };
168*f4a2713aSLionel Sambuc   extern template void foo::bar(const void *);
169*f4a2713aSLionel Sambuc }
170*f4a2713aSLionel Sambuc 
171*f4a2713aSLionel Sambuc namespace test3 {
172*f4a2713aSLionel Sambuc   struct foo {
173*f4a2713aSLionel Sambuc     typedef void bar();
174*f4a2713aSLionel Sambuc   };
175*f4a2713aSLionel Sambuc   bool zed(foo::bar *);
176*f4a2713aSLionel Sambuc   void bah() {}
177*f4a2713aSLionel Sambuc   void baz() { zed(bah); }
178*f4a2713aSLionel Sambuc }
179*f4a2713aSLionel Sambuc 
180*f4a2713aSLionel Sambuc namespace test4 {
181*f4a2713aSLionel Sambuc   class foo {
182*f4a2713aSLionel Sambuc     template <typename T> static void bar(T v);
183*f4a2713aSLionel Sambuc   };
184*f4a2713aSLionel Sambuc   extern template void foo::bar(const void *);
185*f4a2713aSLionel Sambuc }
186