From 56bf960629cb5accf0584b1aabb1a4d8191249d1 Mon Sep 17 00:00:00 2001 From: Pierre Gousseau Date: Tue, 13 Jun 2023 10:14:40 +0100 Subject: [PATCH] [CMake] Enable building with UBSAN + clang-cl on windows. Currently both ASAN and UBSAN are supported on Windows but only ASAN is enabled in LLVM build system. This patch enables the option to build LLVM with UBSAN on windows. Tested with clang-cl released in LLVM16. Submitting on behalf of @dwang. Reviewed by: andrewng, pgousseau Differential Revision: https://reviews.llvm.org/D151511 --- llvm/cmake/modules/HandleLLVMOptions.cmake | 50 ++++++++++++++++++------------ llvm/include/llvm/ADT/EpochTracker.h | 6 ++++ llvm/include/llvm/ADT/SmallPtrSet.h | 5 +-- llvm/include/llvm/ADT/StringMap.h | 5 +-- llvm/include/llvm/Support/AllocatorBase.h | 6 ++++ 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index 1c63db5..525ba48 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -849,7 +849,7 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND NOT LLVM_ENABLE_WARNINGS) endif() macro(append_common_sanitizer_flags) - if (NOT MSVC) + if (NOT MSVC OR CLANG_CL) # Append -fno-omit-frame-pointer and turn on debug info to get better # stack traces. add_flag_if_supported("-fno-omit-frame-pointer" FNO_OMIT_FRAME_POINTER) @@ -928,23 +928,18 @@ if(LLVM_USE_SANITIZER) message(FATAL_ERROR "This sanitizer not yet supported in a MinGW environment: ${LLVM_USE_SANITIZER}") endif() elseif(MSVC) - if (LLVM_USE_SANITIZER STREQUAL "Address") - append_common_sanitizer_flags() - append("/fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) - if (NOT CLANG_CL) - # Not compatible with /RTC flags. - foreach (flags_opt_to_scrub - CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}) - string (REGEX REPLACE "(^| )/RTC[1csu]*($| )" " " - "${flags_opt_to_scrub}" "${${flags_opt_to_scrub}}") - endforeach() + if (NOT LLVM_USE_SANITIZER MATCHES "^(Address|Undefined|Address;Undefined|Undefined;Address)$") + message(FATAL_ERROR "This sanitizer not yet supported in the MSVC environment: ${LLVM_USE_SANITIZER}") + endif() + append_common_sanitizer_flags() + if (LINKER_IS_LLD_LINK) + if (LLVM_HOST_TRIPLE MATCHES "i[2-6]86-.*") + set(arch "i386") + else() + set(arch "x86_64") endif() - if (LINKER_IS_LLD_LINK) - if (LLVM_HOST_TRIPLE MATCHES "i[2-6]86-.*") - set(arch "i386") - else() - set(arch "x86_64") - endif() + # Prepare ASAN runtime if needed + if (LLVM_USE_SANITIZER MATCHES ".*Address.*") if (${LLVM_USE_CRT_${uppercase_CMAKE_BUILD_TYPE}} MATCHES "^(MT|MTd)$") append("/wholearchive:clang_rt.asan-${arch}.lib /wholearchive:clang_rt.asan_cxx-${arch}.lib" CMAKE_EXE_LINKER_FLAGS) @@ -955,8 +950,25 @@ if(LLVM_USE_SANITIZER) CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() - else() - message(FATAL_ERROR "This sanitizer not yet supported in the MSVC environment: ${LLVM_USE_SANITIZER}") + endif() + if (LLVM_USE_SANITIZER MATCHES ".*Address.*") + if (NOT CLANG_CL) + append("/fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + # Not compatible with /RTC flags. + foreach (flags_opt_to_scrub + CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}) + string (REGEX REPLACE "(^| )/RTC[1csu]*($| )" " " + "${flags_opt_to_scrub}" "${${flags_opt_to_scrub}}") + endforeach() + else() + append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + endif() + if (LLVM_USE_SANITIZER MATCHES ".*Undefined.*") + if (NOT CLANG_CL) + message(FATAL_ERROR "This sanitizer is only supported by clang-cl: Undefined") + endif() + append(${LLVM_UBSAN_FLAGS} CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() else() message(FATAL_ERROR "LLVM_USE_SANITIZER is not supported on this platform.") diff --git a/llvm/include/llvm/ADT/EpochTracker.h b/llvm/include/llvm/ADT/EpochTracker.h index a639d1b..fc41d6f 100644 --- a/llvm/include/llvm/ADT/EpochTracker.h +++ b/llvm/include/llvm/ADT/EpochTracker.h @@ -23,6 +23,7 @@ namespace llvm { #if LLVM_ENABLE_ABI_BREAKING_CHECKS +#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE /// A base class for data structure classes wishing to make iterators /// ("handles") pointing into themselves fail-fast. When building without @@ -78,6 +79,11 @@ public: }; #else +#ifdef _MSC_VER +#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE __declspec(empty_bases) +#else +#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE +#endif // _MSC_VER class DebugEpochBase { public: diff --git a/llvm/include/llvm/ADT/SmallPtrSet.h b/llvm/include/llvm/ADT/SmallPtrSet.h index 3d8191b..4c06439 100644 --- a/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/llvm/include/llvm/ADT/SmallPtrSet.h @@ -264,8 +264,9 @@ protected: /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. template -class SmallPtrSetIterator : public SmallPtrSetIteratorImpl, - DebugEpochBase::HandleBase { +class LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE SmallPtrSetIterator + : public SmallPtrSetIteratorImpl, + DebugEpochBase::HandleBase { using PtrTraits = PointerLikeTypeTraits; public: diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h index 17e81bc..466f952 100644 --- a/llvm/include/llvm/ADT/StringMap.h +++ b/llvm/include/llvm/ADT/StringMap.h @@ -107,8 +107,9 @@ public: /// funky memory allocation and hashing things to make it extremely efficient, /// storing the string data *after* the value in the map. template -class StringMap : public StringMapImpl, - private detail::AllocatorHolder { +class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap + : public StringMapImpl, + private detail::AllocatorHolder { using AllocTy = detail::AllocatorHolder; public: diff --git a/llvm/include/llvm/Support/AllocatorBase.h b/llvm/include/llvm/Support/AllocatorBase.h index 278ec43..0442432 100644 --- a/llvm/include/llvm/Support/AllocatorBase.h +++ b/llvm/include/llvm/Support/AllocatorBase.h @@ -19,6 +19,12 @@ #ifndef LLVM_SUPPORT_ALLOCATORBASE_H #define LLVM_SUPPORT_ALLOCATORBASE_H +#ifdef _MSC_VER +#define LLVM_ALLOCATORHOLDER_EMPTYBASE __declspec(empty_bases) +#else +#define LLVM_ALLOCATORHOLDER_EMPTYBASE +#endif // _MSC_VER + #include "llvm/Support/Compiler.h" #include "llvm/Support/MemAlloc.h" #include -- 2.7.4