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