[clang] 96d3319 - Sema: relax va_start checking further for Windows AArch64
Saleem Abdulrasool via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 20 14:24:09 PDT 2021
Author: Saleem Abdulrasool
Date: 2021-09-20T21:23:33Z
New Revision: 96d3319d6f024b17ac725d9595548acc4787003c
URL: https://github.com/llvm/llvm-project/commit/96d3319d6f024b17ac725d9595548acc4787003c
DIFF: https://github.com/llvm/llvm-project/commit/96d3319d6f024b17ac725d9595548acc4787003c.diff
LOG: Sema: relax va_start checking further for Windows AArch64
When building in C mode, the VC runtime assumes that it can use pointer
aliasing through `char *` for the parameter to `__va_start`. Relax the
checks further. In theory we could keep the tests strict for non-system
header code, but this takes the less strict approach as the additional
check doesn't particularly end up being too much more helpful for
correctness. The C++ type system is a bit stricter and requires the
explicit cast which we continue to verify.
Added:
clang/test/Sema/microsoft-varargs.c
Modified:
clang/lib/Sema/SemaChecking.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 99cd2b2278f1..0c47fb040d60 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -6413,6 +6413,21 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
}
bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
+ auto IsSuitablyTypedFormatArgument = [this](const Expr *Arg) -> bool {
+ const LangOptions &LO = getLangOpts();
+
+ if (LO.CPlusPlus)
+ return Arg->getType()
+ .getCanonicalType()
+ .getTypePtr()
+ ->getPointeeType()
+ .withoutLocalFastQualifiers() == Context.CharTy;
+
+ // In C, allow aliasing through `char *`, this is required for AArch64 at
+ // least.
+ return true;
+ };
+
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
@@ -6441,8 +6456,7 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
const QualType &ConstCharPtrTy =
Context.getPointerType(Context.CharTy.withConst());
- if (!Arg1Ty->isPointerType() ||
- Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
+ if (!Arg1Ty->isPointerType() || !IsSuitablyTypedFormatArgument(Arg1))
Diag(Arg1->getBeginLoc(), diag::err_typecheck_convert_incompatible)
<< Arg1->getType() << ConstCharPtrTy << 1 /*
diff erent class */
<< 0 /* qualifier
diff erence */
diff --git a/clang/test/Sema/microsoft-varargs.c b/clang/test/Sema/microsoft-varargs.c
new file mode 100644
index 000000000000..979875e8cbae
--- /dev/null
+++ b/clang/test/Sema/microsoft-varargs.c
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only -x c %s -verify
+// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only -x c %s -verify
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only -x c++ %s -verify
+// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only -x c++ %s -verify
+// expected-no-diagnostics
+
+#if defined _NO_CRT_STDIO_INLINE
+# undef _CRT_STDIO_INLINE
+# define _CRT_STDIO_INLINE
+#elif !defined _CRT_STDIO_INLINE
+# define _CRT_STDIO_INLINE __inline
+#endif
+
+#ifndef _VA_LIST_DEFINED
+#define _VA_LIST_DEFINED
+typedef char *va_list;
+#endif
+
+#if !defined __cplusplus
+// Workaround for /Zc:wchar_t
+typedef __WCHAR_TYPE__ wchar_t;
+#endif
+
+#if defined __cplusplus
+# define _ADDRESSOF(v) (&const_cast<char&>(reinterpret_cast<const volatile char&>(v)))
+#else
+# define _ADDRESSOF(v) (&(v))
+#endif
+
+#if defined _M_ARM
+# define _VA_ALIGN 4
+# define _SLOTSIZEOF(t) ((sizeof(t) + _VA_ALIGN - 1) & ~(_VA_ALIGN - 1))
+# define _APALIGN(t,ap) (((va_list)0 - (ap)) & (__alignof(t) - 1))
+#elif defined _M_ARM64
+# define _VA_ALIGN 8
+# define _SLOTSIZEOF(t) ((sizeof(t) + _VA_ALIGN - 1) & ~(_VA_ALIGN - 1))
+# define _APALIGN(t,ap) (((va_list)0 - (ap)) & (__alignof(t) - 1))
+#endif
+
+#if defined _M_ARM
+void __cdecl __va_start(va_list*, ...);
+# if defined __cplusplus
+# define __crt_va_start_a(ap, v) ((void)(__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), _ADDRESSOF(v))))
+# else
+# define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _SLOTSIZEOF(v)))
+# endif
+
+# define __crt_va_arg(ap, t) (*(t*)((ap += _SLOTSIZEOF(t) + _APALIGN(t,ap)) - _SLOTSIZEOF(t)))
+# define __crt_va_end(ap) ((void)(ap = (va_list)0))
+#elif defined _M_ARM64
+void __cdecl __va_start(va_list*, ...);
+# define __crt_va_start_a(ap,v) ((void)(__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), __alignof(v), _ADDRESSOF(v))))
+# define __crt_va_arg(ap, t) \
+ ((sizeof(t) > (2 * sizeof(__int64))) \
+ ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \
+ : *(t*)((ap ++ _SLOTSIZEOF(t) + _APALIGN(t,ap)) - _SLOTSIZEOF(t)))
+# define __crt_va_end(ap) ((void)(ap = (va_list)0))
+#endif
+
+#if defined __cplusplus
+extern "C++" {
+template <typename _T>
+struct __vcrt_va_list_is_reference {
+ enum : bool { __the_value = false };
+};
+
+template <typename _T>
+struct __vcrt_va_list_is_reference<_T&> {
+ enum : bool { __the_value = true };
+};
+
+template <typename _T>
+struct __vcrt_va_list_is_reference<_T&&> {
+ enum : bool { __the_value = true };
+};
+
+template <typename _T>
+struct __vcrt_assert_va_start_is_not_reference {
+ static_assert(!__vcrt_va_list_is_reference<_T>::__the_value,
+ "va_start argument must not have reference type and must not be parenthesized");
+};
+}
+
+# define __crt_va_start(ap, x) ((void)(__vcrt_assert_va_start_is_not_reference<decltype(x)>(), __crt_va_start_a(ap, x)))
+#else
+# define __crt_va_start(ap, x) __crt_va_start_a(ap, x)
+#endif
+
+/*_Check_return_opt_*/ _CRT_STDIO_INLINE int __cdecl
+wprintf(/*_In_z_ _Printf_format_string_*/ wchar_t const * const _Format, ...) {
+ int _Result;
+ va_list _ArgList;
+ __crt_va_start(_ArgList, _Format);
+ // _Result = _vfwprintf_l(stdout, _Format, NULL, _ArgList);
+ __crt_va_end(_ArgList);
+ return _Result;
+}
More information about the cfe-commits
mailing list