diff --git a/docs/configuration.md b/docs/configuration.md index 098496d6..dd81dde4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -120,6 +120,7 @@ by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`. CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression CATCH_CONFIG_DISABLE // Disables assertions and test case registration + CATCH_CONFIG_WCHAR // Enables use of wchart_t Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. @@ -127,6 +128,9 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, `CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running. +`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently +it is only used in support for DJGPP cross-compiler. + These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`. ### `CATCH_CONFIG_FAST_COMPILE` diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 0cecfb05..0eb266c4 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -67,7 +67,7 @@ //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #endif @@ -107,6 +107,13 @@ //////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// + // Use of __COUNTER__ is suppressed during code analysis in // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly // handled by it. @@ -126,6 +133,10 @@ #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_CONFIG_POSIX_SIGNALS #endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index f692b5c5..5fb1d07f 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -169,7 +169,12 @@ namespace { #ifdef CATCH_PLATFORM_MAC !isDebuggerActive() && #endif - isatty(STDOUT_FILENO); +#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) + isatty(STDOUT_FILENO) +#else + false +#endif + ; } IColourImpl* platformColourInstance() { ErrnoGuard guard; diff --git a/include/internal/catch_default_main.hpp b/include/internal/catch_default_main.hpp index 4372e9cc..17ad090a 100644 --- a/include/internal/catch_default_main.hpp +++ b/include/internal/catch_default_main.hpp @@ -12,7 +12,7 @@ #ifndef __OBJC__ -#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { #else diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index c6cde603..0581ac88 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -202,7 +202,7 @@ namespace Catch { return returnCode; } -#if defined(WIN32) && defined(UNICODE) +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) int Session::run( int argc, wchar_t* const argv[] ) { char **utf8Argv = new char *[ argc ]; diff --git a/include/internal/catch_session.h b/include/internal/catch_session.h index 09e8c2ed..eb8013cd 100644 --- a/include/internal/catch_session.h +++ b/include/internal/catch_session.h @@ -30,7 +30,7 @@ namespace Catch { void useConfigData( ConfigData const& configData ); int run( int argc, char* argv[] ); - #if defined(WIN32) && defined(UNICODE) + #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) int run( int argc, wchar_t* const argv[] ); #endif int run(); diff --git a/include/internal/catch_tostring.cpp b/include/internal/catch_tostring.cpp index a9f7735e..0d0158fa 100644 --- a/include/internal/catch_tostring.cpp +++ b/include/internal/catch_tostring.cpp @@ -116,6 +116,7 @@ std::string StringMaker::convert(const std::string& str) { return s; } +#ifdef CATCH_CONFIG_WCHAR std::string StringMaker::convert(const std::wstring& wstr) { std::string s; s.reserve(wstr.size()); @@ -124,6 +125,7 @@ std::string StringMaker::convert(const std::wstring& wstr) { } return ::Catch::Detail::stringify(s); } +#endif std::string StringMaker::convert(char const* str) { if (str) { @@ -139,6 +141,7 @@ std::string StringMaker::convert(char* str) { return{ "{null string}" }; } } +#ifdef CATCH_CONFIG_WCHAR std::string StringMaker::convert(wchar_t const * str) { if (str) { return ::Catch::Detail::stringify(std::wstring{ str }); @@ -153,6 +156,7 @@ std::string StringMaker::convert(wchar_t * str) { return{ "{null string}" }; } } +#endif std::string StringMaker::convert(int value) { diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index bb9cb0be..26756fa9 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -13,6 +13,7 @@ #include #include #include +#include "catch_compiler_capabilities.h" #include "catch_stream.h" #ifdef __OBJC__ @@ -119,10 +120,12 @@ namespace Catch { struct StringMaker { static std::string convert(const std::string& str); }; +#ifdef CATCH_CONFIG_WCHAR template<> struct StringMaker { static std::string convert(const std::wstring& wstr); }; +#endif template<> struct StringMaker { @@ -132,6 +135,7 @@ namespace Catch { struct StringMaker { static std::string convert(char * str); }; +#ifdef CATCH_CONFIG_WCHAR template<> struct StringMaker { static std::string convert(wchar_t const * str); @@ -140,6 +144,7 @@ namespace Catch { struct StringMaker { static std::string convert(wchar_t * str); }; +#endif template struct StringMaker { diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt index a4f85a68..4a1aeb78 100644 --- a/projects/SelfTest/Baselines/compact.sw.approved.txt +++ b/projects/SelfTest/Baselines/compact.sw.approved.txt @@ -236,9 +236,9 @@ Matchers.tests.cpp:: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not Matchers.tests.cpp:: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0 Matchers.tests.cpp:: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan Matchers.tests.cpp:: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 -Matchers.tests.cpp:: passed: std::nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 -Matchers.tests.cpp:: passed: std::nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 -Matchers.tests.cpp:: passed: std::nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0 +Matchers.tests.cpp:: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 +Matchers.tests.cpp:: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 +Matchers.tests.cpp:: passed: nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0 Matchers.tests.cpp:: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 Matchers.tests.cpp:: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0 Matchers.tests.cpp:: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf @@ -256,9 +256,9 @@ Matchers.tests.cpp:: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f Matchers.tests.cpp:: passed: 0.f, WithinAbs(-0.f, 0) for: 0.0f is within 0.0 of -0.0 Matchers.tests.cpp:: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan Matchers.tests.cpp:: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f -Matchers.tests.cpp:: passed: std::nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f -Matchers.tests.cpp:: passed: std::nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f -Matchers.tests.cpp:: passed: std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f +Matchers.tests.cpp:: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f +Matchers.tests.cpp:: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f +Matchers.tests.cpp:: passed: nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f Matchers.tests.cpp:: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f Matchers.tests.cpp:: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.0f Matchers.tests.cpp:: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 9c738463..70bff4a8 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1873,19 +1873,19 @@ with expansion: Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1., 2.), WithinULP(1., 1) ) + REQUIRE_THAT( nextafter(1., 2.), WithinULP(1., 1) ) with expansion: 1.0 is within 1 ULPs of 1.0 Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1., 0.), WithinULP(1., 1) ) + REQUIRE_THAT( nextafter(1., 0.), WithinULP(1., 1) ) with expansion: 1.0 is within 1 ULPs of 1.0 Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1., 2.), !WithinULP(1., 0) ) + REQUIRE_THAT( nextafter(1., 2.), !WithinULP(1., 0) ) with expansion: 1.0 not is within 0 ULPs of 1.0 @@ -2013,19 +2013,19 @@ with expansion: Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1.f, 2.f), WithinULP(1.f, 1) ) + REQUIRE_THAT( nextafter(1.f, 2.f), WithinULP(1.f, 1) ) with expansion: 1.0f is within 1 ULPs of 1.0f Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1.f, 0.f), WithinULP(1.f, 1) ) + REQUIRE_THAT( nextafter(1.f, 0.f), WithinULP(1.f, 1) ) with expansion: 1.0f is within 1 ULPs of 1.0f Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) ) + REQUIRE_THAT( nextafter(1.f, 2.f), !WithinULP(1.f, 0) ) with expansion: 1.0f not is within 0 ULPs of 1.0f diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 70868b59..227dee93 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -2121,7 +2121,7 @@ - std::nextafter(1., 2.), WithinULP(1., 1) + nextafter(1., 2.), WithinULP(1., 1) 1.0 is within 1 ULPs of 1.0 @@ -2129,7 +2129,7 @@ - std::nextafter(1., 0.), WithinULP(1., 1) + nextafter(1., 0.), WithinULP(1., 1) 1.0 is within 1 ULPs of 1.0 @@ -2137,7 +2137,7 @@ - std::nextafter(1., 2.), !WithinULP(1., 0) + nextafter(1., 2.), !WithinULP(1., 0) 1.0 not is within 0 ULPs of 1.0 @@ -2296,7 +2296,7 @@ - std::nextafter(1.f, 2.f), WithinULP(1.f, 1) + nextafter(1.f, 2.f), WithinULP(1.f, 1) 1.0f is within 1 ULPs of 1.0f @@ -2304,7 +2304,7 @@ - std::nextafter(1.f, 0.f), WithinULP(1.f, 1) + nextafter(1.f, 0.f), WithinULP(1.f, 1) 1.0f is within 1 ULPs of 1.0f @@ -2312,7 +2312,7 @@ - std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) + nextafter(1.f, 2.f), !WithinULP(1.f, 0) 1.0f not is within 0 ULPs of 1.0f diff --git a/projects/SelfTest/UsageTests/Matchers.tests.cpp b/projects/SelfTest/UsageTests/Matchers.tests.cpp index 3c20caa1..05056b43 100644 --- a/projects/SelfTest/UsageTests/Matchers.tests.cpp +++ b/projects/SelfTest/UsageTests/Matchers.tests.cpp @@ -77,6 +77,20 @@ namespace { namespace MatchersTests { using namespace Catch::Matchers; +#ifdef __DJGPP__ + float nextafter(float from, float to) + { + return ::nextafterf(from, to); + } + + double nextafter(double from, double to) + { + return ::nextafter(from, to); + } +#else + using std::nextafter; +#endif + TEST_CASE("String matchers", "[matchers]") { REQUIRE_THAT(testStringForMatching(), Contains("string")); REQUIRE_THAT(testStringForMatching(), Contains("string", Catch::CaseSensitive::No)); @@ -130,12 +144,16 @@ namespace { namespace MatchersTests { (defined(_GLIBCXX_RELEASE) && \ _GLIBCXX_RELEASE > 4)))) +// DJGPP meets the above condition but does not work properly anyway +#ifndef __DJGPP__ REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring")); REQUIRE_THAT(testStringForMatching(), Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No)); REQUIRE_THAT(testStringForMatching(), Matches("^this string contains 'abc' as a substring$")); REQUIRE_THAT(testStringForMatching(), Matches("^.* 'abc' .*$")); REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No)); +#endif + #endif REQUIRE_THAT(testStringForMatching2(), !Matches("this string contains 'abc' as a substring")); @@ -307,9 +325,9 @@ namespace { namespace MatchersTests { SECTION("ULPs") { REQUIRE_THAT(1.f, WithinULP(1.f, 0)); - REQUIRE_THAT(std::nextafter(1.f, 2.f), WithinULP(1.f, 1)); - REQUIRE_THAT(std::nextafter(1.f, 0.f), WithinULP(1.f, 1)); - REQUIRE_THAT(std::nextafter(1.f, 2.f), !WithinULP(1.f, 0)); + REQUIRE_THAT(nextafter(1.f, 2.f), WithinULP(1.f, 1)); + REQUIRE_THAT(nextafter(1.f, 0.f), WithinULP(1.f, 1)); + REQUIRE_THAT(nextafter(1.f, 2.f), !WithinULP(1.f, 0)); REQUIRE_THAT(1.f, WithinULP(1.f, 0)); REQUIRE_THAT(-0.f, WithinULP(0.f, 0)); @@ -344,9 +362,9 @@ namespace { namespace MatchersTests { SECTION("ULPs") { REQUIRE_THAT(1., WithinULP(1., 0)); - REQUIRE_THAT(std::nextafter(1., 2.), WithinULP(1., 1)); - REQUIRE_THAT(std::nextafter(1., 0.), WithinULP(1., 1)); - REQUIRE_THAT(std::nextafter(1., 2.), !WithinULP(1., 0)); + REQUIRE_THAT(nextafter(1., 2.), WithinULP(1., 1)); + REQUIRE_THAT(nextafter(1., 0.), WithinULP(1., 1)); + REQUIRE_THAT(nextafter(1., 2.), !WithinULP(1., 0)); REQUIRE_THAT(1., WithinULP(1., 0)); REQUIRE_THAT(-0., WithinULP(0., 0)); diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp index 683b8391..fa158705 100644 --- a/projects/SelfTest/UsageTests/Misc.tests.cpp +++ b/projects/SelfTest/UsageTests/Misc.tests.cpp @@ -290,6 +290,7 @@ TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) { } +#ifdef CATCH_CONFIG_WCHAR TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) { const wchar_t * const s = L"wide load"; std::string result = ::Catch::Detail::stringify( s ); @@ -313,6 +314,7 @@ TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { std::string result = ::Catch::Detail::stringify( s ); CHECK( result == "\"wide load\"" ); } +#endif TEST_CASE( "long long" ) { long long l = std::numeric_limits::max();