summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorciappi2022-06-19 13:47:28 +0200
committerciappi2022-06-19 13:47:28 +0200
commit05780d04bb85244e2749422945c061ffdfc7b3ac (patch)
tree3935ee8d952376d835ba92d240547e8865185ae1
parent73b0490d2f5dbf2d34a8678bf6d9c09b5f2d064a (diff)
downloadaur-05780d04bb85244e2749422945c061ffdfc7b3ac.tar.gz
v0.15.0-1
-rw-r--r--.SRCINFO12
-rw-r--r--.gitignore1
-rw-r--r--PKGBUILD11
-rw-r--r--doctest.patch4833
4 files changed, 10 insertions, 4847 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 7b31c384ab9a..e9ed5e86e1e0 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,17 +1,15 @@
pkgbase = lfortran
pkgdesc = Modern interactive LLVM-based Fortran compiler
- pkgver = 0.14.0
- pkgrel = 2
+ pkgver = 0.15.0
+ pkgrel = 1
url = https://lfortran.org
arch = x86_64
license = BSD
- makedepends = llvm11
+ makedepends = llvm
makedepends = cmake
depends = zlib
depends = ncurses
- source = https://lfortran.github.io/tarballs/release/lfortran-0.14.0.tar.gz
- source = doctest.patch
- sha256sums = fc3c1d592c56ae2636065ec0228db747f154f65a0867f6311bc8091efd5c13a7
- sha256sums = c0a8eabdefe530e65a22ac5b19948c7cbf77d8c46a7afeef8792e9e38006c5d5
+ source = https://lfortran.github.io/tarballs/release/lfortran-0.15.0.tar.gz
+ sha256sums = 8712c1b0c886f08937ff4c277ff3fa5c05e4dead1bafe55e3bd789be96470127
pkgname = lfortran
diff --git a/.gitignore b/.gitignore
index 498667d7dff1..018a3de08144 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,3 @@
!PKGBUILD
!.SRCINFO
!.gitignore
-!doctest.patch
diff --git a/PKGBUILD b/PKGBUILD
index 8b3676c880ff..6550f858b982 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Ciappi <marco.scopesi@gmail.com>
pkgname=lfortran
-pkgver=0.14.0
-pkgrel=2
+pkgver=0.15.0
+pkgrel=1
pkgdesc="Modern interactive LLVM-based Fortran compiler"
arch=('x86_64')
url="https://lfortran.org"
@@ -18,14 +18,12 @@ backup=()
options=()
install=
changelog=
-source=("https://lfortran.github.io/tarballs/release/"$pkgname-$pkgver.tar.gz "doctest.patch")
-sha256sums=('fc3c1d592c56ae2636065ec0228db747f154f65a0867f6311bc8091efd5c13a7'
- 'c0a8eabdefe530e65a22ac5b19948c7cbf77d8c46a7afeef8792e9e38006c5d5')
+source=("https://lfortran.github.io/tarballs/release/"$pkgname-$pkgver.tar.gz)
+sha256sums=('8712c1b0c886f08937ff4c277ff3fa5c05e4dead1bafe55e3bd789be96470127')
noextract=()
prepare() {
cd "$pkgname-$pkgver"
- patch --forward --strip=1 --input="${srcdir}/doctest.patch"
}
build() {
@@ -49,3 +47,4 @@ package() {
# vim:set ts=2 sw=2 et:
+
diff --git a/doctest.patch b/doctest.patch
deleted file mode 100644
index 4b812d76e8eb..000000000000
--- a/doctest.patch
+++ /dev/null
@@ -1,4833 +0,0 @@
-diff --unified --recursive --text package.orig/src/tests/doctest.h package.new/src/tests/doctest.h
---- package.orig/src/tests/doctest.h 2021-09-23 08:22:52.000000000 +0200
-+++ package.new/src/tests/doctest.h 2022-01-10 18:39:35.000000000 +0100
-@@ -4,14 +4,14 @@
- //
- // doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
- //
--// Copyright (c) 2016-2019 Viktor Kirilov
-+// Copyright (c) 2016-2021 Viktor Kirilov
- //
- // Distributed under the MIT Software License
- // See accompanying file LICENSE.txt or copy at
- // https://opensource.org/licenses/MIT
- //
- // The documentation can be found at the library's page:
--// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md
-+// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
- //
- // =================================================================================================
- // =================================================================================================
-@@ -47,9 +47,17 @@
- // =================================================================================================
-
- #define DOCTEST_VERSION_MAJOR 2
--#define DOCTEST_VERSION_MINOR 3
--#define DOCTEST_VERSION_PATCH 4
--#define DOCTEST_VERSION_STR "2.3.4"
-+#define DOCTEST_VERSION_MINOR 4
-+#define DOCTEST_VERSION_PATCH 8
-+
-+// util we need here
-+#define DOCTEST_TOSTR_IMPL(x) #x
-+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
-+
-+#define DOCTEST_VERSION_STR \
-+ DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
-+ DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
-+ DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
-
- #define DOCTEST_VERSION \
- (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
-@@ -137,84 +145,93 @@
- // == COMPILER WARNINGS ============================================================================
- // =================================================================================================
-
-+// both the header and the implementation suppress all of these,
-+// so it only makes sense to aggregrate them like so
-+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
-+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
-+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
-+ \
-+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
-+ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
-+ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
-+ /* these 4 also disabled globally via cmake: */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
-+ /* */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
-+ /* static analysis */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
-+
-+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
-+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
-+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
-+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
-+
-+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
-+
- DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
-
- DOCTEST_GCC_SUPPRESS_WARNING_PUSH
--DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
--DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
--DOCTEST_GCC_SUPPRESS_WARNING("-Winline")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
-
- DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
--DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
--DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
--DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
--DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
--DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
--DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
--DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding
--DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
- DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
--// static analysis
--DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
--DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
--DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
--DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtr...
--
--// 4548 - expression before comma has no effect; expected expression with side - effect
--// 4265 - class has virtual functions, but destructor is not virtual
--// 4986 - exception specification does not match previous declaration
--// 4350 - behavior change: 'member1' called instead of 'member2'
--// 4668 - 'x' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
--// 4365 - conversion from 'int' to 'unsigned long', signed/unsigned mismatch
--// 4774 - format string expected in argument 'x' is not a string literal
--// 4820 - padding in structs
--
--// only 4 should be disabled globally:
--// - 4514 # unreferenced inline function has been removed
--// - 4571 # SEH related
--// - 4710 # function not inlined
--// - 4711 # function 'x' selected for automatic inline expansion
-
- #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
- DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4548) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4265) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4986) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4350) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4668) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4365) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4774) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4820) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4625) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4626) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(5027) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(5026) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(4623) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(5039) \
-- DOCTEST_MSVC_SUPPRESS_WARNING(5045)
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
-+ DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */
-
- #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
-
-@@ -227,6 +244,7 @@
- // GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
- // MSVC version table:
- // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
-+// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
- // MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
- // MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
- // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
-@@ -236,6 +254,10 @@
- // MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
- // MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
-
-+// Universal Windows Platform support
-+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
-+#define DOCTEST_CONFIG_NO_WINDOWS_SEH
-+#endif // WINAPI_FAMILY
- #if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
- #define DOCTEST_CONFIG_WINDOWS_SEH
- #endif // MSVC
-@@ -300,15 +322,39 @@
- #define DOCTEST_NOINLINE __declspec(noinline)
- #define DOCTEST_UNUSED
- #define DOCTEST_ALIGNMENT(x)
--#else // MSVC
-+#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
-+#define DOCTEST_NOINLINE
-+#define DOCTEST_UNUSED
-+#define DOCTEST_ALIGNMENT(x)
-+#else
- #define DOCTEST_NOINLINE __attribute__((noinline))
- #define DOCTEST_UNUSED __attribute__((unused))
- #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
--#endif // MSVC
-+#endif
-+
-+#ifndef DOCTEST_NORETURN
-+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
-+#define DOCTEST_NORETURN
-+#else // DOCTEST_MSVC
-+#define DOCTEST_NORETURN [[noreturn]]
-+#endif // DOCTEST_MSVC
-+#endif // DOCTEST_NORETURN
-
--#ifndef DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK
--#define DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK 5
--#endif // DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK
-+#ifndef DOCTEST_NOEXCEPT
-+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
-+#define DOCTEST_NOEXCEPT
-+#else // DOCTEST_MSVC
-+#define DOCTEST_NOEXCEPT noexcept
-+#endif // DOCTEST_MSVC
-+#endif // DOCTEST_NOEXCEPT
-+
-+#ifndef DOCTEST_CONSTEXPR
-+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
-+#define DOCTEST_CONSTEXPR const
-+#else // DOCTEST_MSVC
-+#define DOCTEST_CONSTEXPR constexpr
-+#endif // DOCTEST_MSVC
-+#endif // DOCTEST_CONSTEXPR
-
- // =================================================================================================
- // == FEATURE DETECTION END ========================================================================
-@@ -323,8 +369,6 @@
- #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
- #endif // __COUNTER__
-
--#define DOCTEST_TOSTR(x) #x
--
- #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
- #define DOCTEST_REF_WRAP(x) x&
- #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
-@@ -342,23 +386,31 @@
- #define DOCTEST_PLATFORM_LINUX
- #endif // DOCTEST_PLATFORM
-
--// clang-format off
--#define DOCTEST_DELETE_COPIES(type) type(const type&) = delete; type& operator=(const type&) = delete
--#define DOCTEST_DECLARE_COPIES(type) type(const type&); type& operator=(const type&)
--#define DOCTEST_DEFINE_COPIES(type) type::type(const type&) = default; type& type::operator=(const type&) = default
--#define DOCTEST_DECLARE_DEFAULTS(type) type(); ~type()
--#define DOCTEST_DEFINE_DEFAULTS(type) type::type() = default; type::~type() = default
--// clang-format on
-+namespace doctest { namespace detail {
-+ static DOCTEST_CONSTEXPR int consume(const int*, int) { return 0; }
-+}}
-
--#define DOCTEST_GLOBAL_NO_WARNINGS(var) \
-+#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
-- DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \
-- static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp)
--#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP
-+ static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
-+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
-
-+#ifndef DOCTEST_BREAK_INTO_DEBUGGER
- // should probably take a look at https://github.com/scottt/debugbreak
--#ifdef DOCTEST_PLATFORM_MAC
--#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :)
-+#ifdef DOCTEST_PLATFORM_LINUX
-+#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
-+// Break at the location of the failing check if possible
-+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
-+#else
-+#include <signal.h>
-+#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
-+#endif
-+#elif defined(DOCTEST_PLATFORM_MAC)
-+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
-+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
-+#else
-+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT (hicpp-no-assembler)
-+#endif
- #elif DOCTEST_MSVC
- #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
- #elif defined(__MINGW32__)
-@@ -367,40 +419,40 @@
- DOCTEST_GCC_SUPPRESS_WARNING_POP
- #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
- #else // linux
--#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
-+#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast<void>(0))
- #endif // linux
-+#endif // DOCTEST_BREAK_INTO_DEBUGGER
-
- // this is kept here for backwards compatibility since the config option was changed
- #ifdef DOCTEST_CONFIG_USE_IOSFWD
- #define DOCTEST_CONFIG_USE_STD_HEADERS
- #endif // DOCTEST_CONFIG_USE_IOSFWD
-
--#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
--#include <iosfwd>
--#include <cstddef>
--#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
--// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
--#include <ostream>
--#endif // VS 2019
--#else // DOCTEST_CONFIG_USE_STD_HEADERS
--
-+// for clang - always include ciso646 (which drags some std stuff) because
-+// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
-+// which case we don't want to forward declare stuff from std - for reference:
-+// https://github.com/doctest/doctest/issues/126
-+// https://github.com/doctest/doctest/issues/356
- #if DOCTEST_CLANG
--// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
- #include <ciso646>
--#endif // clang
--
- #ifdef _LIBCPP_VERSION
--#define DOCTEST_STD_NAMESPACE_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
--#define DOCTEST_STD_NAMESPACE_END _LIBCPP_END_NAMESPACE_STD
--#else // _LIBCPP_VERSION
--#define DOCTEST_STD_NAMESPACE_BEGIN namespace std {
--#define DOCTEST_STD_NAMESPACE_END }
-+#define DOCTEST_CONFIG_USE_STD_HEADERS
- #endif // _LIBCPP_VERSION
-+#endif // clang
-+
-+#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
-+#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-+#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-+#include <cstddef>
-+#include <ostream>
-+#include <istream>
-+#else // DOCTEST_CONFIG_USE_STD_HEADERS
-
- // Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
-
--DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp)
-+namespace std { // NOLINT (cert-dcl58-cpp)
- typedef decltype(nullptr) nullptr_t;
- template <class charT>
- struct char_traits;
-@@ -409,17 +461,20 @@
- template <class charT, class traits>
- class basic_ostream;
- typedef basic_ostream<char, char_traits<char>> ostream;
-+template <class charT, class traits>
-+class basic_istream;
-+typedef basic_istream<char, char_traits<char>> istream;
- template <class... Types>
- class tuple;
- #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
--// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
--template <class _Ty>
-+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
-+template <class Ty>
- class allocator;
--template <class _Elem, class _Traits, class _Alloc>
-+template <class Elem, class Traits, class Alloc>
- class basic_string;
- using string = basic_string<char, char_traits<char>, allocator<char>>;
- #endif // VS 2019
--DOCTEST_STD_NAMESPACE_END
-+} // namespace std
-
- DOCTEST_MSVC_SUPPRESS_WARNING_POP
-
-@@ -471,6 +526,8 @@
- view data;
- };
-
-+ char* allocate(unsigned sz);
-+
- bool isOnStack() const { return (buf[last] & 128) == 0; }
- void setOnHeap();
- void setLast(unsigned in = last);
-@@ -485,11 +542,12 @@
- String(const char* in);
- String(const char* in, unsigned in_size);
-
-+ String(std::istream& in, unsigned in_size);
-+
- String(const String& other);
- String& operator=(const String& other);
-
- String& operator+=(const String& other);
-- String operator+(const String& other) const;
-
- String(String&& other);
- String& operator=(String&& other);
-@@ -512,6 +570,8 @@
- int compare(const String& other, bool no_case = false) const;
- };
-
-+DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
-+
- DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
- DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
- DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
-@@ -592,6 +652,10 @@
- DT_WARN_THROWS_WITH = is_throws_with | is_warn,
- DT_CHECK_THROWS_WITH = is_throws_with | is_check,
- DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
-+
-+ DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
-+ DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
-+ DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
-
- DT_WARN_NOTHROW = is_nothrow | is_warn,
- DT_CHECK_NOTHROW = is_nothrow | is_check,
-@@ -637,19 +701,18 @@
-
- struct DOCTEST_INTERFACE TestCaseData
- {
-- const char* m_file; // the file in which the test was registered
-+ String m_file; // the file in which the test was registered (using String - see #350)
- unsigned m_line; // the line where the test was registered
- const char* m_name; // name of the test case
- const char* m_test_suite; // the test suite in which the test was added
- const char* m_description;
- bool m_skip;
-+ bool m_no_breaks;
-+ bool m_no_output;
- bool m_may_fail;
- bool m_should_fail;
- int m_expected_failures;
- double m_timeout;
--
-- DOCTEST_DECLARE_DEFAULTS(TestCaseData);
-- DOCTEST_DECLARE_COPIES(TestCaseData);
- };
-
- struct DOCTEST_INTERFACE AssertData
-@@ -672,9 +735,7 @@
- // for specific exception-related asserts
- bool m_threw_as;
- const char* m_exception_type;
--
-- DOCTEST_DECLARE_DEFAULTS(AssertData);
-- DOCTEST_DELETE_COPIES(AssertData);
-+ const char* m_exception_string;
- };
-
- struct DOCTEST_INTERFACE MessageData
-@@ -683,39 +744,34 @@
- const char* m_file;
- int m_line;
- assertType::Enum m_severity;
--
-- DOCTEST_DECLARE_DEFAULTS(MessageData);
-- DOCTEST_DELETE_COPIES(MessageData);
- };
-
- struct DOCTEST_INTERFACE SubcaseSignature
- {
-- const char* m_name;
-+ String m_name;
- const char* m_file;
- int m_line;
-
-- SubcaseSignature(const char* name, const char* file, int line);
--
- bool operator<(const SubcaseSignature& other) const;
--
-- DOCTEST_DECLARE_DEFAULTS(SubcaseSignature);
-- DOCTEST_DECLARE_COPIES(SubcaseSignature);
- };
-
- struct DOCTEST_INTERFACE IContextScope
- {
-- DOCTEST_DELETE_COPIES(IContextScope);
--
- IContextScope();
- virtual ~IContextScope();
- virtual void stringify(std::ostream*) const = 0;
- };
-
-+namespace detail {
-+ struct DOCTEST_INTERFACE TestCase;
-+} // namespace detail
-+
- struct ContextOptions //!OCLINT too many fields
- {
-- std::ostream* cout; // stdout stream - std::cout by default
-- std::ostream* cerr; // stderr stream - std::cerr by default
-- String binary_name; // the test binary name
-+ std::ostream* cout = nullptr; // stdout stream
-+ String binary_name; // the test binary name
-+
-+ const detail::TestCase* currentTest = nullptr;
-
- // == parameters from the command line
- String out; // output filename
-@@ -732,9 +788,12 @@
- bool case_sensitive; // if filtering should be case sensitive
- bool exit; // if the program should be exited after the tests are ran/whatever
- bool duration; // print the time duration of each test case
-+ bool minimal; // minimal console output (only test failures)
-+ bool quiet; // no console output
- bool no_throw; // to skip exceptions-related assertion macros
- bool no_exitcode; // if the framework should return 0 as the exitcode
- bool no_run; // to not run the tests at all (can be done with an "*" exclude)
-+ bool no_intro; // to not print the intro of the framework
- bool no_version; // to not print the version of the framework
- bool no_colors; // if output to the console should be colorized
- bool force_colors; // forces the use of colors even when a tty cannot be detected
-@@ -743,21 +802,19 @@
- bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
- bool no_path_in_filenames; // if the path to files should be removed from the output
- bool no_line_numbers; // if source code line numbers should be omitted from the output
-+ bool no_debug_output; // no output in the debug console when a debugger is attached
- bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
-+ bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
-
- bool help; // to print the help
- bool version; // to print the version
-- bool count; // if only the count of matching tests is to be retreived
-+ bool count; // if only the count of matching tests is to be retrieved
- bool list_test_cases; // to list all tests matching the filters
- bool list_test_suites; // to list all suites matching the filters
- bool list_reporters; // lists all registered reporters
--
-- DOCTEST_DECLARE_DEFAULTS(ContextOptions);
-- DOCTEST_DELETE_COPIES(ContextOptions);
- };
-
- namespace detail {
--#if defined(DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || defined(DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS)
- template <bool CONDITION, typename TYPE = void>
- struct enable_if
- {};
-@@ -765,15 +822,48 @@
- template <typename TYPE>
- struct enable_if<true, TYPE>
- { typedef TYPE type; };
--#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-
- // clang-format off
- template<class T> struct remove_reference { typedef T type; };
- template<class T> struct remove_reference<T&> { typedef T type; };
- template<class T> struct remove_reference<T&&> { typedef T type; };
-
-+ template<typename T, typename U = T&&> U declval(int);
-+
-+ template<typename T> T declval(long);
-+
-+ template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ;
-+
-+ template<class T> struct is_lvalue_reference { const static bool value=false; };
-+ template<class T> struct is_lvalue_reference<T&> { const static bool value=true; };
-+
-+ template<class T> struct is_rvalue_reference { const static bool value=false; };
-+ template<class T> struct is_rvalue_reference<T&&> { const static bool value=true; };
-+
-+ template <class T>
-+ inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT
-+ {
-+ return static_cast<T&&>(t);
-+ }
-+
-+ template <class T>
-+ inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT
-+ {
-+ static_assert(!is_lvalue_reference<T>::value,
-+ "Can not forward an rvalue as an lvalue.");
-+ return static_cast<T&&>(t);
-+ }
-+
- template<class T> struct remove_const { typedef T type; };
- template<class T> struct remove_const<const T> { typedef T type; };
-+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-+ template<class T> struct is_enum : public std::is_enum<T> {};
-+ template<class T> struct underlying_type : public std::underlying_type<T> {};
-+#else
-+ // Use compiler intrinsics
-+ template<class T> struct is_enum { DOCTEST_CONSTEXPR static bool value = __is_enum(T); };
-+ template<class T> struct underlying_type { typedef __underlying_type(T) type; };
-+#endif
- // clang-format on
-
- template <typename T>
-@@ -782,38 +872,27 @@
- { static const bool value = false; };
-
- namespace has_insertion_operator_impl {
-- typedef char no;
-- typedef char yes[2];
--
-- struct any_t
-- {
-- template <typename T>
-- // cppcheck-suppress noExplicitConstructor
-- any_t(const DOCTEST_REF_WRAP(T));
-+ std::ostream &os();
-+ template<class T>
-+ DOCTEST_REF_WRAP(T) val();
-+
-+ template<class, class = void>
-+ struct check {
-+ static DOCTEST_CONSTEXPR bool value = false;
- };
-
-- yes& testStreamable(std::ostream&);
-- no testStreamable(no);
--
-- no operator<<(const std::ostream&, const any_t&);
--
-- template <typename T>
-- struct has_insertion_operator
-- {
-- static std::ostream& s;
-- static const DOCTEST_REF_WRAP(T) t;
-- static const bool value = sizeof(decltype(testStreamable(s << t))) == sizeof(yes);
-+ template<class T>
-+ struct check<T, decltype(os() << val<T>(), void())> {
-+ static DOCTEST_CONSTEXPR bool value = true;
- };
- } // namespace has_insertion_operator_impl
-
-- template <typename T>
-- struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T>
-- {};
-+ template<class T>
-+ using has_insertion_operator = has_insertion_operator_impl::check<const T>;
-
-- DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num);
-+ DOCTEST_INTERFACE std::ostream* tlssPush();
-+ DOCTEST_INTERFACE String tlssPop();
-
-- DOCTEST_INTERFACE std::ostream* getTlsOss(); // returns a thread-local ostringstream
-- DOCTEST_INTERFACE String getTlsOssResult();
-
- template <bool C>
- struct StringMakerBase
-@@ -824,13 +903,61 @@
- }
- };
-
-+ // Vector<int> and various type other than pointer or array.
-+ template<typename T>
-+ struct filldata
-+ {
-+ static void fill(std::ostream* stream, const T &in) {
-+ *stream << in;
-+ }
-+ };
-+
-+ template<typename T,unsigned long N>
-+ struct filldata<T[N]>
-+ {
-+ static void fill(std::ostream* stream, const T (&in)[N]) {
-+ for (unsigned long i = 0; i < N; i++) {
-+ *stream << in[i];
-+ }
-+ }
-+ };
-+
-+ // Specialized since we don't want the terminating null byte!
-+ template<unsigned long N>
-+ struct filldata<const char[N]>
-+ {
-+ static void fill(std::ostream* stream, const char(&in)[N]) {
-+ *stream << in;
-+ }
-+ };
-+
-+ template<typename T>
-+ void filloss(std::ostream* stream, const T& in) {
-+ filldata<T>::fill(stream, in);
-+ }
-+
-+ template<typename T,unsigned long N>
-+ void filloss(std::ostream* stream, const T (&in)[N]) {
-+ // T[N], T(&)[N], T(&&)[N] have same behaviour.
-+ // Hence remove reference.
-+ filldata<typename remove_reference<decltype(in)>::type>::fill(stream, in);
-+ }
-+
- template <>
- struct StringMakerBase<true>
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T) in) {
-- *getTlsOss() << in;
-- return getTlsOssResult();
-+ /* When parameter "in" is a null terminated const char* it works.
-+ * When parameter "in" is a T arr[N] without '\0' we can fill the
-+ * stringstream with N objects (T=char).If in is char pointer *
-+ * without '\0' , it would cause segfault
-+ * stepping over unaccessible memory.
-+ */
-+
-+ std::ostream* stream = tlssPush();
-+ filloss(stream, in);
-+ return tlssPop();
- }
- };
-
-@@ -872,7 +999,7 @@
- }
- };
-
--template <typename T>
-+template <typename T, typename detail::enable_if<!detail::is_enum<T>::value, bool>::type = true>
- String toString(const DOCTEST_REF_WRAP(T) value) {
- return StringMaker<T>::convert(value);
- }
-@@ -899,8 +1026,14 @@
- DOCTEST_INTERFACE String toString(int long long unsigned in);
- DOCTEST_INTERFACE String toString(std::nullptr_t in);
-
-+template <typename T, typename detail::enable_if<detail::is_enum<T>::value, bool>::type = true>
-+String toString(const DOCTEST_REF_WRAP(T) value) {
-+ typedef typename detail::underlying_type<T>::type UT;
-+ return toString(static_cast<UT>(value));
-+}
-+
- #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
--// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
-+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
- DOCTEST_INTERFACE String toString(const std::string& in);
- #endif // VS 2019
-
-@@ -909,8 +1042,6 @@
- public:
- explicit Approx(double value);
-
-- DOCTEST_DECLARE_COPIES(Approx);
--
- Approx operator()(double value) const;
-
- #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-@@ -1010,14 +1141,12 @@
-
- struct DOCTEST_INTERFACE TestFailureException
- {
-- DOCTEST_DECLARE_DEFAULTS(TestFailureException);
-- DOCTEST_DECLARE_COPIES(TestFailureException);
- };
-
- DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
-
- #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- [[noreturn]]
-+ DOCTEST_NORETURN
- #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
- DOCTEST_INTERFACE void throwException();
-
-@@ -1026,24 +1155,42 @@
- SubcaseSignature m_signature;
- bool m_entered = false;
-
-- Subcase(const char* name, const char* file, int line);
-+ Subcase(const String& name, const char* file, int line);
- ~Subcase();
-
-- DOCTEST_DELETE_COPIES(Subcase);
--
- operator bool() const;
- };
-
- template <typename L, typename R>
- String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
- const DOCTEST_REF_WRAP(R) rhs) {
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- return toString(lhs) + op + toString(rhs);
- }
-
-+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
-+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
-+#endif
-+
-+// This will check if there is any way it could find a operator like member or friend and uses it.
-+// If not it doesn't find the operator or if the operator at global scope is defined after
-+// this template, the template won't be instantiated due to SFINAE. Once the template is not
-+// instantiated it can look for global operator using normal conversions.
-+#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
-+
- #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
- template <typename R> \
-- DOCTEST_NOINLINE Result operator op(const DOCTEST_REF_WRAP(R) rhs) { \
-- bool res = op_macro(lhs, rhs); \
-+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(const R&& rhs) { \
-+ bool res = op_macro(doctest::detail::forward<const L>(lhs), doctest::detail::forward<const R>(rhs)); \
-+ if(m_at & assertType::is_false) \
-+ res = !res; \
-+ if(!res || doctest::getContextOptions()->success) \
-+ return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
-+ return Result(res); \
-+ } \
-+ template <typename R ,typename enable_if<!doctest::detail::is_rvalue_reference<R>::value, void >::type* = nullptr> \
-+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(const R& rhs) { \
-+ bool res = op_macro(doctest::detail::forward<const L>(lhs), rhs); \
- if(m_at & assertType::is_false) \
- res = !res; \
- if(!res || doctest::getContextOptions()->success) \
-@@ -1067,12 +1214,10 @@
- bool m_passed;
- String m_decomp;
-
-+ Result() = default;
- Result(bool passed, const String& decomposition = String());
-
-- DOCTEST_DECLARE_DEFAULTS(Result);
-- DOCTEST_DECLARE_COPIES(Result);
--
-- // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
-+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
- DOCTEST_FORBIT_EXPRESSION(Result, &)
- DOCTEST_FORBIT_EXPRESSION(Result, ^)
- DOCTEST_FORBIT_EXPRESSION(Result, |)
-@@ -1114,7 +1259,7 @@
- //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
-
- DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
-- // http://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
-+ // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
- DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
- DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
- DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
-@@ -1127,6 +1272,7 @@
- #define DOCTEST_COMPARISON_RETURN_TYPE bool
- #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- #define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
- inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
- inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
-@@ -1173,12 +1319,15 @@
- L lhs;
- assertType::Enum m_at;
-
-- explicit Expression_lhs(L in, assertType::Enum at)
-- : lhs(in)
-+ explicit Expression_lhs(L&& in, assertType::Enum at)
-+ : lhs(doctest::detail::forward<L>(in))
- , m_at(at) {}
-
- DOCTEST_NOINLINE operator Result() {
-- bool res = !!lhs;
-+// this is needed only for MSVC 2015
-+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
-+ bool res = static_cast<bool>(lhs);
-+DOCTEST_MSVC_SUPPRESS_WARNING_POP
- if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
- res = !res;
-
-@@ -1187,6 +1336,9 @@
- return Result(res);
- }
-
-+ /* This is required for user-defined conversions from Expression_lhs to L */
-+ operator L() const { return lhs; }
-+
- // clang-format off
- DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
- DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
-@@ -1196,7 +1348,7 @@
- DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
- // clang-format on
-
-- // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
-+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
- DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
- DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
- DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |)
-@@ -1227,37 +1379,42 @@
-
- #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
-
-+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
-+DOCTEST_CLANG_SUPPRESS_WARNING_POP
-+#endif
-+
- struct DOCTEST_INTERFACE ExpressionDecomposer
- {
- assertType::Enum m_at;
-
- ExpressionDecomposer(assertType::Enum at);
-
-- DOCTEST_DECLARE_DEFAULTS(ExpressionDecomposer);
-- DOCTEST_DELETE_COPIES(ExpressionDecomposer);
--
- // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
- // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
- // https://github.com/catchorg/Catch2/issues/870
- // https://github.com/catchorg/Catch2/issues/565
- template <typename L>
-- Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) {
-- return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand, m_at);
-+ Expression_lhs<const L> operator<<(const L &&operand) {
-+ return Expression_lhs<const L>(doctest::detail::forward<const L>(operand), m_at);
-+ }
-+
-+ template <typename L,typename enable_if<!doctest::detail::is_rvalue_reference<L>::value,void >::type* = nullptr>
-+ Expression_lhs<const L&> operator<<(const L &operand) {
-+ return Expression_lhs<const L&>(operand, m_at);
- }
- };
-
- struct DOCTEST_INTERFACE TestSuite
- {
-- const char* m_test_suite;
-- const char* m_description;
-- bool m_skip;
-- bool m_may_fail;
-- bool m_should_fail;
-- int m_expected_failures;
-- double m_timeout;
--
-- DOCTEST_DECLARE_DEFAULTS(TestSuite);
-- DOCTEST_DECLARE_COPIES(TestSuite);
-+ const char* m_test_suite = nullptr;
-+ const char* m_description = nullptr;
-+ bool m_skip = false;
-+ bool m_no_breaks = false;
-+ bool m_no_output = false;
-+ bool m_may_fail = false;
-+ bool m_should_fail = false;
-+ int m_expected_failures = 0;
-+ double m_timeout = 0;
-
- TestSuite& operator*(const char* in);
-
-@@ -1281,8 +1438,6 @@
- TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
- const char* type = "", int template_id = -1);
-
-- DOCTEST_DECLARE_DEFAULTS(TestCase);
--
- TestCase(const TestCase& other);
-
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
-@@ -1327,33 +1482,31 @@
- template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
- // clang-format on
-
-- DOCTEST_BINARY_RELATIONAL_OP(0, eq)
-- DOCTEST_BINARY_RELATIONAL_OP(1, ne)
-- DOCTEST_BINARY_RELATIONAL_OP(2, gt)
-- DOCTEST_BINARY_RELATIONAL_OP(3, lt)
-- DOCTEST_BINARY_RELATIONAL_OP(4, ge)
-- DOCTEST_BINARY_RELATIONAL_OP(5, le)
-+ DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
-+ DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
-+ DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
-+ DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
-+ DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
-+ DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
-
- struct DOCTEST_INTERFACE ResultBuilder : public AssertData
- {
- ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
-- const char* exception_type = "");
--
-- DOCTEST_DECLARE_DEFAULTS(ResultBuilder);
-- DOCTEST_DELETE_COPIES(ResultBuilder);
-+ const char* exception_type = "", const char* exception_string = "");
-
- void setResult(const Result& res);
-
- template <int comparison, typename L, typename R>
-- DOCTEST_NOINLINE void binary_assert(const DOCTEST_REF_WRAP(L) lhs,
-+ DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
- const DOCTEST_REF_WRAP(R) rhs) {
- m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
- if(m_failed || getContextOptions()->success)
- m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
-+ return !m_failed;
- }
-
- template <typename L>
-- DOCTEST_NOINLINE void unary_assert(const DOCTEST_REF_WRAP(L) val) {
-+ DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
- m_failed = !val;
-
- if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
-@@ -1361,6 +1514,8 @@
-
- if(m_failed || getContextOptions()->success)
- m_decomp = toString(val);
-+
-+ return !m_failed;
- }
-
- void translateException();
-@@ -1380,7 +1535,7 @@
-
- DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
-
-- DOCTEST_INTERFACE void decomp_assert(assertType::Enum at, const char* file, int line,
-+ DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
- const char* expr, Result result);
-
- #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
-@@ -1396,7 +1551,7 @@
- if(checkIfShouldThrow(at)) \
- throwException(); \
- } \
-- return; \
-+ return !failed; \
- } \
- } while(false)
-
-@@ -1411,7 +1566,7 @@
- throwException()
-
- template <int comparison, typename L, typename R>
-- DOCTEST_NOINLINE void binary_assert(assertType::Enum at, const char* file, int line,
-+ DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
- const char* expr, const DOCTEST_REF_WRAP(L) lhs,
- const DOCTEST_REF_WRAP(R) rhs) {
- bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
-@@ -1422,10 +1577,11 @@
- // ###################################################################################
- DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
- DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
-+ return !failed;
- }
-
- template <typename L>
-- DOCTEST_NOINLINE void unary_assert(assertType::Enum at, const char* file, int line,
-+ DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
- const char* expr, const DOCTEST_REF_WRAP(L) val) {
- bool failed = !val;
-
-@@ -1438,12 +1594,11 @@
- // ###################################################################################
- DOCTEST_ASSERT_OUT_OF_TESTS(toString(val));
- DOCTEST_ASSERT_IN_TESTS(toString(val));
-+ return !failed;
- }
-
- struct DOCTEST_INTERFACE IExceptionTranslator
- {
-- DOCTEST_DELETE_COPIES(IExceptionTranslator);
--
- IExceptionTranslator();
- virtual ~IExceptionTranslator();
- virtual bool translate(String&) const = 0;
-@@ -1464,9 +1619,9 @@
- } catch(T ex) { // NOLINT
- res = m_translateFunction(ex); //!OCLINT parameter reassignment
- return true;
-- } catch(...) {} //!OCLINT - empty catch statement
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-- ((void)res); // to silence -Wunused-parameter
-+ } catch(...) {} //!OCLINT - empty catch statement
-+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-+ static_cast<void>(res); // to silence -Wunused-parameter
- return false;
- }
-
-@@ -1533,40 +1688,57 @@
- class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
- protected:
- ContextScopeBase();
-+ ContextScopeBase(ContextScopeBase&& other);
-
- void destroy();
-+ bool need_to_destroy{true};
- };
-
-- template <typename L> class DOCTEST_INTERFACE ContextScope : public ContextScopeBase
-+ template <typename L> class ContextScope : public ContextScopeBase
- {
-- const L &lambda_;
-+ const L lambda_;
-
- public:
- explicit ContextScope(const L &lambda) : lambda_(lambda) {}
-
-- ContextScope(ContextScope &&other) : lambda_(other.lambda_) {}
-+ ContextScope(ContextScope &&other) : ContextScopeBase(static_cast<ContextScopeBase&&>(other)), lambda_(other.lambda_) {}
-
- void stringify(std::ostream* s) const override { lambda_(s); }
-
-- ~ContextScope() override { destroy(); }
-+ ~ContextScope() override {
-+ if (need_to_destroy) {
-+ destroy();
-+ }
-+ }
- };
-
- struct DOCTEST_INTERFACE MessageBuilder : public MessageData
- {
- std::ostream* m_stream;
-+ bool logged = false;
-
- MessageBuilder(const char* file, int line, assertType::Enum severity);
- MessageBuilder() = delete;
- ~MessageBuilder();
-
-- DOCTEST_DELETE_COPIES(MessageBuilder);
--
-+ // the preferred way of chaining parameters for stringification
- template <typename T>
-- MessageBuilder& operator<<(const T& in) {
-+ MessageBuilder& operator,(const T& in) {
- toStream(m_stream, in);
- return *this;
- }
-
-+ // kept here just for backwards-compatibility - the comma operator should be preferred now
-+ template <typename T>
-+ MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
-+
-+ // the `,` operator has the lowest operator precedence - if `<<` is used by the user then
-+ // the `,` operator will be called last which is not what we want and thus the `*` operator
-+ // is used first (has higher operator precedence compared to `<<`) so that we guarantee that
-+ // an operator of the MessageBuilder class is called first before the rest of the parameters
-+ template <typename T>
-+ MessageBuilder& operator*(const T& in) { return this->operator,(in); }
-+
- bool log();
- void react();
- };
-@@ -1590,6 +1762,8 @@
- DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
- DOCTEST_DEFINE_DECORATOR(description, const char*, "");
- DOCTEST_DEFINE_DECORATOR(skip, bool, true);
-+DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
-+DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
- DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
- DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
- DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
-@@ -1634,14 +1808,13 @@
- public:
- explicit Context(int argc = 0, const char* const* argv = nullptr);
-
-- DOCTEST_DELETE_COPIES(Context);
--
- ~Context();
-
- void applyCommandLine(int argc, const char* const* argv);
-
- void addFilter(const char* filter, const char* value);
- void clearFilters();
-+ void setOption(const char* option, bool value);
- void setOption(const char* option, int value);
- void setOption(const char* option, const char* value);
-
-@@ -1651,6 +1824,8 @@
-
- void setAssertHandler(detail::assert_handler ah);
-
-+ void setCout(std::ostream* out);
-+
- int run();
- };
-
-@@ -1677,9 +1852,7 @@
- int numAssertsFailedCurrentTest;
- double seconds;
- int failure_flags; // use TestCaseFailureReason::Enum
--
-- DOCTEST_DECLARE_DEFAULTS(CurrentTestCaseStats);
-- DOCTEST_DELETE_COPIES(CurrentTestCaseStats);
-+ bool testCaseSuccess;
- };
-
- struct DOCTEST_INTERFACE TestCaseException
-@@ -1696,16 +1869,13 @@
- unsigned numTestCasesFailed;
- int numAsserts;
- int numAssertsFailed;
--
-- DOCTEST_DECLARE_DEFAULTS(TestRunStats);
-- DOCTEST_DELETE_COPIES(TestRunStats);
- };
-
- struct QueryData
- {
-- const TestRunStats* run_stats = nullptr;
-- String* data = nullptr;
-- unsigned num_data = 0;
-+ const TestRunStats* run_stats = nullptr;
-+ const TestCaseData** data = nullptr;
-+ unsigned num_data = 0;
- };
-
- struct DOCTEST_INTERFACE IReporter
-@@ -1724,6 +1894,8 @@
-
- // called when a test case is started (safe to cache a pointer to the input)
- virtual void test_case_start(const TestCaseData&) = 0;
-+ // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
-+ virtual void test_case_reenter(const TestCaseData&) = 0;
- // called when a test case has ended
- virtual void test_case_end(const CurrentTestCaseStats&) = 0;
-
-@@ -1778,10 +1950,11 @@
- #if !defined(DOCTEST_CONFIG_DISABLE)
-
- // common code in asserts - for convenience
--#define DOCTEST_ASSERT_LOG_AND_REACT(b) \
-+#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \
- if(b.log()) \
- DOCTEST_BREAK_INTO_DEBUGGER(); \
-- b.react()
-+ b.react(); \
-+ return !b.m_failed
-
- #ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
- #define DOCTEST_WRAP_IN_TRY(x) x;
-@@ -1789,27 +1962,26 @@
- #define DOCTEST_WRAP_IN_TRY(x) \
- try { \
- x; \
-- } catch(...) { _DOCTEST_RB.translateException(); }
-+ } catch(...) { DOCTEST_RB.translateException(); }
- #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
-
- #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
--#define DOCTEST_CAST_TO_VOID(x) \
-+#define DOCTEST_CAST_TO_VOID(...) \
- DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \
-- static_cast<void>(x); \
-+ static_cast<void>(__VA_ARGS__); \
- DOCTEST_GCC_SUPPRESS_WARNING_POP
- #else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
--#define DOCTEST_CAST_TO_VOID(x) x;
-+#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__;
- #endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
-
- // registers the test by initializing a dummy var with a function
- #define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \
-- global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
-+ global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \
- doctest::detail::regTest( \
- doctest::detail::TestCase( \
- f, __FILE__, __LINE__, \
- doctest_detail_test_suite_ns::getCurrentTestSuite()) * \
-- decorators); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END()
-+ decorators))
-
- #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \
- namespace { \
-@@ -1832,18 +2004,18 @@
-
- #define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \
- static doctest::detail::funcType proxy() { return f; } \
-- DOCTEST_REGISTER_FUNCTION(inline const, proxy(), decorators) \
-+ DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \
- static void f()
-
- // for registering tests
- #define DOCTEST_TEST_CASE(decorators) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
-+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
-
- // for registering tests in classes - requires C++17 for inline variables!
- #if __cplusplus >= 201703L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 12, 0) && _MSVC_LANG >= 201703L)
- #define DOCTEST_TEST_CASE_CLASS(decorators) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_PROXY_), \
-+ DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \
-+ DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \
- decorators)
- #else // DOCTEST_TEST_CASE_CLASS
- #define DOCTEST_TEST_CASE_CLASS(...) \
-@@ -1852,8 +2024,8 @@
-
- // for registering tests with a fixture
- #define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \
-- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
-+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \
-+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
-
- // for converting types to strings without the <typeinfo> header and demangling
- #define DOCTEST_TYPE_TO_STRING_IMPL(...) \
-@@ -1866,7 +2038,7 @@
- DOCTEST_TYPE_TO_STRING_IMPL(__VA_ARGS__) \
- } \
- } \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ static_assert(true, "")
-
- #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
- template <typename T> \
-@@ -1897,20 +2069,20 @@
-
- #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
- DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
-+ DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_))
-
- #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
-- doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
-- DOCTEST_GLOBAL_NO_WARNINGS_END()
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), \
-+ doctest::detail::instantiationHelper( \
-+ DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0)))
-
- #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
-- DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
-+ static_assert(true, "")
-
- #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
-- DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \
-+ static_assert(true, "")
-
- #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
-@@ -1919,11 +2091,11 @@
- static void anon()
-
- #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
-- DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__)
-+ DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__)
-
- // for subcases
- #define DOCTEST_SUBCASE(name) \
-- if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
-+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
- doctest::detail::Subcase(name, __FILE__, __LINE__))
-
- // for grouping tests in test suites by using code blocks
-@@ -1932,10 +2104,12 @@
- static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
-- static doctest::detail::TestSuite data; \
-+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
-+ static doctest::detail::TestSuite data{}; \
- static bool inited = false; \
- DOCTEST_MSVC_SUPPRESS_WARNING_POP \
- DOCTEST_CLANG_SUPPRESS_WARNING_POP \
-+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
- if(!inited) { \
- data* decorators; \
- inited = true; \
-@@ -1947,79 +2121,79 @@
- namespace ns_name
-
- #define DOCTEST_TEST_SUITE(decorators) \
-- DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUITE_))
-+ DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_))
-
- // for starting a testsuite block
- #define DOCTEST_TEST_SUITE_BEGIN(decorators) \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
-- doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END() \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \
-+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \
-+ static_assert(true, "")
-
- // for ending a testsuite block
- #define DOCTEST_TEST_SUITE_END \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
-- doctest::detail::setTestSuite(doctest::detail::TestSuite() * ""); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END() \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), \
-+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \
-+ typedef int DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_)
-
- // for registering exception translators
- #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \
- inline doctest::String translatorName(signature); \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)) = \
-- doctest::registerExceptionTranslator(translatorName); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END() \
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \
-+ doctest::registerExceptionTranslator(translatorName)) \
- doctest::String translatorName(signature)
-
- #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
-- DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \
-+ DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \
- signature)
-
- // for registering reporters
- #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
-- doctest::registerReporter<reporter>(name, priority, true); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), \
-+ doctest::registerReporter<reporter>(name, priority, true)) \
-+ static_assert(true, "")
-
- // for registering listeners
- #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
-- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
-- doctest::registerReporter<reporter>(name, priority, false); \
-- DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--
--// for logging
--#define DOCTEST_INFO(expression) \
-- DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \
-- DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), expression)
--
--#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, expression) \
-- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \
-- auto lambda_name = [&](std::ostream* s_name) { \
-+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), \
-+ doctest::registerReporter<reporter>(name, priority, false)) \
-+ static_assert(true, "")
-+
-+// clang-format off
-+// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557
-+#define DOCTEST_INFO(...) \
-+ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \
-+ DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \
-+ __VA_ARGS__)
-+// clang-format on
-+
-+#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
-+ auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
-+ [&](std::ostream* s_name) { \
- doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
- mb_name.m_stream = s_name; \
-- mb_name << expression; \
-- }; \
-- DOCTEST_MSVC_SUPPRESS_WARNING_POP \
-- auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name)
-+ mb_name * __VA_ARGS__; \
-+ })
-
--#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x)
-+#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
-
--#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \
-- do { \
-+#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \
-+ [&] { \
- doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \
-- mb << x; \
-- DOCTEST_ASSERT_LOG_AND_REACT(mb); \
-- } while((void)0, 0)
-+ mb * __VA_ARGS__; \
-+ if(mb.log()) \
-+ DOCTEST_BREAK_INTO_DEBUGGER(); \
-+ mb.react(); \
-+ }()
-
- // clang-format off
--#define DOCTEST_ADD_MESSAGE_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x)
--#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x)
--#define DOCTEST_ADD_FAIL_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x)
-+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
-+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
-+#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
- // clang-format on
-
--#define DOCTEST_MESSAGE(x) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, x)
--#define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x)
--#define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x)
-+#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
-+#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__)
-+#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__)
-
- #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
-
-@@ -2027,21 +2201,24 @@
-
- #define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
- __LINE__, #__VA_ARGS__); \
-- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult( \
-+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \
- doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
- << __VA_ARGS__)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB) \
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
-
- #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
-- do { \
-+ [&] { \
- DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \
-- } while((void)0, 0)
-+ }()
-
- #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
-+// necessary for <ASSERT>_MESSAGE
-+#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
-+
- #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
- doctest::detail::decomp_assert( \
-@@ -2059,102 +2236,113 @@
- #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
-
- // clang-format off
--#define DOCTEST_WARN_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while((void)0, 0)
--#define DOCTEST_CHECK_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while((void)0, 0)
--#define DOCTEST_REQUIRE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while((void)0, 0)
--#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while((void)0, 0)
--#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while((void)0, 0)
--#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while((void)0, 0)
-+#define DOCTEST_WARN_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); }()
-+#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); }()
-+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); }()
-+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); }()
-+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); }()
-+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); }()
- // clang-format on
-
--#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, ...) \
-- do { \
-+#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
-+ [&] { \
- if(!doctest::getContextOptions()->no_throw) { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-- __LINE__, #expr, #__VA_ARGS__); \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ __LINE__, #expr, #__VA_ARGS__, message); \
- try { \
- DOCTEST_CAST_TO_VOID(expr) \
-- } catch(const doctest::detail::remove_const< \
-- doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \
-- _DOCTEST_RB.translateException(); \
-- _DOCTEST_RB.m_threw_as = true; \
-- } catch(...) { _DOCTEST_RB.translateException(); } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-+ } catch(const typename doctest::detail::remove_const< \
-+ typename doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \
-+ DOCTEST_RB.translateException(); \
-+ DOCTEST_RB.m_threw_as = true; \
-+ } catch(...) { DOCTEST_RB.translateException(); } \
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
-+ } else { \
-+ return false; \
- } \
-- } while((void)0, 0)
-+ }()
-
--#define DOCTEST_ASSERT_THROWS_WITH(expr, assert_type, ...) \
-- do { \
-+#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \
-+ [&] { \
- if(!doctest::getContextOptions()->no_throw) { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-- __LINE__, #expr, __VA_ARGS__); \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ __LINE__, expr_str, "", __VA_ARGS__); \
- try { \
- DOCTEST_CAST_TO_VOID(expr) \
-- } catch(...) { _DOCTEST_RB.translateException(); } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-+ } catch(...) { DOCTEST_RB.translateException(); } \
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
-+ } else { \
-+ return false; \
- } \
-- } while((void)0, 0)
-+ }()
-
--#define DOCTEST_ASSERT_NOTHROW(expr, assert_type) \
-- do { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-- __LINE__, #expr); \
-+#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \
-+ [&] { \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ __LINE__, #__VA_ARGS__); \
- try { \
-- DOCTEST_CAST_TO_VOID(expr) \
-- } catch(...) { _DOCTEST_RB.translateException(); } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } while((void)0, 0)
-+ DOCTEST_CAST_TO_VOID(__VA_ARGS__) \
-+ } catch(...) { DOCTEST_RB.translateException(); } \
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
-+ }()
-
- // clang-format off
--#define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS, "")
--#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS, "")
--#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS, "")
--
--#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, __VA_ARGS__)
--#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, __VA_ARGS__)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, __VA_ARGS__)
--
--#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
--#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
--#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
--
--#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW)
--#define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW)
--#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW)
--
--#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS(expr); } while((void)0, 0)
--#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS(expr); } while((void)0, 0)
--#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS(expr); } while((void)0, 0)
--#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while((void)0, 0)
--#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while((void)0, 0)
--#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while((void)0, 0)
--#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, ex); } while((void)0, 0)
--#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, ex); } while((void)0, 0)
--#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, ex); } while((void)0, 0)
--#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while((void)0, 0)
--#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while((void)0, 0)
--#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while((void)0, 0)
-+#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
-+#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "")
-+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "")
-+
-+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
-+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
-+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
-+
-+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
-+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
-+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
-+
-+#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
-+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
-+
-+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__)
-+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
-+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
-+
-+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); }()
-+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); }()
-+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); }()
-+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); }()
-+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); }()
-+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); }()
-+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); }()
-+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); }()
-+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); }()
-+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); }()
-+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); }()
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); }()
-+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); }()
-+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); }()
-+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] {DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); }()
- // clang-format on
-
- #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
- #define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
-- do { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ [&] { \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
- __LINE__, #__VA_ARGS__); \
- DOCTEST_WRAP_IN_TRY( \
-- _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
-+ DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
- __VA_ARGS__)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } while((void)0, 0)
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
-+ }()
-
- #define DOCTEST_UNARY_ASSERT(assert_type, ...) \
-- do { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
-+ [&] { \
-+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
- __LINE__, #__VA_ARGS__); \
-- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(__VA_ARGS__)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } while((void)0, 0)
-+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \
-+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
-+ }()
-
- #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
-@@ -2205,6 +2393,9 @@
- #undef DOCTEST_WARN_THROWS_WITH
- #undef DOCTEST_CHECK_THROWS_WITH
- #undef DOCTEST_REQUIRE_THROWS_WITH
-+#undef DOCTEST_WARN_THROWS_WITH_AS
-+#undef DOCTEST_CHECK_THROWS_WITH_AS
-+#undef DOCTEST_REQUIRE_THROWS_WITH_AS
- #undef DOCTEST_WARN_NOTHROW
- #undef DOCTEST_CHECK_NOTHROW
- #undef DOCTEST_REQUIRE_NOTHROW
-@@ -2218,37 +2409,46 @@
- #undef DOCTEST_WARN_THROWS_WITH_MESSAGE
- #undef DOCTEST_CHECK_THROWS_WITH_MESSAGE
- #undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
-+#undef DOCTEST_WARN_THROWS_WITH_AS_MESSAGE
-+#undef DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE
-+#undef DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE
- #undef DOCTEST_WARN_NOTHROW_MESSAGE
- #undef DOCTEST_CHECK_NOTHROW_MESSAGE
- #undef DOCTEST_REQUIRE_NOTHROW_MESSAGE
-
- #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
-
--#define DOCTEST_WARN_THROWS(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
--#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
--#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
--
--#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0)
-+#define DOCTEST_WARN_THROWS(...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS(...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_WARN_NOTHROW(...) ([] { return false; })
-+#define DOCTEST_CHECK_NOTHROW(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_NOTHROW(...) ([] { return false; })
-+
-+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-
- #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
-
-@@ -2290,35 +2490,32 @@
-
- // for registering tests
- #define DOCTEST_TEST_CASE(name) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
-+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
-
- // for registering tests in classes
- #define DOCTEST_TEST_CASE_CLASS(name) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
-+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
-
- // for registering tests with a fixture
- #define DOCTEST_TEST_CASE_FIXTURE(x, name) \
-- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
-+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \
-+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
-
- // for converting types to strings without the <typeinfo> header and demangling
--#define DOCTEST_TYPE_TO_STRING(...) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "")
- #define DOCTEST_TYPE_TO_STRING_IMPL(...)
-
- // for typed tests
- #define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \
- template <typename type> \
-- inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
-+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
-
- #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \
- template <typename type> \
-- inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
-+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
-
--#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--
--#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "")
-+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "")
-
- // for subcases
- #define DOCTEST_SUBCASE(name)
-@@ -2327,92 +2524,159 @@
- #define DOCTEST_TEST_SUITE(name) namespace
-
- // for starting a testsuite block
--#define DOCTEST_TEST_SUITE_BEGIN(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "")
-
- // for ending a testsuite block
--#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-+#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_)
-
- #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
- template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
-- static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature)
-+ static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature)
-
- #define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
- #define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
-
--#define DOCTEST_INFO(x) ((void)0)
--#define DOCTEST_CAPTURE(x) ((void)0)
--#define DOCTEST_ADD_MESSAGE_AT(file, line, x) ((void)0)
--#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) ((void)0)
--#define DOCTEST_ADD_FAIL_AT(file, line, x) ((void)0)
--#define DOCTEST_MESSAGE(x) ((void)0)
--#define DOCTEST_FAIL_CHECK(x) ((void)0)
--#define DOCTEST_FAIL(x) ((void)0)
--
--#define DOCTEST_WARN(...) ((void)0)
--#define DOCTEST_CHECK(...) ((void)0)
--#define DOCTEST_REQUIRE(...) ((void)0)
--#define DOCTEST_WARN_FALSE(...) ((void)0)
--#define DOCTEST_CHECK_FALSE(...) ((void)0)
--#define DOCTEST_REQUIRE_FALSE(...) ((void)0)
--
--#define DOCTEST_WARN_MESSAGE(cond, msg) ((void)0)
--#define DOCTEST_CHECK_MESSAGE(cond, msg) ((void)0)
--#define DOCTEST_REQUIRE_MESSAGE(cond, msg) ((void)0)
--#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) ((void)0)
--#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) ((void)0)
--#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) ((void)0)
--
--#define DOCTEST_WARN_THROWS(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
--#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0)
--#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0)
--#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
--#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
--
--#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0)
--#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0)
--
--#define DOCTEST_WARN_EQ(...) ((void)0)
--#define DOCTEST_CHECK_EQ(...) ((void)0)
--#define DOCTEST_REQUIRE_EQ(...) ((void)0)
--#define DOCTEST_WARN_NE(...) ((void)0)
--#define DOCTEST_CHECK_NE(...) ((void)0)
--#define DOCTEST_REQUIRE_NE(...) ((void)0)
--#define DOCTEST_WARN_GT(...) ((void)0)
--#define DOCTEST_CHECK_GT(...) ((void)0)
--#define DOCTEST_REQUIRE_GT(...) ((void)0)
--#define DOCTEST_WARN_LT(...) ((void)0)
--#define DOCTEST_CHECK_LT(...) ((void)0)
--#define DOCTEST_REQUIRE_LT(...) ((void)0)
--#define DOCTEST_WARN_GE(...) ((void)0)
--#define DOCTEST_CHECK_GE(...) ((void)0)
--#define DOCTEST_REQUIRE_GE(...) ((void)0)
--#define DOCTEST_WARN_LE(...) ((void)0)
--#define DOCTEST_CHECK_LE(...) ((void)0)
--#define DOCTEST_REQUIRE_LE(...) ((void)0)
--
--#define DOCTEST_WARN_UNARY(...) ((void)0)
--#define DOCTEST_CHECK_UNARY(...) ((void)0)
--#define DOCTEST_REQUIRE_UNARY(...) ((void)0)
--#define DOCTEST_WARN_UNARY_FALSE(...) ((void)0)
--#define DOCTEST_CHECK_UNARY_FALSE(...) ((void)0)
--#define DOCTEST_REQUIRE_UNARY_FALSE(...) ((void)0)
-+#define DOCTEST_INFO(...) (static_cast<void>(0))
-+#define DOCTEST_CAPTURE(x) (static_cast<void>(0))
-+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0))
-+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0))
-+#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0))
-+#define DOCTEST_MESSAGE(...) (static_cast<void>(0))
-+#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
-+#define DOCTEST_FAIL(...) (static_cast<void>(0))
-+
-+#ifdef DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
-+
-+#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+
-+#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }()
-+#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }()
-+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }()
-+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
-+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
-+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
-+
-+namespace doctest {
-+namespace detail {
-+#define DOCTEST_RELATIONAL_OP(name, op) \
-+ template <typename L, typename R> \
-+ bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; }
-+
-+ DOCTEST_RELATIONAL_OP(eq, ==)
-+ DOCTEST_RELATIONAL_OP(ne, !=)
-+ DOCTEST_RELATIONAL_OP(lt, <)
-+ DOCTEST_RELATIONAL_OP(gt, >)
-+ DOCTEST_RELATIONAL_OP(le, <=)
-+ DOCTEST_RELATIONAL_OP(ge, >=)
-+} // namespace detail
-+} // namespace doctest
-+
-+#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
-+#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
-+#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
-+#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
-+#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
-+#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
-+#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }()
-+#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
-+
-+#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
-+
-+#define DOCTEST_WARN(...) ([] { return false; })
-+#define DOCTEST_CHECK(...) ([] { return false; })
-+#define DOCTEST_REQUIRE(...) ([] { return false; })
-+#define DOCTEST_WARN_FALSE(...) ([] { return false; })
-+#define DOCTEST_CHECK_FALSE(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_FALSE(...) ([] { return false; })
-+
-+#define DOCTEST_WARN_MESSAGE(cond, ...) ([] { return false; })
-+#define DOCTEST_CHECK_MESSAGE(cond, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) ([] { return false; })
-+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) ([] { return false; })
-+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) ([] { return false; })
-+
-+#define DOCTEST_WARN_EQ(...) ([] { return false; })
-+#define DOCTEST_CHECK_EQ(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_EQ(...) ([] { return false; })
-+#define DOCTEST_WARN_NE(...) ([] { return false; })
-+#define DOCTEST_CHECK_NE(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_NE(...) ([] { return false; })
-+#define DOCTEST_WARN_GT(...) ([] { return false; })
-+#define DOCTEST_CHECK_GT(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_GT(...) ([] { return false; })
-+#define DOCTEST_WARN_LT(...) ([] { return false; })
-+#define DOCTEST_CHECK_LT(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_LT(...) ([] { return false; })
-+#define DOCTEST_WARN_GE(...) ([] { return false; })
-+#define DOCTEST_CHECK_GE(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_GE(...) ([] { return false; })
-+#define DOCTEST_WARN_LE(...) ([] { return false; })
-+#define DOCTEST_CHECK_LE(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_LE(...) ([] { return false; })
-+
-+#define DOCTEST_WARN_UNARY(...) ([] { return false; })
-+#define DOCTEST_CHECK_UNARY(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_UNARY(...) ([] { return false; })
-+#define DOCTEST_WARN_UNARY_FALSE(...) ([] { return false; })
-+#define DOCTEST_CHECK_UNARY_FALSE(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_UNARY_FALSE(...) ([] { return false; })
-+
-+#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
-+
-+// TODO: think about if these also need to work properly even when doctest is disabled
-+#define DOCTEST_WARN_THROWS(...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS(...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ([] { return false; })
-+#define DOCTEST_WARN_NOTHROW(...) ([] { return false; })
-+#define DOCTEST_CHECK_NOTHROW(...) ([] { return false; })
-+#define DOCTEST_REQUIRE_NOTHROW(...) ([] { return false; })
-+
-+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) ([] { return false; })
-+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) ([] { return false; })
-+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) ([] { return false; })
-
- #endif // DOCTEST_CONFIG_DISABLE
-
-@@ -2444,7 +2708,7 @@
- #define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
- #define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
-
--#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INVOKE
-+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
- // clang-format on
-
- // BDD style macros
-@@ -2464,132 +2728,138 @@
- // == SHORT VERSIONS OF THE MACROS
- #if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
-
--#define TEST_CASE DOCTEST_TEST_CASE
--#define TEST_CASE_CLASS DOCTEST_TEST_CASE_CLASS
--#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE
--#define TYPE_TO_STRING DOCTEST_TYPE_TO_STRING
--#define TEST_CASE_TEMPLATE DOCTEST_TEST_CASE_TEMPLATE
--#define TEST_CASE_TEMPLATE_DEFINE DOCTEST_TEST_CASE_TEMPLATE_DEFINE
--#define TEST_CASE_TEMPLATE_INVOKE DOCTEST_TEST_CASE_TEMPLATE_INVOKE
--#define TEST_CASE_TEMPLATE_APPLY DOCTEST_TEST_CASE_TEMPLATE_APPLY
--#define SUBCASE DOCTEST_SUBCASE
--#define TEST_SUITE DOCTEST_TEST_SUITE
--#define TEST_SUITE_BEGIN DOCTEST_TEST_SUITE_BEGIN
-+#define TEST_CASE(name) DOCTEST_TEST_CASE(name)
-+#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
-+#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
-+#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
-+#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
-+#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
-+#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
-+#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
-+#define SUBCASE(name) DOCTEST_SUBCASE(name)
-+#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
-+#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
- #define TEST_SUITE_END DOCTEST_TEST_SUITE_END
--#define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR
--#define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER
--#define REGISTER_LISTENER DOCTEST_REGISTER_LISTENER
--#define INFO DOCTEST_INFO
--#define CAPTURE DOCTEST_CAPTURE
--#define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT
--#define ADD_FAIL_CHECK_AT DOCTEST_ADD_FAIL_CHECK_AT
--#define ADD_FAIL_AT DOCTEST_ADD_FAIL_AT
--#define MESSAGE DOCTEST_MESSAGE
--#define FAIL_CHECK DOCTEST_FAIL_CHECK
--#define FAIL DOCTEST_FAIL
--#define TO_LVALUE DOCTEST_TO_LVALUE
--
--#define WARN DOCTEST_WARN
--#define WARN_FALSE DOCTEST_WARN_FALSE
--#define WARN_THROWS DOCTEST_WARN_THROWS
--#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS
--#define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH
--#define WARN_NOTHROW DOCTEST_WARN_NOTHROW
--#define CHECK DOCTEST_CHECK
--#define CHECK_FALSE DOCTEST_CHECK_FALSE
--#define CHECK_THROWS DOCTEST_CHECK_THROWS
--#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS
--#define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH
--#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW
--#define REQUIRE DOCTEST_REQUIRE
--#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE
--#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS
--#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS
--#define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH
--#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW
--
--#define WARN_MESSAGE DOCTEST_WARN_MESSAGE
--#define WARN_FALSE_MESSAGE DOCTEST_WARN_FALSE_MESSAGE
--#define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE
--#define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE
--#define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE
--#define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE
--#define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE
--#define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE
--#define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE
--#define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE
--#define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE
--#define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE
--#define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE
--#define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE
--#define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE
--#define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE
--#define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
--#define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE
--
--#define SCENARIO DOCTEST_SCENARIO
--#define SCENARIO_CLASS DOCTEST_SCENARIO_CLASS
--#define SCENARIO_TEMPLATE DOCTEST_SCENARIO_TEMPLATE
--#define SCENARIO_TEMPLATE_DEFINE DOCTEST_SCENARIO_TEMPLATE_DEFINE
--#define GIVEN DOCTEST_GIVEN
--#define WHEN DOCTEST_WHEN
--#define AND_WHEN DOCTEST_AND_WHEN
--#define THEN DOCTEST_THEN
--#define AND_THEN DOCTEST_AND_THEN
--
--#define WARN_EQ DOCTEST_WARN_EQ
--#define CHECK_EQ DOCTEST_CHECK_EQ
--#define REQUIRE_EQ DOCTEST_REQUIRE_EQ
--#define WARN_NE DOCTEST_WARN_NE
--#define CHECK_NE DOCTEST_CHECK_NE
--#define REQUIRE_NE DOCTEST_REQUIRE_NE
--#define WARN_GT DOCTEST_WARN_GT
--#define CHECK_GT DOCTEST_CHECK_GT
--#define REQUIRE_GT DOCTEST_REQUIRE_GT
--#define WARN_LT DOCTEST_WARN_LT
--#define CHECK_LT DOCTEST_CHECK_LT
--#define REQUIRE_LT DOCTEST_REQUIRE_LT
--#define WARN_GE DOCTEST_WARN_GE
--#define CHECK_GE DOCTEST_CHECK_GE
--#define REQUIRE_GE DOCTEST_REQUIRE_GE
--#define WARN_LE DOCTEST_WARN_LE
--#define CHECK_LE DOCTEST_CHECK_LE
--#define REQUIRE_LE DOCTEST_REQUIRE_LE
--#define WARN_UNARY DOCTEST_WARN_UNARY
--#define CHECK_UNARY DOCTEST_CHECK_UNARY
--#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
--#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
--#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
--#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
-+#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
-+#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
-+#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
-+#define INFO(...) DOCTEST_INFO(__VA_ARGS__)
-+#define CAPTURE(x) DOCTEST_CAPTURE(x)
-+#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
-+#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
-+#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
-+#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
-+#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
-+#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
-+#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
-+
-+#define WARN(...) DOCTEST_WARN(__VA_ARGS__)
-+#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
-+#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
-+#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
-+#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
-+#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
-+#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
-+#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
-+#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
-+#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
-+#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
-+#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
-+#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
-+#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
-+#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
-+#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
-+#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
-+#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
-+#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
-+#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
-+#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
-+
-+#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
-+#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
-+#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
-+#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
-+#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
-+#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
-+#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
-+#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
-+#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
-+#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
-+#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
-+#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
-+#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
-+#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
-+#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
-+#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
-+#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
-+#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
-+#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
-+#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
-+#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
-+
-+#define SCENARIO(name) DOCTEST_SCENARIO(name)
-+#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
-+#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
-+#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
-+#define GIVEN(name) DOCTEST_GIVEN(name)
-+#define WHEN(name) DOCTEST_WHEN(name)
-+#define AND_WHEN(name) DOCTEST_AND_WHEN(name)
-+#define THEN(name) DOCTEST_THEN(name)
-+#define AND_THEN(name) DOCTEST_AND_THEN(name)
-+
-+#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
-+#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
-+#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
-+#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
-+#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
-+#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
-+#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
-+#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
-+#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
-+#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
-+#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
-+#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
-+#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
-+#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
-+#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
-+#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
-+#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
-+#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
-+#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
-+#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
-+#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
-+#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
-+#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
-+#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
-
- // KEPT FOR BACKWARDS COMPATIBILITY
--#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ
--#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ
--#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ
--#define FAST_WARN_NE DOCTEST_FAST_WARN_NE
--#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE
--#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE
--#define FAST_WARN_GT DOCTEST_FAST_WARN_GT
--#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT
--#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT
--#define FAST_WARN_LT DOCTEST_FAST_WARN_LT
--#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT
--#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT
--#define FAST_WARN_GE DOCTEST_FAST_WARN_GE
--#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE
--#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE
--#define FAST_WARN_LE DOCTEST_FAST_WARN_LE
--#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE
--#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE
--
--#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY
--#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY
--#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY
--#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE
--#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE
--#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE
-+#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
-+#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
-+#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
-+#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
-+#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
-+#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
-+#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
-+#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
-+#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
-+#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
-+#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
-+#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
-+#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
-+#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
-+#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
-+#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
-+#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
-+#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
-+
-+#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
-+#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
-+#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
-+#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
-+#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
-+#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
-
--#define TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE
-+#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
-
- #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
-
-@@ -2626,6 +2896,8 @@
- DOCTEST_MSVC_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
-
-+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
-+
- #endif // DOCTEST_LIBRARY_INCLUDED
-
- #ifndef DOCTEST_SINGLE_HEADER
-@@ -2645,13 +2917,11 @@
-
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
-
-+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
-+
- DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
-@@ -2659,64 +2929,35 @@
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
--DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
-+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
-
- DOCTEST_GCC_SUPPRESS_WARNING_PUSH
--DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
--DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
--DOCTEST_GCC_SUPPRESS_WARNING("-Winline")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
--DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
- DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
-
- DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
--DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
--DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
--DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
- DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
--DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
--DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
--DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
- DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
- DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
- DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
- DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
--DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding in structs
--DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
- DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
--DOCTEST_MSVC_SUPPRESS_WARNING(5045) // Spectre mitigation stuff
--DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
--DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
- DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
--// static analysis
--DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
--DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
--DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
--DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtor...
-+DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed
-
- DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
-
-@@ -2724,7 +2965,7 @@
- #include <ctime>
- #include <cmath>
- #include <climits>
--// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
-+// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37
- #ifdef __BORLANDC__
- #include <math.h>
- #endif // __BORLANDC__
-@@ -2746,9 +2987,7 @@
- #include <map>
- #include <exception>
- #include <stdexcept>
--#ifdef DOCTEST_CONFIG_POSIX_SIGNALS
- #include <csignal>
--#endif // DOCTEST_CONFIG_POSIX_SIGNALS
- #include <cfloat>
- #include <cctype>
- #include <cstdint>
-@@ -2773,7 +3012,7 @@
- #ifdef __AFXDLL
- #include <AfxWin.h>
- #else
--#include <Windows.h>
-+#include <windows.h>
- #endif
- #include <io.h>
-
-@@ -2784,6 +3023,12 @@
-
- #endif // DOCTEST_PLATFORM_WINDOWS
-
-+// this is a fix for https://github.com/doctest/doctest/issues/348
-+// https://mail.gnome.org/archives/xml/2012-January/msg00000.html
-+#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
-+#define STDOUT_FILENO fileno(stdout)
-+#endif // HAVE_UNISTD_H
-+
- DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
-
- // counts the number of elements in a C array
-@@ -2800,7 +3045,19 @@
- #endif
-
- #ifndef DOCTEST_THREAD_LOCAL
-+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
-+#define DOCTEST_THREAD_LOCAL
-+#else // DOCTEST_MSVC
- #define DOCTEST_THREAD_LOCAL thread_local
-+#endif // DOCTEST_MSVC
-+#endif // DOCTEST_THREAD_LOCAL
-+
-+#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
-+#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
-+#endif
-+
-+#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
-+#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
- #endif
-
- #ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-@@ -2809,12 +3066,38 @@
- #define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
- #endif
-
-+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
-+#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
-+#endif
-+
-+#ifndef DOCTEST_CDECL
-+#define DOCTEST_CDECL __cdecl
-+#endif
-+
- namespace doctest {
-
- bool is_running_in_test = false;
-
- namespace {
- using namespace detail;
-+
-+ template <typename Ex>
-+ DOCTEST_NORETURN void throw_exception(Ex const& e) {
-+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-+ throw e;
-+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
-+ std::cerr << "doctest will terminate because it needed to throw an exception.\n"
-+ << "The message was: " << e.what() << '\n';
-+ std::terminate();
-+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-+ }
-+
-+#ifndef DOCTEST_INTERNAL_ERROR
-+#define DOCTEST_INTERNAL_ERROR(msg) \
-+ throw_exception(std::logic_error( \
-+ __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
-+#endif // DOCTEST_INTERNAL_ERROR
-+
- // case insensitive strcmp
- int stricmp(const char* a, const char* b) {
- for(;; a++, b++) {
-@@ -2858,8 +3141,6 @@
- } // namespace
-
- namespace detail {
-- void my_memcpy(void* dest, const void* src, unsigned num) { memcpy(dest, src, num); }
--
- String rawMemoryToString(const void* object, unsigned size) {
- // Reverse order for little endian architectures
- int i = 0, end = static_cast<int>(size), inc = 1;
-@@ -2869,49 +3150,76 @@
- }
-
- unsigned const char* bytes = static_cast<unsigned const char*>(object);
-- std::ostringstream oss;
-- oss << "0x" << std::setfill('0') << std::hex;
-+ std::ostream* oss = tlssPush();
-+ *oss << "0x" << std::setfill('0') << std::hex;
- for(; i != end; i += inc)
-- oss << std::setw(2) << static_cast<unsigned>(bytes[i]);
-- return oss.str().c_str();
-+ *oss << std::setw(2) << static_cast<unsigned>(bytes[i]);
-+ return tlssPop();
- }
-
-- DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp)
-+ DOCTEST_THREAD_LOCAL class
-+ {
-+ std::vector<std::streampos> stack;
-+ std::stringstream ss;
-+
-+ public:
-+ std::ostream* push() {
-+ stack.push_back(ss.tellp());
-+ return &ss;
-+ }
-+
-+ String pop() {
-+ if (stack.empty())
-+ DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!");
-+
-+ std::streampos pos = stack.back();
-+ stack.pop_back();
-+ unsigned sz = static_cast<unsigned>(ss.tellp() - pos);
-+ ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out);
-+ return String(ss, sz);
-+ }
-+ } g_oss;
-
-- std::ostream* getTlsOss() {
-- g_oss.clear(); // there shouldn't be anything worth clearing in the flags
-- g_oss.str(""); // the slow way of resetting a string stream
-- //g_oss.seekp(0); // optimal reset - as seen here: https://stackoverflow.com/a/624291/3162383
-- return &g_oss;
-+ std::ostream* tlssPush() {
-+ return g_oss.push();
- }
-
-- String getTlsOssResult() {
-- //g_oss << std::ends; // needed - as shown here: https://stackoverflow.com/a/624291/3162383
-- return g_oss.str().c_str();
-+ String tlssPop() {
-+ return g_oss.pop();
- }
-
- #ifndef DOCTEST_CONFIG_DISABLE
-
-- typedef uint64_t UInt64;
-+namespace timer_large_integer
-+{
-+
-+#if defined(DOCTEST_PLATFORM_WINDOWS)
-+ typedef ULONGLONG type;
-+#else // DOCTEST_PLATFORM_WINDOWS
-+ typedef std::uint64_t type;
-+#endif // DOCTEST_PLATFORM_WINDOWS
-+}
-+
-+typedef timer_large_integer::type ticks_t;
-
- #ifdef DOCTEST_CONFIG_GETCURRENTTICKS
-- UInt64 getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
-+ ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
- #elif defined(DOCTEST_PLATFORM_WINDOWS)
-- UInt64 getCurrentTicks() {
-- static UInt64 hz = 0, hzo = 0;
-- if(!hz) {
-- QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&hz));
-- QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&hzo));
-- }
-- UInt64 t;
-- QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&t));
-- return ((t - hzo) * 1000000) / hz;
-+ ticks_t getCurrentTicks() {
-+ static LARGE_INTEGER hz = {0}, hzo = {0};
-+ if(!hz.QuadPart) {
-+ QueryPerformanceFrequency(&hz);
-+ QueryPerformanceCounter(&hzo);
-+ }
-+ LARGE_INTEGER t;
-+ QueryPerformanceCounter(&t);
-+ return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart;
- }
- #else // DOCTEST_PLATFORM_WINDOWS
-- UInt64 getCurrentTicks() {
-+ ticks_t getCurrentTicks() {
- timeval t;
- gettimeofday(&t, nullptr);
-- return static_cast<UInt64>(t.tv_sec) * 1000000 + static_cast<UInt64>(t.tv_usec);
-+ return static_cast<ticks_t>(t.tv_sec) * 1000000 + static_cast<ticks_t>(t.tv_usec);
- }
- #endif // DOCTEST_PLATFORM_WINDOWS
-
-@@ -2924,24 +3232,111 @@
- //unsigned int getElapsedMilliseconds() const {
- // return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
- //}
-- double getElapsedSeconds() const { return getElapsedMicroseconds() / 1000000.0; }
-+ double getElapsedSeconds() const { return static_cast<double>(getCurrentTicks() - m_ticks) / 1000000.0; }
-+
-+ private:
-+ ticks_t m_ticks = 0;
-+ };
-+
-+#ifdef DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
-+ template <typename T>
-+ using AtomicOrMultiLaneAtomic = std::atomic<T>;
-+#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
-+ // Provides a multilane implementation of an atomic variable that supports add, sub, load,
-+ // store. Instead of using a single atomic variable, this splits up into multiple ones,
-+ // each sitting on a separate cache line. The goal is to provide a speedup when most
-+ // operations are modifying. It achieves this with two properties:
-+ //
-+ // * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
-+ // * Each atomic sits on a separate cache line, so false sharing is reduced.
-+ //
-+ // The disadvantage is that there is a small overhead due to the use of TLS, and load/store
-+ // is slower because all atomics have to be accessed.
-+ template <typename T>
-+ class MultiLaneAtomic
-+ {
-+ struct CacheLineAlignedAtomic
-+ {
-+ std::atomic<T> atomic{};
-+ char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(std::atomic<T>)];
-+ };
-+ CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
-+
-+ static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
-+ "guarantee one atomic takes exactly one cache line");
-+
-+ public:
-+ T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
-+
-+ T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
-+
-+ T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
-+ return myAtomic().fetch_add(arg, order);
-+ }
-+
-+ T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
-+ return myAtomic().fetch_sub(arg, order);
-+ }
-+
-+ operator T() const DOCTEST_NOEXCEPT { return load(); }
-+
-+ T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
-+ auto result = T();
-+ for(auto const& c : m_atomics) {
-+ result += c.atomic.load(order);
-+ }
-+ return result;
-+ }
-+
-+ T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this]
-+ store(desired);
-+ return desired;
-+ }
-+
-+ void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
-+ // first value becomes desired", all others become 0.
-+ for(auto& c : m_atomics) {
-+ c.atomic.store(desired, order);
-+ desired = {};
-+ }
-+ }
-
- private:
-- UInt64 m_ticks = 0;
-+ // Each thread has a different atomic that it operates on. If more than NumLanes threads
-+ // use this, some will use the same atomic. So performance will degrade a bit, but still
-+ // everything will work.
-+ //
-+ // The logic here is a bit tricky. The call should be as fast as possible, so that there
-+ // is minimal to no overhead in determining the correct atomic for the current thread.
-+ //
-+ // 1. A global static counter laneCounter counts continuously up.
-+ // 2. Each successive thread will use modulo operation of that counter so it gets an atomic
-+ // assigned in a round-robin fashion.
-+ // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
-+ // little overhead.
-+ std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
-+ static std::atomic<size_t> laneCounter;
-+ DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
-+ laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
-+
-+ return m_atomics[tlsLaneIdx].atomic;
-+ }
- };
-
-+ template <typename T>
-+ using AtomicOrMultiLaneAtomic = MultiLaneAtomic<T>;
-+#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
-+
- // this holds both parameters from the command line and runtime data for tests
- struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
- {
-- std::atomic<int> numAssertsCurrentTest_atomic;
-- std::atomic<int> numAssertsFailedCurrentTest_atomic;
-+ AtomicOrMultiLaneAtomic<int> numAssertsCurrentTest_atomic;
-+ AtomicOrMultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
-
- std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
-
- std::vector<IReporter*> reporters_currently_used;
-
-- const TestCase* currentTest = nullptr;
--
- assert_handler ah = nullptr;
-
- Timer timer;
-@@ -2949,10 +3344,11 @@
- std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
-
- // stuff for subcases
-- std::set<SubcaseSignature> subcasesPassed;
-- std::set<int> subcasesEnteredLevels;
-- int subcasesCurrentLevel;
-- bool should_reenter;
-+ std::vector<SubcaseSignature> subcasesStack;
-+ std::set<decltype(subcasesStack)> subcasesPassed;
-+ int subcasesCurrentMaxLevel;
-+ bool should_reenter;
-+ std::atomic<bool> shouldLogCurrentException;
-
- void resetRunData() {
- numTestCases = 0;
-@@ -3002,7 +3398,8 @@
- (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
-
- // if any subcase has failed - the whole test case has failed
-- if(failure_flags && !ok_to_fail)
-+ testCaseSuccess = !(failure_flags && !ok_to_fail);
-+ if(!testCaseSuccess)
- numTestCasesFailed++;
- }
- };
-@@ -3017,6 +3414,21 @@
- #endif // DOCTEST_CONFIG_DISABLE
- } // namespace detail
-
-+char* String::allocate(unsigned sz) {
-+ if (sz <= last) {
-+ buf[sz] = '\0';
-+ setLast(last - sz);
-+ return buf;
-+ } else {
-+ setOnHeap();
-+ data.size = sz;
-+ data.capacity = data.size + 1;
-+ data.ptr = new char[data.capacity];
-+ data.ptr[sz] = '\0';
-+ return data.ptr;
-+ }
-+}
-+
- void String::setOnHeap() { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
- void String::setLast(unsigned in) { buf[last] = char(in); }
-
-@@ -3024,11 +3436,7 @@
- if(other.isOnStack()) {
- memcpy(buf, other.buf, len);
- } else {
-- setOnHeap();
-- data.size = other.data.size;
-- data.capacity = data.size + 1;
-- data.ptr = new char[data.capacity];
-- memcpy(data.ptr, other.data.ptr, data.size + 1);
-+ memcpy(allocate(other.data.size), other.data.ptr, other.data.size);
- }
- }
-
-@@ -3040,22 +3448,18 @@
- String::~String() {
- if(!isOnStack())
- delete[] data.ptr;
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- }
-
- String::String(const char* in)
- : String(in, strlen(in)) {}
-
- String::String(const char* in, unsigned in_size) {
-- if(in_size <= last) {
-- memcpy(buf, in, in_size + 1);
-- setLast(last - in_size);
-- } else {
-- setOnHeap();
-- data.size = in_size;
-- data.capacity = data.size + 1;
-- data.ptr = new char[data.capacity];
-- memcpy(data.ptr, in, in_size + 1);
-- }
-+ memcpy(allocate(in_size), in, in_size);
-+}
-+
-+String::String(std::istream& in, unsigned in_size) {
-+ in.read(allocate(in_size), in_size);
- }
-
- String::String(const String& other) { copy(other); }
-@@ -3079,6 +3483,7 @@
- if(total_size < len) {
- // append to the current stack space
- memcpy(buf + my_old_size, other.c_str(), other_size + 1);
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- setLast(last - total_size);
- } else {
- // alloc new chunk
-@@ -3120,8 +3525,6 @@
- return *this;
- }
-
--String String::operator+(const String& other) const { return String(*this) += other; }
--
- String::String(String&& other) {
- memcpy(buf, other.buf, len);
- other.buf[0] = '\0';
-@@ -3165,7 +3568,7 @@
-
- int String::compare(const char* other, bool no_case) const {
- if(no_case)
-- return stricmp(c_str(), other);
-+ return doctest::stricmp(c_str(), other);
- return std::strcmp(c_str(), other);
- }
-
-@@ -3173,6 +3576,9 @@
- return compare(other.c_str(), no_case);
- }
-
-+// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-+String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; }
-+
- // clang-format off
- bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
- bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
-@@ -3219,6 +3625,10 @@
- case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH";
- case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH";
-
-+ case assertType::DT_WARN_THROWS_WITH_AS : return "WARN_THROWS_WITH_AS";
-+ case assertType::DT_CHECK_THROWS_WITH_AS : return "CHECK_THROWS_WITH_AS";
-+ case assertType::DT_REQUIRE_THROWS_WITH_AS : return "REQUIRE_THROWS_WITH_AS";
-+
- case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
- case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
- case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
-@@ -3268,6 +3678,7 @@
- DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
- // depending on the current options this will remove the path of filenames
- const char* skipPathFromFilename(const char* file) {
-+#ifndef DOCTEST_CONFIG_DISABLE
- if(getContextOptions()->no_path_in_filenames) {
- auto back = std::strrchr(file, '\\');
- auto forward = std::strrchr(file, '/');
-@@ -3277,41 +3688,26 @@
- return forward + 1;
- }
- }
-+#endif // DOCTEST_CONFIG_DISABLE
- return file;
- }
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
-
--DOCTEST_DEFINE_DEFAULTS(TestCaseData);
--DOCTEST_DEFINE_COPIES(TestCaseData);
--
--DOCTEST_DEFINE_DEFAULTS(AssertData);
--
--DOCTEST_DEFINE_DEFAULTS(MessageData);
--
--SubcaseSignature::SubcaseSignature(const char* name, const char* file, int line)
-- : m_name(name)
-- , m_file(file)
-- , m_line(line) {}
--
--DOCTEST_DEFINE_DEFAULTS(SubcaseSignature);
--DOCTEST_DEFINE_COPIES(SubcaseSignature);
--
- bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
- if(m_line != other.m_line)
- return m_line < other.m_line;
- if(std::strcmp(m_file, other.m_file) != 0)
- return std::strcmp(m_file, other.m_file) < 0;
-- return std::strcmp(m_name, other.m_name) < 0;
-+ return m_name.compare(other.m_name) < 0;
- }
-
- IContextScope::IContextScope() = default;
- IContextScope::~IContextScope() = default;
-
--DOCTEST_DEFINE_DEFAULTS(ContextOptions);
--
- #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- String toString(char* in) { return toString(static_cast<const char*>(in)); }
-+// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
- #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- String toString(bool in) { return in ? "true" : "false"; }
-@@ -3341,7 +3737,7 @@
- String toString(std::nullptr_t) { return "NULL"; }
-
- #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
--// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
-+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
- String toString(const std::string& in) { return in.c_str(); }
- #endif // VS 2019
-
-@@ -3350,8 +3746,6 @@
- , m_scale(1.0)
- , m_value(value) {}
-
--DOCTEST_DEFINE_COPIES(Approx);
--
- Approx Approx::operator()(double value) const {
- Approx approx(value);
- approx.epsilon(m_epsilon);
-@@ -3386,7 +3780,8 @@
- bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
-
- String toString(const Approx& in) {
-- return String("Approx( ") + doctest::toString(in.m_value) + " )";
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-+ return "Approx( " + doctest::toString(in.m_value) + " )";
- }
- const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
-
-@@ -3399,17 +3794,15 @@
- void Context::applyCommandLine(int, const char* const*) {}
- void Context::addFilter(const char*, const char*) {}
- void Context::clearFilters() {}
-+void Context::setOption(const char*, bool) {}
- void Context::setOption(const char*, int) {}
- void Context::setOption(const char*, const char*) {}
- bool Context::shouldExit() { return false; }
- void Context::setAsDefaultForAssertsOutOfTestCases() {}
- void Context::setAssertHandler(detail::assert_handler) {}
-+void Context::setCout(std::ostream* out) {}
- int Context::run() { return 0; }
-
--DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats);
--
--DOCTEST_DEFINE_DEFAULTS(TestRunStats);
--
- IReporter::~IReporter() = default;
-
- int IReporter::get_num_active_contexts() { return 0; }
-@@ -3435,7 +3828,7 @@
- namespace doctest_detail_test_suite_ns {
- // holds the current test suite
- doctest::detail::TestSuite& getCurrentTestSuite() {
-- static doctest::detail::TestSuite data;
-+ static doctest::detail::TestSuite data{};
- return data;
- }
- } // namespace doctest_detail_test_suite_ns
-@@ -3460,8 +3853,6 @@
- for(auto& curr_rep : g_cs->reporters_currently_used) \
- curr_rep->function(__VA_ARGS__)
-
-- DOCTEST_DEFINE_DEFAULTS(TestFailureException);
-- DOCTEST_DEFINE_COPIES(TestFailureException);
- bool checkIfShouldThrow(assertType::Enum at) {
- if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
- return true;
-@@ -3476,7 +3867,10 @@
- }
-
- #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- [[noreturn]] void throwException() { throw TestFailureException(); } // NOLINT(cert-err60-cpp)
-+ DOCTEST_NORETURN void throwException() {
-+ g_cs->shouldLogCurrentException = false;
-+ throw TestFailureException();
-+ } // NOLINT(cert-err60-cpp)
- #else // DOCTEST_CONFIG_NO_EXCEPTIONS
- void throwException() {}
- #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-@@ -3487,8 +3881,8 @@
- // matching of a string against a wildcard mask (case sensitivity configurable) taken from
- // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
- int wildcmp(const char* str, const char* wild, bool caseSensitive) {
-- const char* cp = nullptr;
-- const char* mp = nullptr;
-+ const char* cp = str;
-+ const char* mp = wild;
-
- while((*str) && (*wild != '*')) {
- if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
-@@ -3544,73 +3938,82 @@
- } // namespace
- namespace detail {
-
-- Subcase::Subcase(const char* name, const char* file, int line)
-- : m_signature(name, file, line) {
-- ContextState* s = g_cs;
--
-- // if we have already completed it
-- if(s->subcasesPassed.count(m_signature) != 0)
-- return;
-+ Subcase::Subcase(const String& name, const char* file, int line)
-+ : m_signature({name, file, line}) {
-+ auto* s = g_cs;
-
- // check subcase filters
-- if(s->subcasesCurrentLevel < s->subcase_filter_levels) {
-- if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive))
-+ if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) {
-+ if(!matchesAny(m_signature.m_name.c_str(), s->filters[6], true, s->case_sensitive))
- return;
-- if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive))
-+ if(matchesAny(m_signature.m_name.c_str(), s->filters[7], false, s->case_sensitive))
- return;
- }
--
-+
- // if a Subcase on the same level has already been entered
-- if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
-+ if(s->subcasesStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
- s->should_reenter = true;
- return;
- }
-
-- s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
-+ // push the current signature to the stack so we can check if the
-+ // current stack + the current new subcase have been traversed
-+ s->subcasesStack.push_back(m_signature);
-+ if(s->subcasesPassed.count(s->subcasesStack) != 0) {
-+ // pop - revert to previous stack since we've already passed this
-+ s->subcasesStack.pop_back();
-+ return;
-+ }
-+
-+ s->subcasesCurrentMaxLevel = s->subcasesStack.size();
- m_entered = true;
-
- DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
- }
-
-+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
-+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
-+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
-+
- Subcase::~Subcase() {
- if(m_entered) {
-- ContextState* s = g_cs;
--
-- s->subcasesCurrentLevel--;
-- // only mark the subcase as passed if no subcases have been skipped
-- if(s->should_reenter == false)
-- s->subcasesPassed.insert(m_signature);
-+ // only mark the subcase stack as passed if no subcases have been skipped
-+ if(g_cs->should_reenter == false)
-+ g_cs->subcasesPassed.insert(g_cs->subcasesStack);
-+ g_cs->subcasesStack.pop_back();
-
-+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
-+ if(std::uncaught_exceptions() > 0
-+#else
-+ if(std::uncaught_exception()
-+#endif
-+ && g_cs->shouldLogCurrentException) {
-+ DOCTEST_ITERATE_THROUGH_REPORTERS(
-+ test_case_exception, {"exception thrown in subcase - will translate later "
-+ "when the whole test case has been exited (cannot "
-+ "translate while there is an active exception)",
-+ false});
-+ g_cs->shouldLogCurrentException = false;
-+ }
- DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
- }
- }
-
-+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
-+ DOCTEST_GCC_SUPPRESS_WARNING_POP
-+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
-+
- Subcase::operator bool() const { return m_entered; }
-
- Result::Result(bool passed, const String& decomposition)
- : m_passed(passed)
- , m_decomp(decomposition) {}
-
-- DOCTEST_DEFINE_DEFAULTS(Result);
-- DOCTEST_DEFINE_COPIES(Result);
--
- ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
- : m_at(at) {}
-
-- DOCTEST_DEFINE_DEFAULTS(ExpressionDecomposer);
--
-- DOCTEST_DEFINE_DEFAULTS(TestSuite);
-- DOCTEST_DEFINE_COPIES(TestSuite);
--
- TestSuite& TestSuite::operator*(const char* in) {
- m_test_suite = in;
-- // clear state
-- m_description = nullptr;
-- m_skip = false;
-- m_may_fail = false;
-- m_should_fail = false;
-- m_expected_failures = 0;
-- m_timeout = 0;
- return *this;
- }
-
-@@ -3622,6 +4025,8 @@
- m_test_suite = test_suite.m_test_suite;
- m_description = test_suite.m_description;
- m_skip = test_suite.m_skip;
-+ m_no_breaks = test_suite.m_no_breaks;
-+ m_no_output = test_suite.m_no_output;
- m_may_fail = test_suite.m_may_fail;
- m_should_fail = test_suite.m_should_fail;
- m_expected_failures = test_suite.m_expected_failures;
-@@ -3632,8 +4037,6 @@
- m_template_id = template_id;
- }
-
-- DOCTEST_DEFINE_DEFAULTS(TestCase);
--
- TestCase::TestCase(const TestCase& other)
- : TestCaseData() {
- *this = other;
-@@ -3667,25 +4070,31 @@
- }
-
- bool TestCase::operator<(const TestCase& other) const {
-+ // this will be used only to differentiate between test cases - not relevant for sorting
- if(m_line != other.m_line)
- return m_line < other.m_line;
-- const int file_cmp = std::strcmp(m_file, other.m_file);
-+ const int name_cmp = strcmp(m_name, other.m_name);
-+ if(name_cmp != 0)
-+ return name_cmp < 0;
-+ const int file_cmp = m_file.compare(other.m_file);
- if(file_cmp != 0)
- return file_cmp < 0;
- return m_template_id < other.m_template_id;
- }
-+
-+ // all the registered tests
-+ std::set<TestCase>& getRegisteredTests() {
-+ static std::set<TestCase> data;
-+ return data;
-+ }
- } // namespace detail
- namespace {
- using namespace detail;
- // for sorting tests by file/line
- bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) {
--#if DOCTEST_MSVC
- // this is needed because MSVC gives different case for drive letters
- // for __FILE__ when evaluated in a header and a source file
-- const int res = stricmp(lhs->m_file, rhs->m_file);
--#else // MSVC
-- const int res = std::strcmp(lhs->m_file, rhs->m_file);
--#endif // MSVC
-+ const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC));
- if(res != 0)
- return res < 0;
- if(lhs->m_line != rhs->m_line)
-@@ -3709,39 +4118,10 @@
- return suiteOrderComparator(lhs, rhs);
- }
-
-- // all the registered tests
-- std::set<TestCase>& getRegisteredTests() {
-- static std::set<TestCase> data;
-- return data;
-- }
--
--#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
-- HANDLE g_stdoutHandle;
-- WORD g_origFgAttrs;
-- WORD g_origBgAttrs;
-- bool g_attrsInitted = false;
--
-- int colors_init() {
-- if(!g_attrsInitted) {
-- g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
-- g_attrsInitted = true;
-- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
-- GetConsoleScreenBufferInfo(g_stdoutHandle, &csbiInfo);
-- g_origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
-- BACKGROUND_BLUE | BACKGROUND_INTENSITY);
-- g_origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
-- FOREGROUND_BLUE | FOREGROUND_INTENSITY);
-- }
-- return 0;
-- }
--
-- int dumy_init_console_colors = colors_init();
--#endif // DOCTEST_CONFIG_COLORS_WINDOWS
--
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
- void color_to_stream(std::ostream& s, Color::Enum code) {
-- ((void)s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
-- ((void)code); // for DOCTEST_CONFIG_COLORS_NONE
-+ static_cast<void>(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
-+ static_cast<void>(code); // for DOCTEST_CONFIG_COLORS_NONE
- #ifdef DOCTEST_CONFIG_COLORS_ANSI
- if(g_no_colors ||
- (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false))
-@@ -3771,10 +4151,26 @@
-
- #ifdef DOCTEST_CONFIG_COLORS_WINDOWS
- if(g_no_colors ||
-- (isatty(fileno(stdout)) == false && getContextOptions()->force_colors == false))
-+ (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false))
- return;
-
--#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(g_stdoutHandle, x | g_origBgAttrs)
-+ static struct ConsoleHelper {
-+ HANDLE stdoutHandle;
-+ WORD origFgAttrs;
-+ WORD origBgAttrs;
-+
-+ ConsoleHelper() {
-+ stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
-+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
-+ GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
-+ origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
-+ BACKGROUND_BLUE | BACKGROUND_INTENSITY);
-+ origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
-+ FOREGROUND_BLUE | FOREGROUND_INTENSITY);
-+ }
-+ } ch;
-+
-+#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs)
-
- // clang-format off
- switch (code) {
-@@ -3791,7 +4187,7 @@
- case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
- case Color::None:
- case Color::Bright: // invalid
-- default: DOCTEST_SET_ATTR(g_origFgAttrs);
-+ default: DOCTEST_SET_ATTR(ch.origFgAttrs);
- }
- // clang-format on
- #endif // DOCTEST_CONFIG_COLORS_WINDOWS
-@@ -3844,9 +4240,33 @@
- return 0;
- }
-
--#ifdef DOCTEST_PLATFORM_MAC
-+#ifdef DOCTEST_IS_DEBUGGER_ACTIVE
-+ bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
-+#else // DOCTEST_IS_DEBUGGER_ACTIVE
-+#ifdef DOCTEST_PLATFORM_LINUX
-+ class ErrnoGuard {
-+ public:
-+ ErrnoGuard() : m_oldErrno(errno) {}
-+ ~ErrnoGuard() { errno = m_oldErrno; }
-+ private:
-+ int m_oldErrno;
-+ };
-+ // See the comments in Catch2 for the reasoning behind this implementation:
-+ // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102
-+ bool isDebuggerActive() {
-+ ErrnoGuard guard;
-+ std::ifstream in("/proc/self/status");
-+ for(std::string line; std::getline(in, line);) {
-+ static const int PREFIX_LEN = 11;
-+ if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
-+ return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
-+ }
-+ }
-+ return false;
-+ }
-+#elif defined(DOCTEST_PLATFORM_MAC)
- // The following function is taken directly from the following technical note:
-- // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
-+ // https://developer.apple.com/library/archive/qa/qa1361/_index.html
- // Returns true if the current process is being debugged (either
- // running under the debugger or has a debugger attached post facto).
- bool isDebuggerActive() {
-@@ -3871,11 +4291,12 @@
- // We're being debugged if the P_TRACED flag is set.
- return ((info.kp_proc.p_flag & P_TRACED) != 0);
- }
--#elif DOCTEST_MSVC || defined(__MINGW32__)
-+#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__)
- bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
- #else
- bool isDebuggerActive() { return false; }
- #endif // Platform
-+#endif // DOCTEST_IS_DEBUGGER_ACTIVE
-
- void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
- if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
-@@ -3910,41 +4331,47 @@
- g_infoContexts.push_back(this);
- }
-
-+ ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) {
-+ if (other.need_to_destroy) {
-+ other.destroy();
-+ }
-+ other.need_to_destroy = false;
-+ g_infoContexts.push_back(this);
-+ }
-+
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
- DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
-+
- // destroy cannot be inlined into the destructor because that would mean calling stringify after
- // ContextScope has been destroyed (base class destructors run after derived class destructors).
- // Instead, ContextScope calls this method directly from its destructor.
- void ContextScopeBase::destroy() {
-+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
-+ if(std::uncaught_exceptions() > 0) {
-+#else
- if(std::uncaught_exception()) {
-+#endif
- std::ostringstream s;
- this->stringify(&s);
- g_cs->stringifiedContexts.push_back(s.str().c_str());
- }
- g_infoContexts.pop_back();
- }
-+
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
- DOCTEST_MSVC_SUPPRESS_WARNING_POP
--
- } // namespace detail
- namespace {
- using namespace detail;
-
-- std::ostream& file_line_to_stream(std::ostream& s, const char* file, int line,
-- const char* tail = "") {
-- const auto opt = getContextOptions();
-- s << Color::LightGrey << skipPathFromFilename(file) << (opt->gnu_file_line ? ":" : "(")
-- << (opt->no_line_numbers ? 0 : line) // 0 or the real num depending on the option
-- << (opt->gnu_file_line ? ":" : "):") << tail;
-- return s;
-- }
--
- #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
- struct FatalConditionHandler
- {
-- void reset() {}
-+ static void reset() {}
-+ static void allocateAltStackMem() {}
-+ static void freeAltStackMem() {}
- };
- #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
-
-@@ -3961,43 +4388,113 @@
- // Windows can easily distinguish between SO and SigSegV,
- // but SigInt, SigTerm, etc are handled differently.
- SignalDefs signalDefs[] = {
-- {EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal"},
-- {EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow"},
-- {EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal"},
-- {EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error"},
-+ {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),
-+ "SIGILL - Illegal instruction signal"},
-+ {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
-+ {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION),
-+ "SIGSEGV - Segmentation violation signal"},
-+ {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
- };
-
- struct FatalConditionHandler
- {
-- static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
-- for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
-- if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
-- reportFatal(signalDefs[i].name);
-+ static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
-+ // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
-+ // console just once no matter how many threads have crashed.
-+ static std::mutex mutex;
-+ static bool execute = true;
-+ {
-+ std::lock_guard<std::mutex> lock(mutex);
-+ if(execute) {
-+ bool reported = false;
-+ for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
-+ if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
-+ reportFatal(signalDefs[i].name);
-+ reported = true;
-+ break;
-+ }
-+ }
-+ if(reported == false)
-+ reportFatal("Unhandled SEH exception caught");
-+ if(isDebuggerActive() && !g_cs->no_breaks)
-+ DOCTEST_BREAK_INTO_DEBUGGER();
- }
-+ execute = false;
- }
-- // If its not an exception we care about, pass it along.
-- // This stops us from eating debugger breaks etc.
-- return EXCEPTION_CONTINUE_SEARCH;
-+ std::exit(EXIT_FAILURE);
- }
-
-+ static void allocateAltStackMem() {}
-+ static void freeAltStackMem() {}
-+
- FatalConditionHandler() {
- isSet = true;
- // 32k seems enough for doctest to handle stack overflow,
- // but the value was found experimentally, so there is no strong guarantee
- guaranteeSize = 32 * 1024;
-- exceptionHandlerHandle = nullptr;
-- // Register as first handler in current chain
-- exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
-+ // Register an unhandled exception filter
-+ previousTop = SetUnhandledExceptionFilter(handleException);
- // Pass in guarantee size to be filled
- SetThreadStackGuarantee(&guaranteeSize);
-+
-+ // On Windows uncaught exceptions from another thread, exceptions from
-+ // destructors, or calls to std::terminate are not a SEH exception
-+
-+ // The terminal handler gets called when:
-+ // - std::terminate is called FROM THE TEST RUNNER THREAD
-+ // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
-+ original_terminate_handler = std::get_terminate();
-+ std::set_terminate([]() DOCTEST_NOEXCEPT {
-+ reportFatal("Terminate handler called");
-+ if(isDebuggerActive() && !g_cs->no_breaks)
-+ DOCTEST_BREAK_INTO_DEBUGGER();
-+ std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well
-+ });
-+
-+ // SIGABRT is raised when:
-+ // - std::terminate is called FROM A DIFFERENT THREAD
-+ // - an exception is thrown from a destructor FROM A DIFFERENT THREAD
-+ // - an uncaught exception is thrown FROM A DIFFERENT THREAD
-+ prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
-+ if(signal == SIGABRT) {
-+ reportFatal("SIGABRT - Abort (abnormal termination) signal");
-+ if(isDebuggerActive() && !g_cs->no_breaks)
-+ DOCTEST_BREAK_INTO_DEBUGGER();
-+ std::exit(EXIT_FAILURE);
-+ }
-+ });
-+
-+ // The following settings are taken from google test, and more
-+ // specifically from UnitTest::Run() inside of gtest.cc
-+
-+ // the user does not want to see pop-up dialogs about crashes
-+ prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
-+ SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
-+ // This forces the abort message to go to stderr in all circumstances.
-+ prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR);
-+ // In the debug version, Visual Studio pops up a separate dialog
-+ // offering a choice to debug the aborted program - we want to disable that.
-+ prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
-+ // In debug mode, the Windows CRT can crash with an assertion over invalid
-+ // input (e.g. passing an invalid file descriptor). The default handling
-+ // for these assertions is to pop up a dialog and wait for user input.
-+ // Instead ask the CRT to dump such assertions to stderr non-interactively.
-+ prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
-+ prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- }
-
- static void reset() {
- if(isSet) {
- // Unregister handler and restore the old guarantee
-- RemoveVectoredExceptionHandler(exceptionHandlerHandle);
-+ SetUnhandledExceptionFilter(previousTop);
- SetThreadStackGuarantee(&guaranteeSize);
-- exceptionHandlerHandle = nullptr;
-+ std::set_terminate(original_terminate_handler);
-+ std::signal(SIGABRT, prev_sigabrt_handler);
-+ SetErrorMode(prev_error_mode_1);
-+ _set_error_mode(prev_error_mode_2);
-+ _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
-+ static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
-+ static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
- isSet = false;
- }
- }
-@@ -4005,14 +4502,28 @@
- ~FatalConditionHandler() { reset(); }
-
- private:
-+ static UINT prev_error_mode_1;
-+ static int prev_error_mode_2;
-+ static unsigned int prev_abort_behavior;
-+ static int prev_report_mode;
-+ static _HFILE prev_report_file;
-+ static void (DOCTEST_CDECL *prev_sigabrt_handler)(int);
-+ static std::terminate_handler original_terminate_handler;
- static bool isSet;
- static ULONG guaranteeSize;
-- static PVOID exceptionHandlerHandle;
-+ static LPTOP_LEVEL_EXCEPTION_FILTER previousTop;
- };
-
-+ UINT FatalConditionHandler::prev_error_mode_1;
-+ int FatalConditionHandler::prev_error_mode_2;
-+ unsigned int FatalConditionHandler::prev_abort_behavior;
-+ int FatalConditionHandler::prev_report_mode;
-+ _HFILE FatalConditionHandler::prev_report_file;
-+ void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int);
-+ std::terminate_handler FatalConditionHandler::original_terminate_handler;
- bool FatalConditionHandler::isSet = false;
- ULONG FatalConditionHandler::guaranteeSize = 0;
-- PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
-+ LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr;
-
- #else // DOCTEST_PLATFORM_WINDOWS
-
-@@ -4033,7 +4544,8 @@
- static bool isSet;
- static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
- static stack_t oldSigStack;
-- static char altStackMem[4 * SIGSTKSZ];
-+ static size_t altStackSize;
-+ static char* altStackMem;
-
- static void handleSignal(int sig) {
- const char* name = "<unknown signal>";
-@@ -4049,11 +4561,19 @@
- raise(sig);
- }
-
-+ static void allocateAltStackMem() {
-+ altStackMem = new char[altStackSize];
-+ }
-+
-+ static void freeAltStackMem() {
-+ delete[] altStackMem;
-+ }
-+
- FatalConditionHandler() {
- isSet = true;
- stack_t sigStack;
- sigStack.ss_sp = altStackMem;
-- sigStack.ss_size = sizeof(altStackMem);
-+ sigStack.ss_size = altStackSize;
- sigStack.ss_flags = 0;
- sigaltstack(&sigStack, &oldSigStack);
- struct sigaction sa = {};
-@@ -4078,10 +4598,11 @@
- }
- };
-
-- bool FatalConditionHandler::isSet = false;
-+ bool FatalConditionHandler::isSet = false;
- struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
-- stack_t FatalConditionHandler::oldSigStack = {};
-- char FatalConditionHandler::altStackMem[] = {};
-+ stack_t FatalConditionHandler::oldSigStack = {};
-+ size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
-+ char* FatalConditionHandler::altStackMem = nullptr;
-
- #endif // DOCTEST_PLATFORM_WINDOWS
- #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
-@@ -4114,8 +4635,10 @@
-
- DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
-
-- while(g_cs->subcasesCurrentLevel--)
-+ while(g_cs->subcasesStack.size()) {
-+ g_cs->subcasesStack.pop_back();
- DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
-+ }
-
- g_cs->finalizeTestCaseData();
-
-@@ -4128,24 +4651,23 @@
- namespace detail {
-
- ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
-- const char* exception_type) {
-- m_test_case = g_cs->currentTest;
-- m_at = at;
-- m_file = file;
-- m_line = line;
-- m_expr = expr;
-- m_failed = true;
-- m_threw = false;
-- m_threw_as = false;
-- m_exception_type = exception_type;
-+ const char* exception_type, const char* exception_string) {
-+ m_test_case = g_cs->currentTest;
-+ m_at = at;
-+ m_file = file;
-+ m_line = line;
-+ m_expr = expr;
-+ m_failed = true;
-+ m_threw = false;
-+ m_threw_as = false;
-+ m_exception_type = exception_type;
-+ m_exception_string = exception_string;
- #if DOCTEST_MSVC
- if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
- ++m_expr;
- #endif // MSVC
- }
-
-- DOCTEST_DEFINE_DEFAULTS(ResultBuilder);
--
- void ResultBuilder::setResult(const Result& res) {
- m_decomp = res.m_decomp;
- m_failed = !res.m_passed;
-@@ -4159,16 +4681,18 @@
- bool ResultBuilder::log() {
- if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
- m_failed = !m_threw;
-+ } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
-+ m_failed = !m_threw_as || (m_exception != m_exception_string);
- } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
- m_failed = !m_threw_as;
- } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
-- m_failed = m_exception != m_exception_type;
-+ m_failed = m_exception != m_exception_string;
- } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
- m_failed = m_threw;
- }
-
- if(m_exception.size())
-- m_exception = String("\"") + m_exception + "\"";
-+ m_exception = "\"" + m_exception + "\"";
-
- if(is_running_in_test) {
- addAssert(m_at);
-@@ -4180,8 +4704,8 @@
- failed_out_of_a_testing_context(*this);
- }
-
-- return m_failed && isDebuggerActive() &&
-- !getContextOptions()->no_breaks; // break into debugger
-+ return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
-+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
- }
-
- void ResultBuilder::react() const {
-@@ -4196,7 +4720,7 @@
- std::abort();
- }
-
-- void decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
-+ bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
- Result result) {
- bool failed = !result.m_passed;
-
-@@ -4206,58 +4730,53 @@
- // ###################################################################################
- DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
- DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-+ return !failed;
- }
-
- MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
-- m_stream = getTlsOss();
-+ m_stream = tlssPush();
- m_file = file;
- m_line = line;
- m_severity = severity;
- }
-
-+ MessageBuilder::~MessageBuilder() {
-+ if (!logged)
-+ tlssPop();
-+ }
-+
- IExceptionTranslator::IExceptionTranslator() = default;
- IExceptionTranslator::~IExceptionTranslator() = default;
-
- bool MessageBuilder::log() {
-- m_string = getTlsOssResult();
-+ if (!logged) {
-+ m_string = tlssPop();
-+ logged = true;
-+ }
-+
- DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
-
- const bool isWarn = m_severity & assertType::is_warn;
-
-- // warn is just a message in this context so we dont treat it as an assert
-+ // warn is just a message in this context so we don't treat it as an assert
- if(!isWarn) {
- addAssert(m_severity);
- addFailedAssert(m_severity);
- }
-
-- return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn; // break
-+ return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
-+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
- }
-
- void MessageBuilder::react() {
- if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
- throwException();
- }
--
-- MessageBuilder::~MessageBuilder() = default;
- } // namespace detail
- namespace {
- using namespace detail;
-
-- template <typename Ex>
-- [[noreturn]] void throw_exception(Ex const& e) {
--#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- throw e;
--#else // DOCTEST_CONFIG_NO_EXCEPTIONS
-- std::cerr << "doctest will terminate because it needed to throw an exception.\n"
-- << "The message was: " << e.what() << '\n';
-- std::terminate();
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-- }
--
--#define DOCTEST_INTERNAL_ERROR(msg) \
-- throw_exception(std::logic_error( \
-- __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
--
- // clang-format off
-
- // =================================================================================================
-@@ -4287,8 +4806,8 @@
- public:
- ScopedElement( XmlWriter* writer );
-
-- ScopedElement( ScopedElement&& other ) noexcept;
-- ScopedElement& operator=( ScopedElement&& other ) noexcept;
-+ ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT;
-+ ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT;
-
- ~ScopedElement();
-
-@@ -4404,7 +4923,7 @@
-
- void XmlEncode::encodeTo( std::ostream& os ) const {
- // Apostrophe escaping not necessary if we always use " to write attributes
-- // (see: http://www.w3.org/TR/xml/#syntax)
-+ // (see: https://www.w3.org/TR/xml/#syntax)
-
- for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
- uchar c = m_str[idx];
-@@ -4413,7 +4932,7 @@
- case '&': os << "&amp;"; break;
-
- case '>':
-- // See: http://www.w3.org/TR/xml/#syntax
-+ // See: https://www.w3.org/TR/xml/#syntax
- if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
- os << "&gt;";
- else
-@@ -4431,7 +4950,7 @@
- // Check for control characters and invalid utf-8
-
- // Escape control characters in standard ascii
-- // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
-+ // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
- if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
- hexEscapeChar(os, c);
- break;
-@@ -4505,11 +5024,11 @@
- : m_writer( writer )
- {}
-
-- XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
-+ XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT
- : m_writer( other.m_writer ){
- other.m_writer = nullptr;
- }
-- XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
-+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT {
- if ( m_writer ) {
- m_writer->endElement();
- }
-@@ -4671,7 +5190,7 @@
- void test_case_start_impl(const TestCaseData& in) {
- bool open_ts_tag = false;
- if(tc != nullptr) { // we have already opened a test suite
-- if(strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
-+ if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
- xml.endElement();
- open_ts_tag = true;
- }
-@@ -4688,7 +5207,7 @@
- tc = &in;
- xml.startElement("TestCase")
- .writeAttribute("name", in.m_name)
-- .writeAttribute("filename", skipPathFromFilename(in.m_file))
-+ .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str()))
- .writeAttribute("line", line(in.m_line))
- .writeAttribute("description", in.m_description);
-
-@@ -4716,13 +5235,18 @@
- .writeAttribute("priority", curr.first.first)
- .writeAttribute("name", curr.first.second);
- } else if(opt.count || opt.list_test_cases) {
-- for(unsigned i = 0; i < in.num_data; ++i)
-- xml.scopedElement("TestCase").writeAttribute("name", in.data[i]);
-+ for(unsigned i = 0; i < in.num_data; ++i) {
-+ xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
-+ .writeAttribute("testsuite", in.data[i]->m_test_suite)
-+ .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
-+ .writeAttribute("line", line(in.data[i]->m_line))
-+ .writeAttribute("skipped", in.data[i]->m_skip);
-+ }
- xml.scopedElement("OverallResultsTestCases")
- .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
- } else if(opt.list_test_suites) {
- for(unsigned i = 0; i < in.num_data; ++i)
-- xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]);
-+ xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite);
- xml.scopedElement("OverallResultsTestCases")
- .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
- xml.scopedElement("OverallResultsTestSuites")
-@@ -4779,12 +5303,15 @@
- test_case_start_impl(in);
- xml.ensureTagClosed();
- }
-+
-+ void test_case_reenter(const TestCaseData&) override {}
-
- void test_case_end(const CurrentTestCaseStats& st) override {
- xml.startElement("OverallResultsAsserts")
- .writeAttribute("successes",
- st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
-- .writeAttribute("failures", st.numAssertsFailedCurrentTest);
-+ .writeAttribute("failures", st.numAssertsFailedCurrentTest)
-+ .writeAttribute("test_case_success", st.testCaseSuccess);
- if(opt.duration)
- xml.writeAttribute("duration", st.seconds);
- if(tc->m_expected_failures)
-@@ -4803,8 +5330,6 @@
- }
-
- void subcase_start(const SubcaseSignature& in) override {
-- std::lock_guard<std::mutex> lock(mutex);
--
- xml.startElement("SubCase")
- .writeAttribute("name", in.m_name)
- .writeAttribute("filename", skipPathFromFilename(in.m_file))
-@@ -4831,11 +5356,12 @@
- if(rb.m_threw)
- xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
-
-- if(rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) {
-+ if(rb.m_at & assertType::is_throws_as)
- xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
-- } else if((rb.m_at & assertType::is_normal) && !rb.m_threw) {
-+ if(rb.m_at & assertType::is_throws_with)
-+ xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string);
-+ if((rb.m_at & assertType::is_normal) && !rb.m_threw)
- xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
-- }
-
- log_contexts();
-
-@@ -4868,6 +5394,278 @@
-
- DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter);
-
-+ void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) {
-+ if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
-+ 0) //!OCLINT bitwise operator in conditional
-+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
-+ << Color::None;
-+
-+ if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
-+ s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
-+ } else if((rb.m_at & assertType::is_throws_as) &&
-+ (rb.m_at & assertType::is_throws_with)) { //!OCLINT
-+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
-+ << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None;
-+ if(rb.m_threw) {
-+ if(!rb.m_failed) {
-+ s << "threw as expected!\n";
-+ } else {
-+ s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
-+ }
-+ } else {
-+ s << "did NOT throw at all!\n";
-+ }
-+ } else if(rb.m_at &
-+ assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
-+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
-+ << rb.m_exception_type << " ) " << Color::None
-+ << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
-+ "threw a DIFFERENT exception: ") :
-+ "did NOT throw at all!")
-+ << Color::Cyan << rb.m_exception << "\n";
-+ } else if(rb.m_at &
-+ assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
-+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
-+ << rb.m_exception_string << "\" ) " << Color::None
-+ << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
-+ "threw a DIFFERENT exception: ") :
-+ "did NOT throw at all!")
-+ << Color::Cyan << rb.m_exception << "\n";
-+ } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
-+ s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
-+ << rb.m_exception << "\n";
-+ } else {
-+ s << (rb.m_threw ? "THREW exception: " :
-+ (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
-+ if(rb.m_threw)
-+ s << rb.m_exception << "\n";
-+ else
-+ s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
-+ }
-+ }
-+
-+ // TODO:
-+ // - log_message()
-+ // - respond to queries
-+ // - honor remaining options
-+ // - more attributes in tags
-+ struct JUnitReporter : public IReporter
-+ {
-+ XmlWriter xml;
-+ std::mutex mutex;
-+ Timer timer;
-+ std::vector<String> deepestSubcaseStackNames;
-+
-+ struct JUnitTestCaseData
-+ {
-+ static std::string getCurrentTimestamp() {
-+ // Beware, this is not reentrant because of backward compatibility issues
-+ // Also, UTC only, again because of backward compatibility (%z is C++11)
-+ time_t rawtime;
-+ std::time(&rawtime);
-+ auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
-+
-+ std::tm timeInfo;
-+#ifdef DOCTEST_PLATFORM_WINDOWS
-+ gmtime_s(&timeInfo, &rawtime);
-+#else // DOCTEST_PLATFORM_WINDOWS
-+ gmtime_r(&rawtime, &timeInfo);
-+#endif // DOCTEST_PLATFORM_WINDOWS
-+
-+ char timeStamp[timeStampSize];
-+ const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
-+
-+ std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
-+ return std::string(timeStamp);
-+ }
-+
-+ struct JUnitTestMessage
-+ {
-+ JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details)
-+ : message(_message), type(_type), details(_details) {}
-+
-+ JUnitTestMessage(const std::string& _message, const std::string& _details)
-+ : message(_message), type(), details(_details) {}
-+
-+ std::string message, type, details;
-+ };
-+
-+ struct JUnitTestCase
-+ {
-+ JUnitTestCase(const std::string& _classname, const std::string& _name)
-+ : classname(_classname), name(_name), time(0), failures() {}
-+
-+ std::string classname, name;
-+ double time;
-+ std::vector<JUnitTestMessage> failures, errors;
-+ };
-+
-+ void add(const std::string& classname, const std::string& name) {
-+ testcases.emplace_back(classname, name);
-+ }
-+
-+ void appendSubcaseNamesToLastTestcase(std::vector<String> nameStack) {
-+ for(auto& curr: nameStack)
-+ if(curr.size())
-+ testcases.back().name += std::string("/") + curr.c_str();
-+ }
-+
-+ void addTime(double time) {
-+ if(time < 1e-4)
-+ time = 0;
-+ testcases.back().time = time;
-+ totalSeconds += time;
-+ }
-+
-+ void addFailure(const std::string& message, const std::string& type, const std::string& details) {
-+ testcases.back().failures.emplace_back(message, type, details);
-+ ++totalFailures;
-+ }
-+
-+ void addError(const std::string& message, const std::string& details) {
-+ testcases.back().errors.emplace_back(message, details);
-+ ++totalErrors;
-+ }
-+
-+ std::vector<JUnitTestCase> testcases;
-+ double totalSeconds = 0;
-+ int totalErrors = 0, totalFailures = 0;
-+ };
-+
-+ JUnitTestCaseData testCaseData;
-+
-+ // caching pointers/references to objects of these types - safe to do
-+ const ContextOptions& opt;
-+ const TestCaseData* tc = nullptr;
-+
-+ JUnitReporter(const ContextOptions& co)
-+ : xml(*co.cout)
-+ , opt(co) {}
-+
-+ unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
-+
-+ // =========================================================================================
-+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
-+ // =========================================================================================
-+
-+ void report_query(const QueryData&) override {}
-+
-+ void test_run_start() override {}
-+
-+ void test_run_end(const TestRunStats& p) override {
-+ // remove .exe extension - mainly to have the same output on UNIX and Windows
-+ std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
-+#ifdef DOCTEST_PLATFORM_WINDOWS
-+ if(binary_name.rfind(".exe") != std::string::npos)
-+ binary_name = binary_name.substr(0, binary_name.length() - 4);
-+#endif // DOCTEST_PLATFORM_WINDOWS
-+ xml.startElement("testsuites");
-+ xml.startElement("testsuite").writeAttribute("name", binary_name)
-+ .writeAttribute("errors", testCaseData.totalErrors)
-+ .writeAttribute("failures", testCaseData.totalFailures)
-+ .writeAttribute("tests", p.numAsserts);
-+ if(opt.no_time_in_output == false) {
-+ xml.writeAttribute("time", testCaseData.totalSeconds);
-+ xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp());
-+ }
-+ if(opt.no_version == false)
-+ xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR);
-+
-+ for(const auto& testCase : testCaseData.testcases) {
-+ xml.startElement("testcase")
-+ .writeAttribute("classname", testCase.classname)
-+ .writeAttribute("name", testCase.name);
-+ if(opt.no_time_in_output == false)
-+ xml.writeAttribute("time", testCase.time);
-+ // This is not ideal, but it should be enough to mimic gtest's junit output.
-+ xml.writeAttribute("status", "run");
-+
-+ for(const auto& failure : testCase.failures) {
-+ xml.scopedElement("failure")
-+ .writeAttribute("message", failure.message)
-+ .writeAttribute("type", failure.type)
-+ .writeText(failure.details, false);
-+ }
-+
-+ for(const auto& error : testCase.errors) {
-+ xml.scopedElement("error")
-+ .writeAttribute("message", error.message)
-+ .writeText(error.details);
-+ }
-+
-+ xml.endElement();
-+ }
-+ xml.endElement();
-+ xml.endElement();
-+ }
-+
-+ void test_case_start(const TestCaseData& in) override {
-+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
-+ timer.start();
-+ }
-+
-+ void test_case_reenter(const TestCaseData& in) override {
-+ testCaseData.addTime(timer.getElapsedSeconds());
-+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
-+ deepestSubcaseStackNames.clear();
-+
-+ timer.start();
-+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
-+ }
-+
-+ void test_case_end(const CurrentTestCaseStats&) override {
-+ testCaseData.addTime(timer.getElapsedSeconds());
-+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
-+ deepestSubcaseStackNames.clear();
-+ }
-+
-+ void test_case_exception(const TestCaseException& e) override {
-+ std::lock_guard<std::mutex> lock(mutex);
-+ testCaseData.addError("exception", e.error_string.c_str());
-+ }
-+
-+ void subcase_start(const SubcaseSignature& in) override {
-+ deepestSubcaseStackNames.push_back(in.m_name);
-+ }
-+
-+ void subcase_end() override {}
-+
-+ void log_assert(const AssertData& rb) override {
-+ if(!rb.m_failed) // report only failures & ignore the `success` option
-+ return;
-+
-+ std::lock_guard<std::mutex> lock(mutex);
-+
-+ std::ostringstream os;
-+ os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
-+ << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
-+
-+ fulltext_log_assert_to_stream(os, rb);
-+ log_contexts(os);
-+ testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
-+ }
-+
-+ void log_message(const MessageData&) override {}
-+
-+ void test_case_skipped(const TestCaseData&) override {}
-+
-+ void log_contexts(std::ostringstream& s) {
-+ int num_contexts = get_num_active_contexts();
-+ if(num_contexts) {
-+ auto contexts = get_active_contexts();
-+
-+ s << " logged: ";
-+ for(int i = 0; i < num_contexts; ++i) {
-+ s << (i == 0 ? "" : " ");
-+ contexts[i]->stringify(&s);
-+ s << std::endl;
-+ }
-+ }
-+ }
-+ };
-+
-+ DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter);
-+
- struct Whitespace
- {
- int nrSpaces;
-@@ -4886,6 +5684,7 @@
- std::ostream& s;
- bool hasLoggedCurrentTestStart;
- std::vector<SubcaseSignature> subcasesStack;
-+ size_t currentSubcaseLevel;
- std::mutex mutex;
-
- // caching pointers/references to objects of these types - safe to do
-@@ -4944,23 +5743,40 @@
- s << "\n";
- }
-
-+ // this was requested to be made virtual so users could override it
-+ virtual void file_line_to_stream(const char* file, int line,
-+ const char* tail = "") {
-+ s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(")
-+ << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option
-+ << (opt.gnu_file_line ? ":" : "):") << tail;
-+ }
-+
- void logTestStart() {
- if(hasLoggedCurrentTestStart)
- return;
-
- separator_to_stream();
-- file_line_to_stream(s, tc->m_file, tc->m_line, "\n");
-+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n");
- if(tc->m_description)
- s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n";
- if(tc->m_test_suite && tc->m_test_suite[0] != '\0')
- s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n";
- if(strncmp(tc->m_name, " Scenario:", 11) != 0)
-- s << Color::None << "TEST CASE: ";
-+ s << Color::Yellow << "TEST CASE: ";
- s << Color::None << tc->m_name << "\n";
-
-- for(auto& curr : subcasesStack)
-- if(curr.m_name[0] != '\0')
-- s << " " << curr.m_name << "\n";
-+ for(size_t i = 0; i < currentSubcaseLevel; ++i) {
-+ if(subcasesStack[i].m_name[0] != '\0')
-+ s << " " << subcasesStack[i].m_name << "\n";
-+ }
-+
-+ if(currentSubcaseLevel != subcasesStack.size()) {
-+ s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None;
-+ for(size_t i = 0; i < subcasesStack.size(); ++i) {
-+ if(subcasesStack[i].m_name[0] != '\0')
-+ s << " " << subcasesStack[i].m_name << "\n";
-+ }
-+ }
-
- s << "\n";
-
-@@ -4974,9 +5790,11 @@
- }
-
- void printIntro() {
-- printVersion();
-- s << Color::Cyan << "[doctest] " << Color::None
-- << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
-+ if(opt.no_intro == false) {
-+ printVersion();
-+ s << Color::Cyan << "[doctest] " << Color::None
-+ << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
-+ }
- }
-
- void printHelp() {
-@@ -5038,7 +5856,7 @@
- << Whitespace(sizePrefixDisplay*1) << "output filename\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> "
- << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
-- s << Whitespace(sizePrefixDisplay*3) << " <string> - by [file/suite/name/rand]\n";
-+ s << Whitespace(sizePrefixDisplay*3) << " <string> - [file/suite/name/rand/none]\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> "
- << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> "
-@@ -5061,12 +5879,18 @@
- << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool> "
- << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
-+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal=<bool> "
-+ << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n";
-+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet=<bool> "
-+ << Whitespace(sizePrefixDisplay*1) << "no console output\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool> "
- << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool> "
- << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool> "
- << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
-+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro=<bool> "
-+ << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool> "
- << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
- s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool> "
-@@ -5104,22 +5928,6 @@
- printReporters(getReporters(), "reporters");
- }
-
-- void list_query_results() {
-- separator_to_stream();
-- if(opt.count || opt.list_test_cases) {
-- s << Color::Cyan << "[doctest] " << Color::None
-- << "unskipped test cases passing the current filters: "
-- << g_cs->numTestCasesPassingFilters << "\n";
-- } else if(opt.list_test_suites) {
-- s << Color::Cyan << "[doctest] " << Color::None
-- << "unskipped test cases passing the current filters: "
-- << g_cs->numTestCasesPassingFilters << "\n";
-- s << Color::Cyan << "[doctest] " << Color::None
-- << "test suites with unskipped test cases passing the current filters: "
-- << g_cs->numTestSuitesPassingFilters << "\n";
-- }
-- }
--
- // =========================================================================================
- // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
- // =========================================================================================
-@@ -5139,7 +5947,7 @@
- }
-
- for(unsigned i = 0; i < in.num_data; ++i)
-- s << Color::None << in.data[i] << "\n";
-+ s << Color::None << in.data[i]->m_name << "\n";
-
- separator_to_stream();
-
-@@ -5152,7 +5960,7 @@
- separator_to_stream();
-
- for(unsigned i = 0; i < in.num_data; ++i)
-- s << Color::None << in.data[i] << "\n";
-+ s << Color::None << in.data[i]->m_test_suite << "\n";
-
- separator_to_stream();
-
-@@ -5165,30 +5973,40 @@
- }
- }
-
-- void test_run_start() override { printIntro(); }
-+ void test_run_start() override {
-+ if(!opt.minimal)
-+ printIntro();
-+ }
-
- void test_run_end(const TestRunStats& p) override {
-+ if(opt.minimal && p.numTestCasesFailed == 0)
-+ return;
-+
- separator_to_stream();
-+ s << std::dec;
-
-+ auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
-+ auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
-+ auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
- const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
-- s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(6)
-+ s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
- << p.numTestCasesPassingFilters << " | "
- << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None :
- Color::Green)
-- << std::setw(6) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
-+ << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
- << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None)
-- << std::setw(6) << p.numTestCasesFailed << " failed" << Color::None << " | ";
-+ << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |";
- if(opt.no_skipped_summary == false) {
- const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
-- s << (numSkipped == 0 ? Color::None : Color::Yellow) << std::setw(6) << numSkipped
-+ s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped
- << " skipped" << Color::None;
- }
- s << "\n";
-- s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(6)
-+ s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth)
- << p.numAsserts << " | "
- << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
-- << std::setw(6) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
-- << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(6)
-+ << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
-+ << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
- << p.numAssertsFailed << " failed" << Color::None << " |\n";
- s << Color::Cyan << "[doctest] " << Color::None
- << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
-@@ -5198,9 +6016,18 @@
- void test_case_start(const TestCaseData& in) override {
- hasLoggedCurrentTestStart = false;
- tc = &in;
-+ subcasesStack.clear();
-+ currentSubcaseLevel = 0;
-+ }
-+
-+ void test_case_reenter(const TestCaseData&) override {
-+ subcasesStack.clear();
- }
-
- void test_case_end(const CurrentTestCaseStats& st) override {
-+ if(tc->m_no_output)
-+ return;
-+
- // log the preamble of the test case only if there is something
- // else to print - something other than that an assert has failed
- if(opt.duration ||
-@@ -5235,9 +6062,13 @@
- }
-
- void test_case_exception(const TestCaseException& e) override {
-+ std::lock_guard<std::mutex> lock(mutex);
-+ if(tc->m_no_output)
-+ return;
-+
- logTestStart();
-
-- file_line_to_stream(s, tc->m_file, tc->m_line, " ");
-+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
- successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require :
- assertType::is_check);
- s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ")
-@@ -5256,71 +6087,41 @@
- }
-
- void subcase_start(const SubcaseSignature& subc) override {
-- std::lock_guard<std::mutex> lock(mutex);
- subcasesStack.push_back(subc);
-+ ++currentSubcaseLevel;
- hasLoggedCurrentTestStart = false;
- }
-
- void subcase_end() override {
-- std::lock_guard<std::mutex> lock(mutex);
-- subcasesStack.pop_back();
-+ --currentSubcaseLevel;
- hasLoggedCurrentTestStart = false;
- }
-
- void log_assert(const AssertData& rb) override {
-- if(!rb.m_failed && !opt.success)
-+ if((!rb.m_failed && !opt.success) || tc->m_no_output)
- return;
-
- std::lock_guard<std::mutex> lock(mutex);
-
- logTestStart();
-
-- file_line_to_stream(s, rb.m_file, rb.m_line, " ");
-+ file_line_to_stream(rb.m_file, rb.m_line, " ");
- successOrFailColoredStringToStream(!rb.m_failed, rb.m_at);
-- if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
-- 0) //!OCLINT bitwise operator in conditional
-- s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
-- << Color::None;
--
-- if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
-- s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
-- } else if(rb.m_at &
-- assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
-- s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
-- << rb.m_exception_type << " ) " << Color::None
-- << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
-- "threw a DIFFERENT exception: ") :
-- "did NOT throw at all!")
-- << Color::Cyan << rb.m_exception << "\n";
-- } else if(rb.m_at &
-- assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
-- s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
-- << rb.m_exception_type << "\" ) " << Color::None
-- << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
-- "threw a DIFFERENT exception: ") :
-- "did NOT throw at all!")
-- << Color::Cyan << rb.m_exception << "\n";
-- } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
-- s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
-- << rb.m_exception << "\n";
-- } else {
-- s << (rb.m_threw ? "THREW exception: " :
-- (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
-- if(rb.m_threw)
-- s << rb.m_exception << "\n";
-- else
-- s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
-- }
-+
-+ fulltext_log_assert_to_stream(s, rb);
-
- log_contexts();
- }
-
- void log_message(const MessageData& mb) override {
-+ if(tc->m_no_output)
-+ return;
-+
- std::lock_guard<std::mutex> lock(mutex);
-
- logTestStart();
-
-- file_line_to_stream(s, mb.m_file, mb.m_line, " ");
-+ file_line_to_stream(mb.m_file, mb.m_line, " ");
- s << getSuccessOrFailColor(false, mb.m_severity)
- << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity,
- "MESSAGE") << ": ";
-@@ -5346,14 +6147,17 @@
- bool with_col = g_no_colors; \
- g_no_colors = false; \
- ConsoleReporter::func(arg); \
-- DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
-- oss.str(""); \
-+ if(oss.tellp() != std::streampos{}) { \
-+ DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
-+ oss.str(""); \
-+ } \
- g_no_colors = with_col; \
- }
-
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
-+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
- DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
-@@ -5368,7 +6172,7 @@
-
- // the implementation of parseOption()
- bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
-- // going from the end to the begining and stopping on the first occurance from the end
-+ // going from the end to the beginning and stopping on the first occurrence from the end
- for(int i = argc; i > 0; --i) {
- auto index = i - 1;
- auto temp = std::strstr(argv[index], pattern);
-@@ -5424,18 +6228,42 @@
- std::vector<String>& res) {
- String filtersString;
- if(parseOption(argc, argv, pattern, &filtersString)) {
-- // tokenize with "," as a separator
-- // cppcheck-suppress strtokCalled
-- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
-- auto pch = std::strtok(filtersString.c_str(), ","); // modifies the string
-- while(pch != nullptr) {
-- if(strlen(pch))
-- res.push_back(pch);
-- // uses the strtok() internal state to go to the next token
-- // cppcheck-suppress strtokCalled
-- pch = std::strtok(nullptr, ",");
-+ // tokenize with "," as a separator, unless escaped with backslash
-+ std::ostringstream s;
-+ auto flush = [&s, &res]() {
-+ auto string = s.str();
-+ if(string.size() > 0) {
-+ res.push_back(string.c_str());
-+ }
-+ s.str("");
-+ };
-+
-+ bool seenBackslash = false;
-+ const char* current = filtersString.c_str();
-+ const char* end = current + strlen(current);
-+ while(current != end) {
-+ char character = *current++;
-+ if(seenBackslash) {
-+ seenBackslash = false;
-+ if(character == ',') {
-+ s.put(',');
-+ continue;
-+ }
-+ s.put('\\');
-+ }
-+ if(character == '\\') {
-+ seenBackslash = true;
-+ } else if(character == ',') {
-+ flush();
-+ } else {
-+ s.put(character);
-+ }
-+ }
-+
-+ if(seenBackslash) {
-+ s.put('\\');
- }
-- DOCTEST_CLANG_SUPPRESS_WARNING_POP
-+ flush();
- return true;
- }
- return false;
-@@ -5533,7 +6361,7 @@
- #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
- if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \
- parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \
-- p->var = !!intRes; \
-+ p->var = static_cast<bool>(intRes); \
- else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \
- parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \
- p->var = true; \
-@@ -5568,9 +6396,12 @@
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
-+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false);
-+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
-+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
-@@ -5579,7 +6410,9 @@
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC));
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false);
-+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false);
- DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false);
-+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false);
- // clang-format on
-
- if(withDefaults) {
-@@ -5632,9 +6465,15 @@
- curr.clear();
- }
-
--// allows the user to override procedurally the int/bool options from the command line
-+// allows the user to override procedurally the bool options from the command line
-+void Context::setOption(const char* option, bool value) {
-+ setOption(option, value ? "true" : "false");
-+}
-+
-+// allows the user to override procedurally the int options from the command line
- void Context::setOption(const char* option, int value) {
- setOption(option, toString(value).c_str());
-+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- }
-
- // allows the user to override procedurally the string options from the command line
-@@ -5651,6 +6490,31 @@
-
- void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
-
-+void Context::setCout(std::ostream* out) { p->cout = out; }
-+
-+static class DiscardOStream : public std::ostream
-+{
-+private:
-+ class : public std::streambuf
-+ {
-+ private:
-+ // allowing some buffering decreases the amount of calls to overflow
-+ char buf[1024];
-+
-+ protected:
-+ std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; }
-+
-+ int_type overflow(int_type ch) override {
-+ setp(std::begin(buf), std::end(buf));
-+ return traits_type::not_eof(ch);
-+ }
-+ } discardBuf;
-+
-+public:
-+ DiscardOStream()
-+ : std::ostream(&discardBuf) {}
-+} discardOut;
-+
- // the main function that does all the filtering and test running
- int Context::run() {
- using namespace detail;
-@@ -5664,18 +6528,25 @@
- g_no_colors = p->no_colors;
- p->resetRunData();
-
-- // stdout by default
-- p->cout = &std::cout;
-- p->cerr = &std::cerr;
--
-- // or to a file if specified
- std::fstream fstr;
-- if(p->out.size()) {
-- fstr.open(p->out.c_str(), std::fstream::out);
-- p->cout = &fstr;
-+ if(p->cout == nullptr) {
-+ if(p->quiet) {
-+ p->cout = &discardOut;
-+ } else if(p->out.size()) {
-+ // to a file if specified
-+ fstr.open(p->out.c_str(), std::fstream::out);
-+ p->cout = &fstr;
-+ } else {
-+ // stdout by default
-+ p->cout = &std::cout;
-+ }
- }
-
-+ FatalConditionHandler::allocateAltStackMem();
-+
- auto cleanup_and_return = [&]() {
-+ FatalConditionHandler::freeAltStackMem();
-+
- if(fstr.is_open())
- fstr.close();
-
-@@ -5710,7 +6581,7 @@
- p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
-
- #ifdef DOCTEST_PLATFORM_WINDOWS
-- if(isDebuggerActive())
-+ if(isDebuggerActive() && p->no_debug_output == false)
- p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
- #endif // DOCTEST_PLATFORM_WINDOWS
-
-@@ -5747,13 +6618,16 @@
- first[i] = first[idxToSwap];
- first[idxToSwap] = temp;
- }
-+ } else if(p->order_by.compare("none", true) == 0) {
-+ // means no sorting - beneficial for death tests which call into the executable
-+ // with a specific test case in mind - we don't want to slow down the startup times
- }
- }
-
- std::set<String> testSuitesPassingFilt;
-
-- bool query_mode = p->count || p->list_test_cases || p->list_test_suites;
-- std::vector<String> queryResults;
-+ bool query_mode = p->count || p->list_test_cases || p->list_test_suites;
-+ std::vector<const TestCaseData*> queryResults;
-
- if(!query_mode)
- DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY);
-@@ -5766,9 +6640,9 @@
- if(tc.m_skip && !p->no_skip)
- skip_me = true;
-
-- if(!matchesAny(tc.m_file, p->filters[0], true, p->case_sensitive))
-+ if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive))
- skip_me = true;
-- if(matchesAny(tc.m_file, p->filters[1], false, p->case_sensitive))
-+ if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive))
- skip_me = true;
- if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive))
- skip_me = true;
-@@ -5799,14 +6673,14 @@
-
- // print the name of the test and don't execute it
- if(p->list_test_cases) {
-- queryResults.push_back(tc.m_name);
-+ queryResults.push_back(&tc);
- continue;
- }
-
- // print the name of the test suite if not done already and don't execute it
- if(p->list_test_suites) {
- if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') {
-- queryResults.push_back(tc.m_test_suite);
-+ queryResults.push_back(&tc);
- testSuitesPassingFilt.insert(tc.m_test_suite);
- p->numTestSuitesPassingFilters++;
- }
-@@ -5829,12 +6703,16 @@
- DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
-
- p->timer.start();
-+
-+ bool run_test = true;
-
- do {
- // reset some of the fields for subcases (except for the set of fully passed ones)
-- p->should_reenter = false;
-- p->subcasesCurrentLevel = 0;
-- p->subcasesEnteredLevels.clear();
-+ p->should_reenter = false;
-+ p->subcasesCurrentMaxLevel = 0;
-+ p->subcasesStack.clear();
-+
-+ p->shouldLogCurrentException = true;
-
- // reset stuff for logging with INFO()
- p->stringifiedContexts.clear();
-@@ -5842,10 +6720,13 @@
- #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
- try {
- #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-+// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
-+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
- FatalConditionHandler fatalConditionHandler; // Handle signals
- // execute the test
- tc.m_test();
- fatalConditionHandler.reset();
-+DOCTEST_MSVC_SUPPRESS_WARNING_POP
- #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
- } catch(const TestFailureException&) {
- p->failure_flags |= TestCaseFailureReason::AssertFailure;
-@@ -5859,10 +6740,15 @@
- // exit this loop if enough assertions have failed - even if there are more subcases
- if(p->abort_after > 0 &&
- p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
-- p->should_reenter = false;
-+ run_test = false;
- p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
- }
-- } while(p->should_reenter == true);
-+
-+ if(p->should_reenter && run_test)
-+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
-+ if(!p->should_reenter)
-+ run_test = false;
-+ } while(run_test);
-
- p->finalizeTestCaseData();
-
-@@ -5886,20 +6772,9 @@
- DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
- }
-
-- // see these issues on the reasoning for this:
-- // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
-- // - https://github.com/onqtam/doctest/issues/126
-- auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
-- { std::cout << std::string(); };
-- DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
--
- return cleanup_and_return();
- }
-
--DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats);
--
--DOCTEST_DEFINE_DEFAULTS(TestRunStats);
--
- IReporter::~IReporter() = default;
-
- int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
-@@ -5935,5 +6810,7 @@
- DOCTEST_MSVC_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
-
-+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
-+
- #endif // DOCTEST_LIBRARY_IMPLEMENTATION
- #endif // DOCTEST_CONFIG_IMPLEMENT