Add Tests with Address & UB Sanitizers Enabled (#285)
* Getting address sanitizer to work with MSVC and compile with Clang * Some CMake fixups * Get it working for Clang * Enable UBSan * Still need to debug * Temporarily revert use of /Ob2 due to bug in Clang * Update tests/sanitize-address/CMakeLists.txt * Update scripts/azure-pipelines.yml
This commit is contained in:
Родитель
89ecb2bc98
Коммит
ab663cfd89
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.11)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(WIL)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
# E.g. replace_cxx_flag("/W[0-4]", "/W4")
|
||||
# This is unfortunately still needed to disable exceptions/RTTI since modern CMake still has no builtin support...
|
||||
# E.g. replace_cxx_flag("/EHsc", "/EHs-c-")
|
||||
macro(replace_cxx_flag pattern text)
|
||||
foreach (flag
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
|
@ -10,66 +11,61 @@ macro(replace_cxx_flag pattern text)
|
|||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(append_cxx_flag text)
|
||||
foreach (flag
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
|
||||
string(APPEND ${flag} " ${text}")
|
||||
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Fixup default compiler settings
|
||||
add_compile_options(
|
||||
# Be as strict as reasonably possible, since we want to support consumers using strict warning levels
|
||||
/W4 /WX
|
||||
)
|
||||
|
||||
# Be as strict as reasonably possible, since we want to support consumers using strict warning levels
|
||||
replace_cxx_flag("/W[0-4]" "/W4")
|
||||
append_cxx_flag("/WX")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(
|
||||
# Ignore some pedantic warnings enabled by '-Wextra'
|
||||
-Wno-missing-field-initializers
|
||||
|
||||
# We want to be as conformant as possible, so tell MSVC to not be permissive (note that this has no effect on clang-cl)
|
||||
append_cxx_flag("/permissive-")
|
||||
|
||||
# wistd::function has padding due to alignment. This is expected
|
||||
append_cxx_flag("/wd4324")
|
||||
|
||||
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||
# Ignore a few Clang warnings. We may want to revisit in the future to see if any of these can/should be removed
|
||||
append_cxx_flag("-Wno-switch")
|
||||
append_cxx_flag("-Wno-c++17-compat-mangling")
|
||||
append_cxx_flag("-Wno-missing-field-initializers")
|
||||
# Ignore some pedantic warnings enabled by '-Wpedantic'
|
||||
-Wno-language-extension-token
|
||||
-Wno-c++17-attribute-extensions
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
-Wno-extra-semi
|
||||
|
||||
# For tests, we want to be able to test self assignment, so disable this warning
|
||||
append_cxx_flag("-Wno-self-assign-overloaded")
|
||||
append_cxx_flag("-Wno-self-move")
|
||||
-Wno-self-assign-overloaded
|
||||
-Wno-self-move
|
||||
|
||||
# C++/WinRT does not declare 'override' in a number of places
|
||||
append_cxx_flag("-Wno-inconsistent-missing-override")
|
||||
# clang needs this to enable _InterlockedCompareExchange128
|
||||
-mcx16
|
||||
|
||||
# clang-cl does not understand the /permissive- flag (or at least it opts to ignore it). We can achieve similar
|
||||
# results through the following flags.
|
||||
append_cxx_flag("-fno-delayed-template-parsing")
|
||||
|
||||
# clang-cl needs this to enable _InterlockedCompareExchange128
|
||||
append_cxx_flag("-mcx16")
|
||||
# We don't want legacy MSVC conformance
|
||||
-fno-delayed-template-parsing
|
||||
|
||||
# NOTE: Windows headers not clean enough for us to realistically attempt to start fixing these errors yet. That
|
||||
# said, errors that originate from WIL headers may benefit
|
||||
# append_cxx_flag("-fno-ms-compatibility")
|
||||
# append_cxx_flag("-ferror-limit=999")
|
||||
# append_cxx_flag("-fmacro-backtrace-limit=0")
|
||||
# -fno-ms-compatibility turns off preprocessor compatability, which currently only works when __VA_OPT__ support is
|
||||
# available (i.e. >= C++20)
|
||||
# append_cxx_flag("-Xclang -std=c++2a")
|
||||
# -fno-ms-compatibility
|
||||
# -ferror-limit=999
|
||||
# -fmacro-backtrace-limit=0
|
||||
|
||||
# -fno-ms-compatibility turns off preprocessor compatability, which currently only works when __VA_OPT__ support
|
||||
# is available (i.e. >= C++20)
|
||||
# -Xclang -std=c++2a
|
||||
)
|
||||
else()
|
||||
# Flags that are either ignored or unrecognized by clang-cl
|
||||
add_compile_options(
|
||||
# We want to be as conformant as possible, so tell MSVC to not be permissive (note that this has no effect on clang-cl)
|
||||
/permissive-
|
||||
|
||||
# wistd::function has padding due to alignment. This is expected
|
||||
/wd4324
|
||||
|
||||
# TODO: https://github.com/Microsoft/wil/issues/6
|
||||
# append_cxx_flag("/experimental:preprocessor")
|
||||
# /experimental:preprocessor
|
||||
|
||||
# CRT headers are not yet /experimental:preprocessor clean, so work around the known issues
|
||||
# append_cxx_flag("/Wv:18")
|
||||
# /Wv:18
|
||||
|
||||
append_cxx_flag("/bigobj")
|
||||
# Some tests have a LOT of template instantiations
|
||||
/bigobj
|
||||
|
||||
# NOTE: Temporary workaround while https://github.com/microsoft/wil/issues/102 is being investigated
|
||||
append_cxx_flag("/d2FH4-")
|
||||
/d2FH4-
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -250,21 +250,24 @@ namespace wistd // ("Windows Implementation" std)
|
|||
return _Invoker::__call(__f_, wistd::forward<_ArgTypes>(__arg)...);
|
||||
}
|
||||
|
||||
} // __function
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __WI_LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
|
||||
: public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
|
||||
public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
|
||||
{
|
||||
// 'wistd::function' is most similar to 'inplace_function' in that it _only_ permits holding function objects
|
||||
// that can fit within its internal buffer. Therefore, we expand this size to accommodate space for at least 12
|
||||
// pointers (__base vtable takes an additional one).
|
||||
static constexpr size_t __buffer_size = 13 * sizeof(void*);
|
||||
constexpr const size_t __buffer_size = 13 * sizeof(void*);
|
||||
|
||||
} // __function
|
||||
|
||||
// NOTE: The extra 'alignas' here is to work around the x86 compiler bug mentioned in
|
||||
// https://github.com/microsoft/STL/issues/1533 to force alignment on the stack
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __WI_LIBCPP_TEMPLATE_VIS __WI_ALIGNAS(typename aligned_storage<__function::__buffer_size>::type)
|
||||
function<_Rp(_ArgTypes...)>
|
||||
: public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
|
||||
public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
|
||||
{
|
||||
using __base = __function::__base<_Rp(_ArgTypes...)>;
|
||||
__WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS
|
||||
typename aligned_storage<__buffer_size>::type __buf_;
|
||||
typename aligned_storage<__function::__buffer_size>::type __buf_;
|
||||
__base* __f_;
|
||||
|
||||
__WI_LIBCPP_NO_CFI static __base *__as_base(void *p) {
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace wistd // ("Windows Implementation" std)
|
|||
struct __second_tag {};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
class __compressed_pair : private __compressed_pair_elem<_T1, 0>,
|
||||
class __declspec(empty_bases) __compressed_pair : private __compressed_pair_elem<_T1, 0>,
|
||||
private __compressed_pair_elem<_T2, 1> {
|
||||
using _Base1 = __compressed_pair_elem<_T1, 0>;
|
||||
using _Base2 = __compressed_pair_elem<_T2, 1>;
|
||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
displayName: 'Install Clang'
|
||||
|
||||
- script: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsamd64_x86.bat"
|
||||
if %ERRORLEVEL% NEQ 0 goto :eof
|
||||
|
||||
call scripts\init_all.cmd --fast
|
||||
|
@ -37,5 +37,9 @@ jobs:
|
|||
call scripts\build_all.cmd
|
||||
displayName: 'Build x64'
|
||||
|
||||
- script: call scripts\runtests.cmd ~[LocalOnly]
|
||||
# NOTE: We run the tests in the 32-bit cross-tools window out of convenience as this adds all necessary directories to
|
||||
# the PATH that are necessary for finding the ASan/UBSan DLLs
|
||||
- script: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsamd64_x86.bat""
|
||||
call scripts\runtests.cmd ~[LocalOnly]
|
||||
displayName: 'Run Tests'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@echo off
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
set BUILD_ROOT=%~dp0\..\build
|
||||
|
@ -15,23 +16,15 @@ if "%Platform%"=="x64" (
|
|||
exit /B 1
|
||||
)
|
||||
|
||||
call :build clang debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build clang release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build clang relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build clang minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
set COMPILERS=clang msvc
|
||||
set BUILD_TYPES=debug release relwithdebinfo minsizerel
|
||||
|
||||
call :build msvc debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build msvc release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build msvc relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :build msvc minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
for %%c in (%COMPILERS%) do (
|
||||
for %%b in (%BUILD_TYPES%) do (
|
||||
call :build %%c %%b
|
||||
if !ERRORLEVEL! NEQ 0 ( goto :eof )
|
||||
)
|
||||
)
|
||||
|
||||
echo All build completed successfully!
|
||||
|
||||
|
@ -47,5 +40,6 @@ if not exist %BUILD_DIR% (
|
|||
pushd %BUILD_DIR%
|
||||
echo Building from %CD%
|
||||
ninja
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
popd
|
||||
goto :eof
|
||||
exit /B %EXIT_CODE%
|
||||
|
|
|
@ -10,8 +10,8 @@ goto :init
|
|||
:usage
|
||||
echo USAGE:
|
||||
echo init.cmd [--help] [-c^|--compiler ^<clang^|msvc^>] [-g^|--generator ^<ninja^|msbuild^>]
|
||||
echo [-b^|--build-type ^<debug^|release^|relwithdebinfo^|minsizerel^>] [-l^|--linker link^|lld-link]
|
||||
echo [-v^|--version X.Y.Z] [--cppwinrt ^<version^>] [--fast]
|
||||
echo [-b^|--build-type ^<debug^|release^|relwithdebinfo^|minsizerel^>] [-v^|--version X.Y.Z]
|
||||
echo [--cppwinrt ^<version^>] [--fast]
|
||||
echo.
|
||||
echo ARGUMENTS
|
||||
echo -c^|--compiler Controls the compiler used, either 'clang' (the default) or 'msvc'
|
||||
|
@ -31,7 +31,6 @@ goto :init
|
|||
set COMPILER=
|
||||
set GENERATOR=
|
||||
set BUILD_TYPE=
|
||||
set LINKER=
|
||||
set CMAKE_ARGS=
|
||||
set BITNESS=
|
||||
set VERSION=
|
||||
|
@ -90,21 +89,6 @@ goto :init
|
|||
goto :parse
|
||||
)
|
||||
|
||||
set LINKER_SET=0
|
||||
if /I "%~1"=="-l" set LINKER_SET=1
|
||||
if /I "%~1"=="--linker" set LINKER_SET=1
|
||||
if %LINKER_SET%==1 (
|
||||
if "%LINKER%" NEQ "" echo ERROR: Linker already specified & call :usage & exit /B 1
|
||||
|
||||
if /I "%~2"=="link" set LINKER=link
|
||||
if /I "%~2"=="lld-link" set LINKER=lld-link
|
||||
if "!LINKER!"=="" echo ERROR: Unrecognized/missing linker %~2 & call :usage & exit /B 1
|
||||
|
||||
shift
|
||||
shift
|
||||
goto :parse
|
||||
)
|
||||
|
||||
set VERSION_SET=0
|
||||
if /I "%~1"=="-v" set VERSION_SET=1
|
||||
if /I "%~1"=="--version" set VERSION_SET=1
|
||||
|
@ -145,9 +129,6 @@ goto :init
|
|||
:: Check for conflicting arguments
|
||||
if "%GENERATOR%"=="msbuild" (
|
||||
if "%COMPILER%"=="clang" echo ERROR: Cannot use Clang with MSBuild & exit /B 1
|
||||
|
||||
:: While CMake won't give an error, specifying the linker won't actually have any effect with the VS generator
|
||||
if "%LINKER%"=="lld-link" echo ERROR: Cannot use lld-link with MSBuild & exit /B 1
|
||||
)
|
||||
|
||||
:: Select defaults
|
||||
|
@ -158,8 +139,6 @@ goto :init
|
|||
|
||||
if "%BUILD_TYPE%"=="" set BUILD_TYPE=debug
|
||||
|
||||
if "%LINKER%"=="" set LINKER=link
|
||||
|
||||
:: Formulate CMake arguments
|
||||
if %GENERATOR%==ninja set CMAKE_ARGS=%CMAKE_ARGS% -G Ninja
|
||||
|
||||
|
@ -180,10 +159,6 @@ goto :init
|
|||
set CMAKE_ARGS=%CMAKE_ARGS% -DCMAKE_SYSTEM_VERSION=10.0
|
||||
)
|
||||
|
||||
if %LINKER%==lld-link (
|
||||
set CMAKE_ARGS=%CMAKE_ARGS% -DCMAKE_LINKER=lld-link
|
||||
)
|
||||
|
||||
if "%VERSION%" NEQ "" set CMAKE_ARGS=%CMAKE_ARGS% -DWIL_BUILD_VERSION=%VERSION%
|
||||
|
||||
if "%CPPWINRT_VERSION%" NEQ "" set CMAKE_ARGS=%CMAKE_ARGS% -DCPPWINRT_VERSION=%CPPWINRT_VERSION%
|
||||
|
@ -208,7 +183,6 @@ goto :init
|
|||
:: Run CMake
|
||||
pushd %BUILD_DIR%
|
||||
echo Using compiler....... %COMPILER%
|
||||
echo Using linker......... %LINKER%
|
||||
echo Using architecture... %Platform%
|
||||
echo Using build type..... %BUILD_TYPE%
|
||||
echo Using build root..... %CD%
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
@echo off
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
:: NOTE: Architecture is picked up from the command window, so we can't control that here :(
|
||||
set COMPILERS=clang msvc
|
||||
set BUILD_TYPES=debug relwithdebinfo
|
||||
|
||||
call %~dp0\init.cmd -c clang -g ninja -b debug %*
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call %~dp0\init.cmd -c clang -g ninja -b relwithdebinfo %*
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
|
||||
call %~dp0\init.cmd -c msvc -g ninja -b debug %*
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call %~dp0\init.cmd -c msvc -g ninja -b relwithdebinfo %*
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
for %%c in (%COMPILERS%) do (
|
||||
for %%b in (%BUILD_TYPES%) do (
|
||||
call %~dp0\init.cmd -c %%c -g ninja -b %%b %*
|
||||
if !ERRORLEVEL! NEQ 0 ( goto :eof )
|
||||
)
|
||||
)
|
||||
|
|
|
@ -7,41 +7,18 @@ set TEST_ARGS=%*
|
|||
set BUILD_ROOT=%~dp0\..\build
|
||||
|
||||
:: Unlike building, we don't need to limit ourselves to the Platform of the command window
|
||||
call :execute_tests clang64debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang64release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang64relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang64minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
set COMPILERS=clang msvc
|
||||
set ARCHITECTURES=32 64
|
||||
set BUILD_TYPES=debug release relwithdebinfo minsizerel
|
||||
|
||||
call :execute_tests clang32debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang32release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang32relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests clang32minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
|
||||
call :execute_tests msvc64debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc64release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc64relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc64minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
|
||||
call :execute_tests msvc32debug
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc32release
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc32relwithdebinfo
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
call :execute_tests msvc32minsizerel
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :eof )
|
||||
for %%c in (%COMPILERS%) do (
|
||||
for %%a in (%ARCHITECTURES%) do (
|
||||
for %%b in (%BUILD_TYPES%) do (
|
||||
call :execute_tests %%c%%a%%b
|
||||
if !ERRORLEVEL! NEQ 0 ( goto :eof )
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
goto :eof
|
||||
|
||||
|
@ -52,18 +29,24 @@ if not exist %BUILD_DIR% ( goto :eof )
|
|||
pushd %BUILD_DIR%
|
||||
echo Running tests from %CD%
|
||||
call :execute_test app witest.app.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( popd && goto :eof )
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test cpplatest witest.cpplatest.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( popd && goto :eof )
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test noexcept witest.noexcept.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( popd && goto :eof )
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test normal witest.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( popd && goto :eof )
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test sanitize-address witest.asan.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test sanitize-undefined-behavior witest.ubsan.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
call :execute_test win7 witest.win7.exe
|
||||
if %ERRORLEVEL% NEQ 0 ( popd && goto :eof )
|
||||
popd
|
||||
if %ERRORLEVEL% NEQ 0 ( goto :execute_tests_done )
|
||||
|
||||
goto :eof
|
||||
:execute_tests_done
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
popd
|
||||
exit /B %EXIT_CODE%
|
||||
|
||||
:execute_test
|
||||
if not exist tests\%1\%2 ( goto :eof )
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/common_build_flags.cmake)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
|
||||
# All projects need to reference the WIL headers
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
|
@ -38,6 +38,14 @@ if (${FAST_BUILD})
|
|||
add_definitions(-DCATCH_CONFIG_FAST_COMPILE -DWIL_FAST_BUILD)
|
||||
endif()
|
||||
|
||||
# For some unknown reason, 'RelWithDebInfo' compiles with '/Ob1' as opposed to '/Ob2' which prevents inlining of
|
||||
# functions not marked 'inline'. The reason we prefer 'RelWithDebInfo' over 'Release' is to get debug info, so manually
|
||||
# revert to the desired (and default) inlining behavior as that exercises more interesting code paths
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
|
||||
# TODO: This is currently blocked by an apparent Clang bug: https://github.com/llvm/llvm-project/issues/59690
|
||||
# replace_cxx_flag("/Ob1" "/Ob2")
|
||||
endif()
|
||||
|
||||
set(COMMON_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CommonTests.cpp
|
||||
|
@ -58,3 +66,32 @@ add_subdirectory(cpplatest)
|
|||
add_subdirectory(noexcept)
|
||||
add_subdirectory(normal)
|
||||
add_subdirectory(win7)
|
||||
|
||||
set(DEBUG_BUILD FALSE)
|
||||
set(HAS_DEBUG_INFO FALSE)
|
||||
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||
set(DEBUG_BUILD TRUE)
|
||||
set(HAS_DEBUG_INFO TRUE)
|
||||
elseif(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
|
||||
set(HAS_DEBUG_INFO TRUE)
|
||||
endif()
|
||||
|
||||
set(ASAN_AVAILABLE FALSE)
|
||||
set(UBSAN_AVAILABLE FALSE)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
# Address Sanitizer is available for all architectures and build types, but warns/errors if debug info is not enabled
|
||||
set(ASAN_AVAILABLE ${HAS_DEBUG_INFO})
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Address Sanitizer is not available with debug libraries
|
||||
set(ASAN_AVAILABLE NOT ${DEBUG_BUILD})
|
||||
set(UBSAN_AVAILABLE NOT ${DEBUG_BUILD})
|
||||
endif()
|
||||
|
||||
if (${ASAN_AVAILABLE})
|
||||
add_subdirectory(sanitize-address)
|
||||
endif()
|
||||
|
||||
if (${UBSAN_AVAILABLE})
|
||||
add_subdirectory(sanitize-undefined-behavior)
|
||||
endif()
|
||||
|
|
|
@ -159,7 +159,7 @@ enum class EClassTest
|
|||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(EClassTest);
|
||||
|
||||
enum ERawTest
|
||||
enum ERawTest : unsigned int
|
||||
{
|
||||
ER_None = 0x0,
|
||||
ER_One = 0x1,
|
||||
|
|
|
@ -240,8 +240,8 @@ void DoHStringDifferentValueComparisonTest(const wchar_t (&lhs)[LhsSize], const
|
|||
DoHStringComparisonTest<InhibitArrayReferences, IgnoreCase>(lhsUniqueStr, rhsUniqueStr, 1);
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
std::wstring lhsWstr(lhs, 7);
|
||||
std::wstring rhsWstr(rhs, 7);
|
||||
std::wstring lhsWstr(lhs);
|
||||
std::wstring rhsWstr(rhs);
|
||||
DoHStringComparisonTest<InhibitArrayReferences, IgnoreCase>(lhsWstr, rhsWstr, 1);
|
||||
DoHStringComparisonTest<InhibitArrayReferences, IgnoreCase>(lhsWstr, rhs, 1);
|
||||
DoHStringComparisonTest<InhibitArrayReferences, IgnoreCase>(lhsWstr, rhsNonConstArray, 1);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
project(witest.app)
|
||||
add_executable(witest.app)
|
||||
|
||||
add_definitions(-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP)
|
||||
target_compile_definitions(witest.app PRIVATE
|
||||
-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP
|
||||
)
|
||||
|
||||
target_sources(witest.app PUBLIC
|
||||
target_sources(witest.app PRIVATE
|
||||
${COMMON_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../UniqueWinRTEventTokenTests.cpp
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
add_executable(witest.cpplatest)
|
||||
|
||||
# Compilers often don't use the latest C++ standard as the default. Periodically update this value (possibly conditioned
|
||||
# on compiler) as new standards are ratified/support is available
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
target_compile_features(witest.cpplatest PRIVATE cxx_std_20)
|
||||
|
||||
project(witest.cpplatest)
|
||||
add_executable(witest.cpplatest)
|
||||
|
||||
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Clang is not compatible with the experimental coroutine header, so temporarily disable some headers until full
|
||||
# C++20 support is available
|
||||
set(COROUTINE_SOURCES)
|
||||
|
@ -15,7 +14,7 @@ else()
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/../ComApartmentVariableTests.cpp)
|
||||
endif()
|
||||
|
||||
target_sources(witest.cpplatest PUBLIC
|
||||
target_sources(witest.cpplatest PRIVATE
|
||||
${COMMON_SOURCES}
|
||||
${COROUTINE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../CppWinRTTests.cpp
|
||||
|
|
|
@ -6,3 +6,15 @@
|
|||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
#if WITEST_ADDRESS_SANITIZER
|
||||
extern "C" __declspec(dllexport)
|
||||
const char* __asan_default_options()
|
||||
{
|
||||
return
|
||||
// Tests validate OOM, so this is expected
|
||||
"allocator_may_return_null=1"
|
||||
// Some structs in Windows have dynamic size where we over-allocate for extra data past the end
|
||||
":new_delete_type_mismatch=0";
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
|
||||
project(witest.noexcept)
|
||||
add_executable(witest.noexcept)
|
||||
|
||||
# Turn off exceptions for this test
|
||||
replace_cxx_flag("/EHsc" "")
|
||||
add_definitions(-DCATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||
replace_cxx_flag("/EHsc" "/EHs-c-")
|
||||
target_compile_definitions(witest.noexcept PRIVATE
|
||||
-DCATCH_CONFIG_DISABLE_EXCEPTIONS
|
||||
)
|
||||
|
||||
# Catch2 has a no exceptions mode (configured above), however still includes STL headers which contain try...catch
|
||||
# statements... Thankfully MSVC just gives us a warning that we can disable
|
||||
append_cxx_flag("/wd4530")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
target_compile_options(witest.noexcept PRIVATE /wd4530)
|
||||
endif()
|
||||
|
||||
target_sources(witest.noexcept PUBLIC
|
||||
target_sources(witest.noexcept PRIVATE
|
||||
${COMMON_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../UniqueWinRTEventTokenTests.cpp
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
project(witest)
|
||||
add_executable(witest)
|
||||
|
||||
target_sources(witest PUBLIC
|
||||
target_sources(witest PRIVATE
|
||||
${COMMON_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
add_executable(witest.asan)
|
||||
|
||||
target_compile_options(witest.asan PRIVATE -fsanitize=address)
|
||||
|
||||
target_compile_definitions(witest.asan PRIVATE
|
||||
-DCATCH_CONFIG_NO_WINDOWS_SEH # ASAN relies on first chance AVs
|
||||
-DWITEST_ADDRESS_SANITIZER # To conditionally enable/disable code
|
||||
)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
target_compile_definitions(witest.asan PRIVATE
|
||||
# Not compatible with using lld-link
|
||||
-D_DISABLE_VECTOR_ANNOTATION
|
||||
# See below; not compatible with exceptions
|
||||
-DCATCH_CONFIG_DISABLE_EXCEPTIONS
|
||||
)
|
||||
|
||||
# Clang ASan on Windows has issues with exceptions: https://github.com/google/sanitizers/issues/749
|
||||
replace_cxx_flag("/EHsc" "/EHs-c-")
|
||||
|
||||
if ($ENV{Platform} STREQUAL "x86")
|
||||
target_link_libraries(witest.asan PRIVATE
|
||||
clang_rt.asan_dynamic-i386.lib
|
||||
clang_rt.asan_dynamic_runtime_thunk-i386.lib
|
||||
)
|
||||
else()
|
||||
target_link_libraries(witest.asan PRIVATE
|
||||
clang_rt.asan_dynamic-x86_64.lib
|
||||
clang_rt.asan_dynamic_runtime_thunk-x86_64.lib
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
# Using exceptions, so we can compile the STL tests
|
||||
set(EXTRA_SOURCES
|
||||
${EXTRA_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(witest.asan PUBLIC
|
||||
${COMMON_SOURCES}
|
||||
${EXTRA_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../UniqueWinRTEventTokenTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WatcherTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WinRTTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WinVerifyTrustTest.cpp
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
add_executable(witest.ubsan)
|
||||
|
||||
target_compile_options(witest.ubsan PRIVATE
|
||||
-fsanitize=undefined
|
||||
-fno-sanitize-recover=undefined # So we get test failures
|
||||
)
|
||||
|
||||
target_compile_definitions(witest.ubsan PRIVATE
|
||||
-DWITEST_UB_SANITIZER # To conditionally enable/disable code
|
||||
)
|
||||
|
||||
# UBSan libraries were built assuming static linking
|
||||
set_property(TARGET witest.ubsan
|
||||
PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
||||
|
||||
target_sources(witest.ubsan PUBLIC
|
||||
${COMMON_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../UniqueWinRTEventTokenTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WatcherTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WinRTTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../WinVerifyTrustTest.cpp
|
||||
)
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
project(witest.win7)
|
||||
add_executable(witest.win7)
|
||||
|
||||
add_definitions("-D_WIN32_WINNT=0x0601")
|
||||
target_compile_definitions(witest.win7 PRIVATE
|
||||
-D_WIN32_WINNT=0x0601
|
||||
)
|
||||
|
||||
target_sources(witest.win7 PUBLIC
|
||||
target_sources(witest.win7 PRIVATE
|
||||
${COMMON_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
|
||||
|
|
|
@ -12,14 +12,6 @@
|
|||
#pragma once
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpragma-pack"
|
||||
#pragma clang diagnostic ignored "-Wunused-value"
|
||||
#pragma clang diagnostic ignored "-Wmicrosoft-sealed"
|
||||
#pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
#endif
|
||||
|
||||
#pragma region includes
|
||||
|
||||
#include <inspectable.h>
|
||||
|
@ -599,6 +591,8 @@ struct VerifyInheritanceHelper<I, Nil>
|
|||
|
||||
} // namespace Details
|
||||
|
||||
// note: Due to potential shutdown ordering issues, the results of GetModuleBase
|
||||
// should always be checked for null on reference counting and cleanup operations.
|
||||
inline Details::ModuleBase* GetModuleBase() throw()
|
||||
{
|
||||
return Details::ModuleBase::module_;
|
||||
|
@ -1523,6 +1517,8 @@ private:
|
|||
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
|
||||
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointer
|
||||
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointer
|
||||
#define UnknownInterlockedCompareExchangeForIncrement InterlockedCompareExchange
|
||||
#define UnknownInterlockedCompareExchangeForRelease InterlockedCompareExchange
|
||||
|
||||
#elif defined(_ARM_)
|
||||
|
||||
|
@ -1532,6 +1528,8 @@ private:
|
|||
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
|
||||
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence
|
||||
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease
|
||||
#define UnknownInterlockedCompareExchangeForIncrement InterlockedCompareExchangeNoFence
|
||||
#define UnknownInterlockedCompareExchangeForRelease InterlockedCompareExchangeRelease
|
||||
|
||||
#elif defined(_ARM64_)
|
||||
|
||||
|
@ -1541,6 +1539,8 @@ private:
|
|||
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
|
||||
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence
|
||||
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease
|
||||
#define UnknownInterlockedCompareExchangeForIncrement InterlockedCompareExchangeNoFence
|
||||
#define UnknownInterlockedCompareExchangeForRelease InterlockedCompareExchangeRelease
|
||||
|
||||
#else
|
||||
|
||||
|
@ -1562,6 +1562,37 @@ class __declspec(novtable) RuntimeClassImpl;
|
|||
// PREFast cannot see through template instantiation for AsIID()
|
||||
#pragma warning(disable: 6388)
|
||||
|
||||
// Reference counting functions that check overflow. If overflow is detected, ref count value will stop at LONG_MAX, and the object being
|
||||
// reference-counted will be leaked.
|
||||
inline unsigned long SafeUnknownIncrementReference(long volatile &refcount) throw()
|
||||
{
|
||||
long oldValue = refcount;
|
||||
while (oldValue != LONG_MAX && (UnknownInterlockedCompareExchangeForIncrement(&refcount, oldValue + 1, oldValue) != oldValue))
|
||||
{
|
||||
oldValue = refcount;
|
||||
}
|
||||
|
||||
if (oldValue != LONG_MAX)
|
||||
{
|
||||
return oldValue + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned long SafeUnknownDecrementReference(long volatile &refcount) throw()
|
||||
{
|
||||
long oldValue = refcount;
|
||||
while (oldValue != LONG_MAX && (UnknownInterlockedCompareExchangeForRelease(&refcount, oldValue - 1, oldValue) != oldValue))
|
||||
{
|
||||
oldValue = refcount;
|
||||
}
|
||||
|
||||
return oldValue - 1;
|
||||
}
|
||||
|
||||
template <class RuntimeClassFlagsT, bool implementsWeakReferenceSource, bool implementsFtmBase, typename ...TInterfaces>
|
||||
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, false, implementsFtmBase, TInterfaces...> :
|
||||
public Details::AdjustImplements<RuntimeClassFlagsT, false, TInterfaces...>::Type,
|
||||
|
@ -1624,7 +1655,7 @@ protected:
|
|||
#ifdef _PERF_COUNTERS
|
||||
IncrementAddRefCount();
|
||||
#endif
|
||||
return UnknownIncrementReference(&refcount_);
|
||||
return SafeUnknownIncrementReference(refcount_);
|
||||
}
|
||||
|
||||
unsigned long InternalRelease() throw()
|
||||
|
@ -1634,7 +1665,7 @@ protected:
|
|||
#endif
|
||||
// A release fence is required to ensure all guarded memory accesses are
|
||||
// complete before any thread can begin destroying the object.
|
||||
unsigned long newValue = UnknownDecrementReference(&refcount_);
|
||||
unsigned long newValue = SafeUnknownDecrementReference(refcount_);
|
||||
if (newValue == 0)
|
||||
{
|
||||
// An acquire fence is required before object destruction to ensure
|
||||
|
@ -1786,7 +1817,7 @@ protected:
|
|||
#ifdef _PERF_COUNTERS
|
||||
IncrementAddRefCount();
|
||||
#endif
|
||||
return UnknownIncrementReference(&refcount_);
|
||||
return SafeUnknownIncrementReference(refcount_);
|
||||
}
|
||||
|
||||
unsigned long InternalRelease() throw()
|
||||
|
@ -1796,7 +1827,7 @@ protected:
|
|||
#endif
|
||||
// A release fence is required to ensure all guarded memory accesses are
|
||||
// complete before any thread can begin destroying the object.
|
||||
unsigned long newValue = UnknownDecrementReference(&refcount_);
|
||||
unsigned long newValue = SafeUnknownDecrementReference(refcount_);
|
||||
if (newValue == 0)
|
||||
{
|
||||
// An acquire fence is required before object destruction to ensure
|
||||
|
@ -1828,14 +1859,14 @@ public:
|
|||
|
||||
unsigned long IncrementStrongReference() throw()
|
||||
{
|
||||
return UnknownIncrementReference(&strongRefCount_);
|
||||
return SafeUnknownIncrementReference(strongRefCount_);
|
||||
}
|
||||
|
||||
unsigned long DecrementStrongReference() throw()
|
||||
{
|
||||
// A release fence is required to ensure all guarded memory accesses are
|
||||
// complete before any thread can begin destroying the object.
|
||||
unsigned long newValue = UnknownDecrementReference(&strongRefCount_);
|
||||
unsigned long newValue = SafeUnknownDecrementReference(strongRefCount_);
|
||||
if (newValue == 0)
|
||||
{
|
||||
// An acquire fence is required before object destruction to ensure
|
||||
|
@ -2089,7 +2120,7 @@ inline INT_PTR EncodeWeakReferencePointer(Microsoft::WRL::Details::WeakReference
|
|||
|
||||
inline Microsoft::WRL::Details::WeakReferenceImpl* DecodeWeakReferencePointer(INT_PTR value)
|
||||
{
|
||||
return reinterpret_cast<Microsoft::WRL::Details::WeakReferenceImpl*>(value << 1);
|
||||
return reinterpret_cast<Microsoft::WRL::Details::WeakReferenceImpl*>(static_cast<UINT_PTR>(value) << 1);
|
||||
}
|
||||
|
||||
#pragma warning(pop) // C6388
|
||||
|
@ -2134,6 +2165,7 @@ class RuntimeClass<InterfaceListHelper<TInterfaces...>, RuntimeClassFlagsT, impl
|
|||
public RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, implementsInspectable, implementsFtmBase, TInterfaces...>
|
||||
{
|
||||
protected:
|
||||
#pragma warning(suppress: 6101) // Function only used internally and the value of 'ppvObject' is only used if *handled is true
|
||||
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
|
||||
{
|
||||
*handled = false;
|
||||
|
@ -2153,6 +2185,7 @@ class RuntimeClass :
|
|||
RuntimeClass(const RuntimeClass&);
|
||||
RuntimeClass& operator=(const RuntimeClass&);
|
||||
protected:
|
||||
#pragma warning(suppress: 6101) // Function only used internally and the value of 'ppvObject' is only used if *handled is true
|
||||
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
|
||||
{
|
||||
*handled = false;
|
||||
|
@ -2177,6 +2210,7 @@ class RuntimeClass<RuntimeClassFlags<classFlags>, TInterfaces...> :
|
|||
RuntimeClass(const RuntimeClass&);
|
||||
RuntimeClass& operator=(const RuntimeClass&);
|
||||
protected:
|
||||
#pragma warning(suppress: 6101) // Function only used internally and the value of 'ppvObject' is only used if *handled is true
|
||||
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
|
||||
{
|
||||
*handled = false;
|
||||
|
@ -2196,8 +2230,8 @@ public:
|
|||
|
||||
namespace Details
|
||||
{
|
||||
//Weak reference implementation
|
||||
class WeakReferenceImpl sealed:
|
||||
// Weak reference implementation
|
||||
class WeakReferenceImpl final :
|
||||
public ::Microsoft::WRL::RuntimeClass<RuntimeClassFlags<ClassicCom>, IWeakReference>,
|
||||
public StrongReference
|
||||
{
|
||||
|
@ -2289,6 +2323,11 @@ unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInter
|
|||
{
|
||||
if (!IsValueAPointerToWeakReference(currentValue.rawValue))
|
||||
{
|
||||
if (static_cast<long>(currentValue.refCount) == LONG_MAX)
|
||||
{
|
||||
return LONG_MAX;
|
||||
}
|
||||
|
||||
UINT_PTR updateValue = currentValue.refCount + 1;
|
||||
|
||||
#ifdef __WRL_UNITTEST__
|
||||
|
@ -2324,6 +2363,11 @@ unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInter
|
|||
{
|
||||
if (!IsValueAPointerToWeakReference(currentValue.rawValue))
|
||||
{
|
||||
if (static_cast<long>(currentValue.refCount) == LONG_MAX)
|
||||
{
|
||||
return LONG_MAX - 1;
|
||||
}
|
||||
|
||||
UINT_PTR updateValue = currentValue.refCount - 1;
|
||||
|
||||
#ifdef __WRL_UNITTEST__
|
||||
|
@ -2432,8 +2476,13 @@ public:
|
|||
// Allocate memory with operator new(size, nothrow) only
|
||||
// This will allow developer to override one operator only
|
||||
// to enable different memory allocation model
|
||||
buffer_ = (char*) (operator new (sizeof(T), std::nothrow));
|
||||
return buffer_;
|
||||
#ifdef __cpp_aligned_new
|
||||
if constexpr (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
return buffer_ = (char*) operator new (sizeof(T), static_cast<std::align_val_t>(alignof(T)), ::std::nothrow);
|
||||
}
|
||||
#endif // /std:c++17 or later
|
||||
return buffer_ = (char*) operator new (sizeof(T), ::std::nothrow);
|
||||
}
|
||||
|
||||
void Detach() throw()
|
||||
|
@ -2526,7 +2575,7 @@ namespace Details
|
|||
{ \
|
||||
return trustLevel; \
|
||||
} \
|
||||
STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) \
|
||||
STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) override \
|
||||
{ \
|
||||
*runtimeName = nullptr; \
|
||||
HRESULT hr = S_OK; \
|
||||
|
@ -2537,7 +2586,7 @@ namespace Details
|
|||
} \
|
||||
return hr; \
|
||||
} \
|
||||
STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel* trustLvl) \
|
||||
STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel* trustLvl) override \
|
||||
{ \
|
||||
*trustLvl = trustLevel; \
|
||||
return S_OK; \
|
||||
|
@ -2545,22 +2594,22 @@ namespace Details
|
|||
STDMETHOD(GetIids)(_Out_ ULONG *iidCount, \
|
||||
_When_(*iidCount == 0, _At_(*iids, _Post_null_)) \
|
||||
_When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) \
|
||||
_Result_nullonfailure_ IID **iids) \
|
||||
_Result_nullonfailure_ IID **iids) override \
|
||||
{ \
|
||||
return RuntimeClassT::GetIids(iidCount, iids); \
|
||||
} \
|
||||
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \
|
||||
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) override \
|
||||
{ \
|
||||
bool handled = false; \
|
||||
HRESULT hr = this->CustomQueryInterface(riid, ppvObject, &handled); \
|
||||
if (FAILED(hr) || handled) return hr; \
|
||||
return RuntimeClassT::QueryInterface(riid, ppvObject); \
|
||||
} \
|
||||
STDMETHOD_(ULONG, Release)() \
|
||||
STDMETHOD_(ULONG, Release)() override \
|
||||
{ \
|
||||
return RuntimeClassT::Release(); \
|
||||
} \
|
||||
STDMETHOD_(ULONG, AddRef)() \
|
||||
STDMETHOD_(ULONG, AddRef)() override \
|
||||
{ \
|
||||
return RuntimeClassT::AddRef(); \
|
||||
} \
|
||||
|
@ -2648,8 +2697,4 @@ namespace Details
|
|||
// Restore packing
|
||||
#include <poppack.h>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // _WRL_IMPLEMENTS_H_
|
||||
|
|
Загрузка…
Ссылка в новой задаче