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