xref: /llvm-project/clang/test/Sema/microsoft-varargs.c (revision 96d3319d6f024b17ac725d9595548acc4787003c)
1 // RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only -x c %s -verify
2 // RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only -x c %s -verify
3 // RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only -x c++ %s -verify
4 // RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only -x c++ %s -verify
5 // expected-no-diagnostics
6 
7 #if defined _NO_CRT_STDIO_INLINE
8 #  undef _CRT_STDIO_INLINE
9 #  define _CRT_STDIO_INLINE
10 #elif !defined _CRT_STDIO_INLINE
11 #  define _CRT_STDIO_INLINE __inline
12 #endif
13 
14 #ifndef _VA_LIST_DEFINED
15 #define _VA_LIST_DEFINED
16 typedef char *va_list;
17 #endif
18 
19 #if !defined __cplusplus
20 // Workaround for /Zc:wchar_t
21 typedef  __WCHAR_TYPE__ wchar_t;
22 #endif
23 
24 #if defined __cplusplus
25 #  define _ADDRESSOF(v) (&const_cast<char&>(reinterpret_cast<const volatile char&>(v)))
26 #else
27 #  define _ADDRESSOF(v) (&(v))
28 #endif
29 
30 #if defined _M_ARM
31 #  define _VA_ALIGN      4
32 #  define _SLOTSIZEOF(t) ((sizeof(t) + _VA_ALIGN - 1) & ~(_VA_ALIGN - 1))
33 #  define _APALIGN(t,ap) (((va_list)0 - (ap)) & (__alignof(t) - 1))
34 #elif defined _M_ARM64
35 #  define _VA_ALIGN      8
36 #  define _SLOTSIZEOF(t) ((sizeof(t) + _VA_ALIGN - 1) & ~(_VA_ALIGN - 1))
37 #  define _APALIGN(t,ap) (((va_list)0 - (ap)) & (__alignof(t) - 1))
38 #endif
39 
40 #if defined _M_ARM
41 void __cdecl __va_start(va_list*, ...);
42 #  if defined __cplusplus
43 #    define __crt_va_start_a(ap, v) ((void)(__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), _ADDRESSOF(v))))
44 #  else
45 #    define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _SLOTSIZEOF(v)))
46 #  endif
47 
48 #  define __crt_va_arg(ap, t) (*(t*)((ap += _SLOTSIZEOF(t) + _APALIGN(t,ap)) - _SLOTSIZEOF(t)))
49 #  define __crt_va_end(ap)    ((void)(ap = (va_list)0))
50 #elif defined _M_ARM64
51 void __cdecl __va_start(va_list*, ...);
52 #  define __crt_va_start_a(ap,v) ((void)(__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), __alignof(v), _ADDRESSOF(v))))
53 #  define __crt_va_arg(ap, t)                                                   \
54     ((sizeof(t) > (2 * sizeof(__int64)))                                        \
55        ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))                     \
56        : *(t*)((ap ++ _SLOTSIZEOF(t) + _APALIGN(t,ap)) - _SLOTSIZEOF(t)))
57 #  define __crt_va_end(ap)       ((void)(ap = (va_list)0))
58 #endif
59 
60 #if defined __cplusplus
61 extern "C++" {
62 template <typename _T>
63 struct __vcrt_va_list_is_reference {
64   enum : bool { __the_value = false };
65 };
66 
67 template <typename _T>
68 struct __vcrt_va_list_is_reference<_T&> {
69   enum : bool { __the_value = true };
70 };
71 
72 template <typename _T>
73 struct __vcrt_va_list_is_reference<_T&&> {
74   enum : bool { __the_value = true };
75 };
76 
77 template <typename _T>
78 struct __vcrt_assert_va_start_is_not_reference {
79   static_assert(!__vcrt_va_list_is_reference<_T>::__the_value,
80                 "va_start argument must not have reference type and must not be parenthesized");
81 };
82 }
83 
84 #  define __crt_va_start(ap, x) ((void)(__vcrt_assert_va_start_is_not_reference<decltype(x)>(), __crt_va_start_a(ap, x)))
85 #else
86 #  define __crt_va_start(ap, x) __crt_va_start_a(ap, x)
87 #endif
88 
89 /*_Check_return_opt_*/ _CRT_STDIO_INLINE int __cdecl
90 wprintf(/*_In_z_ _Printf_format_string_*/ wchar_t const * const _Format, ...) {
91   int _Result;
92   va_list _ArgList;
93   __crt_va_start(_ArgList, _Format);
94   // _Result = _vfwprintf_l(stdout, _Format, NULL, _ArgList);
95   __crt_va_end(_ArgList);
96   return _Result;
97 }
98