xref: /llvm-project/clang/test/SemaCXX/MicrosoftCompatibility.cpp (revision 4848f3bf2ff5ec57a8e2b8d3676c947dcf0fd735)
1 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.28
2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.27
3 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.00
4 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=18.00
5 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++17 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
6 
7 
8 #if defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT
9 char16_t x;
10 char32_t y;
11 #else
12 typedef unsigned short char16_t;
13 typedef unsigned int char32_t;
14 #endif
15 
16 _Atomic(int) z;
17 template <typename T>
18 struct _Atomic {
_Atomic_Atomic19   _Atomic() {}
~_Atomic_Atomic20   ~_Atomic() {}
21 };
22 template <typename T>
23 struct atomic : _Atomic<T> {
24   typedef _Atomic<T> TheBase;
25   TheBase field;
26 };
27 _Atomic(int) alpha;
28 
29 typename decltype(3) a; // expected-warning {{expected a qualified name after 'typename'}}
30 
31 namespace ms_conversion_rules {
32 
33 void f(float a);
34 void f(int a);
35 #if _MSC_VER >= 1928
36 // expected-note@-3 2 {{candidate function}}
37 // expected-note@-3 2 {{candidate function}}
38 #endif
39 
test()40 void test()
41 {
42     long a = 0;
43     f((long)0);
44     f(a);
45 #if _MSC_VER >= 1928
46 // expected-error@-3 {{call to 'f' is ambiguous}}
47 // expected-error@-3 {{call to 'f' is ambiguous}}
48 #endif
49 }
50 
51 }
52 
53 
54 namespace ms_predefined_types {
55   // ::type_info is a built-in forward class declaration.
56   void f(const type_info &a);
57   void f(size_t);
58 }
59 
60 
61 namespace ms_protected_scope {
62   struct C { C(); };
63 
jump_over_variable_init(bool b)64   int jump_over_variable_init(bool b) {
65     if (b)
66       goto foo; // expected-warning {{jump from this goto statement to its label is a Microsoft extension}}
67     C c; // expected-note {{jump bypasses variable initialization}}
68   foo:
69     return 1;
70   }
71 
72 struct Y {
73   ~Y();
74 };
75 
jump_over_var_with_dtor()76 void jump_over_var_with_dtor() {
77   goto end; // expected-warning{{jump from this goto statement to its label is a Microsoft extension}}
78   Y y; // expected-note {{jump bypasses variable with a non-trivial destructor}}
79  end:
80     ;
81 }
82 
jump_over_variable_case(int c)83   void jump_over_variable_case(int c) {
84     switch (c) {
85     case 0:
86       int x = 56; // expected-note {{jump bypasses variable initialization}}
87     case 1:       // expected-error {{cannot jump}}
88       x = 10;
89     }
90   }
91 
92 
exception_jump()93 void exception_jump() {
94   goto l2; // expected-error {{cannot jump}}
95   try { // expected-note {{jump bypasses initialization of try block}}
96      l2: ;
97   } catch(int) {
98   }
99 }
100 
jump_over_indirect_goto()101 int jump_over_indirect_goto() {
102   static void *ps[] = { &&a0 };
103   goto *&&a0; // expected-warning {{jump from this goto statement to its label is a Microsoft extension}}
104   int a = 3; // expected-note {{jump bypasses variable initialization}}
105  a0:
106   return 0;
107 }
108 
109 }
110 
111 namespace PR11826 {
112   struct pair {
pairPR11826::pair113     pair(int v) { }
114 #if _MSC_VER >= 1900
operator =PR11826::pair115     void operator=(pair&& rhs) { } // expected-note {{copy constructor is implicitly deleted because 'pair' has a user-declared move assignment operator}}
116 #else
operator =PR11826::pair117     void operator=(pair&& rhs) { }
118 #endif
119   };
f()120   void f() {
121     pair p0(3);
122 #if _MSC_VER >= 1900
123     pair p = p0; // expected-error {{call to implicitly-deleted copy constructor of 'pair'}}
124 #else
125     pair p = p0;
126 #endif
127   }
128 }
129 
130 namespace PR11826_for_symmetry {
131   struct pair {
pairPR11826_for_symmetry::pair132     pair(int v) { }
133 #if _MSC_VER >= 1900
pairPR11826_for_symmetry::pair134     pair(pair&& rhs) { } // expected-note {{copy assignment operator is implicitly deleted because 'pair' has a user-declared move constructor}}
135 #else
pairPR11826_for_symmetry::pair136     pair(pair&& rhs) { }
137 #endif
138   };
f()139   void f() {
140     pair p0(3);
141     pair p(4);
142 #if _MSC_VER >= 1900
143     p = p0; // expected-error {{object of type 'pair' cannot be assigned because its copy assignment operator is implicitly deleted}}
144 #else
145     p = p0;
146 #endif
147   }
148 }
149 
150 namespace ms_using_declaration_bug {
151 
152 class A {
153 public:
154   int f();
155 };
156 
157 class B : public A {
158 private:
159   using A::f;
g()160   void g() {
161     f(); // no diagnostic
162   }
163 };
164 
165 class C : public B {
166 private:
167   using B::f; // expected-warning {{using declaration referring to inaccessible member 'ms_using_declaration_bug::B::f' (which refers to accessible member 'ms_using_declaration_bug::A::f') is a Microsoft compatibility extension}}
168 };
169 
170 }
171 
172 namespace using_tag_redeclaration
173 {
174   struct S;
175   namespace N {
176     using ::using_tag_redeclaration::S;
177     struct S {}; // expected-note {{previous definition is here}}
178   }
f()179   void f() {
180     N::S s1;
181     S s2;
182   }
g()183   void g() {
184     struct S; // expected-note {{forward declaration of 'S'}}
185     S s3; // expected-error {{variable has incomplete type 'S'}}
186   }
h()187   void h() {
188     using ::using_tag_redeclaration::S;
189     struct S {}; // expected-error {{redefinition of 'S'}}
190   }
191 }
192 
193 
194 namespace MissingTypename {
195 
196 template<class T> class A {
197 public:
198 	 typedef int TYPE;
199 };
200 
201 template<class T> class B {
202 public:
203 	 typedef int TYPE;
204 };
205 
206 
207 template<class T, class U>
208 class C : private A<T>, public B<U> {
209 public:
210    typedef A<T> Base1;
211    typedef B<U> Base2;
212    typedef A<U> Base3;
213 
214    A<T>::TYPE a1; // expected-warning {{implicit 'typename' is a C++20 extension}}
215    Base1::TYPE a2; // expected-warning {{implicit 'typename' is a C++20 extension}}
216 
217    B<U>::TYPE a3; // expected-warning {{implicit 'typename' is a C++20 extension}}
218    Base2::TYPE a4; // expected-warning {{implicit 'typename' is a C++20 extension}}
219 
220    A<U>::TYPE a5; // expected-warning {{implicit 'typename' is a C++20 extension}}
221    Base3::TYPE a6; // expected-warning {{implicit 'typename' is a C++20 extension}}
222  };
223 
224 class D {
225 public:
226     typedef int Type;
227 };
228 
229 template <class T>
function_missing_typename(const T::Type param)230 void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename'}}
231 {
232     const T::Type var = 2; // expected-warning {{missing 'typename'}}
233 }
234 
235 template void function_missing_typename<D>(const D::Type param);
236 
237 }
238 
239 //MSVC allows forward enum declaration
240 enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
241 ENUM *var = 0;
242 ENUM var2 = (ENUM)0;
243 enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}}
244 
245 enum ENUM1 { kA };
246 enum ENUM1;  // This way round is fine.
247 
248 enum ENUM2 {
249 	ENUM2_a = (enum ENUM2) 0,
250 	ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
251 	ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
252 };
253 
254 namespace NsEnumForwardDecl {
255   enum E *p; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
256   extern E e;
257 }
258 // Clang used to complain that NsEnumForwardDecl::E was undeclared below.
259 NsEnumForwardDecl::E NsEnumForwardDecl_e;
260 namespace NsEnumForwardDecl {
261   extern E e;
262 }
263 
264 namespace PR11791 {
265   template<class _Ty>
del(_Ty * _Ptr)266   void del(_Ty *_Ptr) {
267     _Ptr->~_Ty();  // expected-warning {{pseudo-destructors on type void are a Microsoft extension}}
268   }
269 
f()270   void f() {
271     int* a = 0;
272     del((void*)a);  // expected-note {{in instantiation of function template specialization}}
273   }
274 }
275 
276 namespace IntToNullPtrConv {
277   struct Foo {
278     static const int ZERO = 0;
279     typedef void (Foo::*MemberFcnPtr)();
280   };
281 
282   struct Bar {
283     const Foo::MemberFcnPtr pB;
284   };
285 
286   Bar g_bar = { (Foo::MemberFcnPtr)Foo::ZERO };
287 
get_n()288   template<int N> int *get_n() { return N; }   // expected-warning {{expression which evaluates to zero treated as a null pointer constant}}
289   int *g_nullptr = get_n<0>();  // expected-note {{in instantiation of function template specialization}}
290 
291   // FIXME: MSVC accepts this.
292   constexpr float k = 0;
293   int *p1 = (int)k; // expected-error {{cannot initialize}}
294 
295   constexpr int n = 0;
296   const int &r = n;
297   int *p2 = (int)r; // expected-error {{cannot initialize}}
298 
f()299   constexpr int f() { return 0; }
300   int *p = f(); // expected-error {{cannot initialize}}
301 }
302 
303 namespace signed_hex_i64 {
304 void f(long long);
305 void f(int);
g()306 void g() {
307   // This is an ambiguous call in standard C++.
308   // This calls f(long long) in Microsoft mode because LL is always signed.
309   f(0xffffffffffffffffLL);
310   f(0xffffffffffffffffi64);
311 }
312 }
313 
314 typedef void (*FnPtrTy)();
315 void (*PR23733_1)() = static_cast<FnPtrTy>((void *)0); // expected-warning {{static_cast between pointer-to-function and pointer-to-object is a Microsoft extension}}
316 void (*PR23733_2)() = FnPtrTy((void *)0);
317 void (*PR23733_3)() = (FnPtrTy)((void *)0);
318 void (*PR23733_4)() = reinterpret_cast<FnPtrTy>((void *)0);
319 
320 long function_prototype(int a);
321 long (*function_ptr)(int a);
322 
function_to_voidptr_conv()323 void function_to_voidptr_conv() {
324   void *a1 = function_prototype;  // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}}
325   void *a2 = &function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}}
326   void *a3 = function_ptr;        // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}}
327 }
328 
329 namespace member_lookup {
330 
331 template<typename T>
332 struct ConfuseLookup {
333   T* m_val;
334   struct m_val {
335     static size_t ms_test;
336   };
337 };
338 
339 // Microsoft mode allows explicit constructor calls
340 // This could confuse name lookup in cases such as this
341 template<typename T>
342 size_t ConfuseLookup<T>::m_val::ms_test
343   = size_t(&(char&)(reinterpret_cast<ConfuseLookup<T>*>(0)->m_val));
344 
instantiate()345 void instantiate() { ConfuseLookup<int>::m_val::ms_test = 1; }
346 }
347 
348 
349 // Microsoft doesn't validate exception specification.
350 namespace microsoft_exception_spec {
351 
352 void foo(); // expected-note {{previous declaration}}
353 void foo() throw(); // expected-warning {{exception specification in declaration does not match previous declaration}}
354 
355 #if __cplusplus < 201703L
356 void r6() throw(...); // expected-note {{previous declaration}}
357 void r6() throw(int); // expected-warning {{exception specification in declaration does not match previous declaration}}
358 
359 struct Base {
360   virtual void f2();
361   virtual void f3() throw(...);
362 };
363 
364 struct Derived : Base {
365   virtual void f2() throw(...);
366   virtual void f3();
367 };
368 #endif
369 
370 class A {
371   virtual ~A() throw();
372 #if __cplusplus <= 199711L
373   // expected-note@-2 {{overridden virtual function is here}}
374 #endif
375 };
376 
377 class B : public A {
378   virtual ~B();
379 #if __cplusplus <= 199711L
380   // expected-warning@-2 {{exception specification of overriding function is more lax than base version}}
381 #endif
382 };
383 
384 void f4() throw(); // expected-note {{previous declaration is here}}
f4()385 void f4() {}       // expected-warning {{'f4' is missing exception specification 'throw()'}}
386 
387 __declspec(nothrow) void f5();
f5()388 void f5() {}
389 
390 void f6() noexcept; // expected-note {{previous declaration is here}}
f6()391 void f6() {}        // expected-error {{'f6' is missing exception specification 'noexcept'}}
392 }
393 
394 namespace PR43265 {
395 template <int N> // expected-note {{template parameter is declared here}}
396 struct Foo {
397   static const int N = 42; // expected-warning {{declaration of 'N' shadows template parameter}}
398 };
399 }
400 
401 namespace Inner_Outer_same_template_param_name {
402 template <typename T> // expected-note {{template parameter is declared here}}
403 struct Outmost {
404   template <typename T> // expected-warning {{declaration of 'T' shadows template parameter}}
405   struct Inner {
fInner_Outer_same_template_param_name::Outmost::Inner406     void f() {
407       T *var;
408     }
409   };
410 };
411 }
412