function(get_clang_resource_dir result_dir)
    execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-resource-dir
        OUTPUT_VARIABLE CLANG_RESOURCE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    file(TO_CMAKE_PATH "${CLANG_RESOURCE_DIR}" CLANG_RESOURCE_DIR)
    set(${result_dir} "${CLANG_RESOURCE_DIR}" PARENT_SCOPE)
endfunction()

if (ENABLE_ADDRESS_SANITIZER)
    if (WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
        add_cxx_compile_options(-fsanitize=address /clang:-fno-omit-frame-pointer)
        # FIXME: Windows on ARM
        link_libraries(clang_rt.asan_dynamic-x86_64.lib -wholearchive:clang_rt.asan_dynamic_runtime_thunk-x86_64.lib)
        get_clang_resource_dir(CLANG_RESOURCE_DIR)
        file(COPY "${CLANG_RESOURCE_DIR}/lib/windows/clang_rt.asan_dynamic-x86_64.dll" DESTINATION "${CMAKE_BINARY_DIR}/bin")
    else()
        add_cxx_compile_options(-fsanitize=address -fno-omit-frame-pointer)
        add_cxx_link_options(-fsanitize=address)
    endif()
endif()

if (ENABLE_MEMORY_SANITIZER)
    add_cxx_compile_options(-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer)
    add_cxx_link_options(-fsanitize=memory -fsanitize-memory-track-origins)
endif()

if (ENABLE_UNDEFINED_SANITIZER)
    if (WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
        add_cxx_compile_options(-fsanitize=undefined)
        # FIXME: Windows on ARM
        link_libraries(clang_rt.ubsan_standalone-x86_64.lib clang_rt.ubsan_standalone_cxx-x86_64.lib)
    else()
        add_cxx_compile_options(-fsanitize=undefined -fno-omit-frame-pointer)
        if (UNDEFINED_BEHAVIOR_IS_FATAL)
            add_cxx_compile_options(-fno-sanitize-recover=undefined)
        endif()
        if (APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang$" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "17")
            add_cxx_compile_options(-fno-sanitize=function)
        endif()
        add_cxx_link_options(-fsanitize=undefined)
    endif()
endif()
