diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e631097..65f1927b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME) set(NOT_SUBPROJECT ON) endif() -project(Catch2 LANGUAGES CXX VERSION 2.1.0) +project(Catch2 LANGUAGES CXX VERSION 2.1.1) include(GNUInstallDirs) diff --git a/README.md b/README.md index e82aea00..1c2c03b0 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ [![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2) [![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2) [![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/nerce2MiN6sVmfCi) +[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/TpIcJaLaH4WrKlhS) -The latest version of the single header can be downloaded directly using this link +The latest version of the single header can be downloaded directly using this link ## Catch2 is released! diff --git a/conanfile.py b/conanfile.py index 354f68a4..fa9fdce1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.1.0" + version = "2.1.1" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/docs/release-notes.md b/docs/release-notes.md index 5c02f6bf..565d6cd8 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,27 @@ +# 2.1.1 + +## Improvements +* Static arrays are now properly stringified like ranges across MSVC/GCC/Clang +* Embedded newer version of Clara -- v1.1.1 + * This should fix some warnings dragged in from Clara +* MSVC's CLR exceptions are supported + + +## Fixes +* Fixed compilation when comparison operators do not return bool (#1147) +* Fixed CLR exceptions blowing up the executable during translation (#1138) + + +## Other changes +* Many CMake changes + * `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead. + * Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes + * Other changes to simplify Catch2's packaging + + + # 2.1.0 ## Improvements diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index 8b50ace0..fc196d91 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 1, 0, "", 0 ); + static Version version( 2, 1, 1, "", 0 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index ef720908..160bad07 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.1.0 - * Generated: 2018-01-10 13:51:15.378034 + * Catch v2.1.1 + * Generated: 2018-01-26 16:04:07.190063 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. @@ -807,18 +807,6 @@ namespace Catch { static std::string convert(wchar_t * str); }; - template - struct is_string_array : std::false_type {}; - - template - struct is_string_array : std::true_type {}; - - template - struct is_string_array : std::true_type {}; - - template - struct is_string_array : std::true_type {}; - template struct StringMaker { static std::string convert(const char* str) { @@ -1069,12 +1057,19 @@ namespace Catch { } template - struct StringMaker::value && !is_string_array::value>::type> { + struct StringMaker::value && !std::is_array::value>::type> { static std::string convert( R const& range ) { return rangeToString( range ); } }; + template + struct StringMaker { + static std::string convert(T const(&arr)[SZ]) { + return rangeToString(arr); + } + }; + } // namespace Catch // Separate std::chrono::duration specialization @@ -1269,7 +1264,7 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast(lhs == rhs); }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template @@ -1280,7 +1275,7 @@ namespace Catch { auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } template - auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast(lhs != rhs); }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } template @@ -1314,19 +1309,19 @@ namespace Catch { template auto operator > ( RhsT const& rhs ) -> BinaryExpr const { - return { m_lhs > rhs, m_lhs, ">", rhs }; + return { static_cast(m_lhs > rhs), m_lhs, ">", rhs }; } template auto operator < ( RhsT const& rhs ) -> BinaryExpr const { - return { m_lhs < rhs, m_lhs, "<", rhs }; + return { static_cast(m_lhs < rhs), m_lhs, "<", rhs }; } template auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { - return { m_lhs >= rhs, m_lhs, ">=", rhs }; + return { static_cast(m_lhs >= rhs), m_lhs, ">=", rhs }; } template auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { - return { m_lhs <= rhs, m_lhs, "<=", rhs }; + return { static_cast(m_lhs <= rhs), m_lhs, "<=", rhs }; } auto makeUnaryExpr() const -> UnaryExpr { @@ -5093,8 +5088,14 @@ namespace Catch { #endif // start clara.hpp -// v1.0-develop.2 -// See https://github.com/philsquared/Clara +// Copyright 2017 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See https://github.com/philsquared/Clara for more details + +// Clara v1.1.1 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH @@ -5457,7 +5458,7 @@ namespace detail { template struct UnaryLambdaTraits { static const bool isValid = true; - using ArgType = typename std::remove_const::type>::type;; + using ArgType = typename std::remove_const::type>::type; using ReturnType = ReturnT; }; @@ -5621,7 +5622,7 @@ namespace detail { return *this; } - ~ResultValueBase() { + ~ResultValueBase() override { if( m_type == Ok ) m_value.~T(); } @@ -5659,7 +5660,7 @@ namespace detail { auto errorMessage() const -> std::string { return m_errorMessage; } protected: - virtual void enforceOk() const { + void enforceOk() const override { // !TBD: If no exceptions, std::terminate here or something switch( m_type ) { case ResultBase::LogicError: @@ -5739,46 +5740,30 @@ namespace detail { return ParserResult::ok( ParseResultType::Matched ); } - struct BoundRefBase { - BoundRefBase() = default; - BoundRefBase( BoundRefBase const & ) = delete; - BoundRefBase( BoundRefBase && ) = delete; - BoundRefBase &operator=( BoundRefBase const & ) = delete; - BoundRefBase &operator=( BoundRefBase && ) = delete; + struct NonCopyable { + NonCopyable() = default; + NonCopyable( NonCopyable const & ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable &operator=( NonCopyable const & ) = delete; + NonCopyable &operator=( NonCopyable && ) = delete; + }; - virtual ~BoundRefBase() = default; - - virtual auto isFlag() const -> bool = 0; + struct BoundRef : NonCopyable { + virtual ~BoundRef() = default; virtual auto isContainer() const -> bool { return false; } + }; + struct BoundValueRefBase : BoundRef { virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + }; + struct BoundFlagRefBase : BoundRef { virtual auto setFlag( bool flag ) -> ParserResult = 0; }; - struct BoundValueRefBase : BoundRefBase { - auto isFlag() const -> bool override { return false; } - - auto setFlag( bool ) -> ParserResult override { - return ParserResult::logicError( "Flags can only be set on boolean fields" ); - } - }; - - struct BoundFlagRefBase : BoundRefBase { - auto isFlag() const -> bool override { return true; } - - auto setValue( std::string const &arg ) -> ParserResult override { - bool flag; - auto result = convertInto( arg, flag ); - if( result ) - setFlag( flag ); - return result; - } - }; - template - struct BoundRef : BoundValueRefBase { + struct BoundValueRef : BoundValueRefBase { T &m_ref; - explicit BoundRef( T &ref ) : m_ref( ref ) {} + explicit BoundValueRef( T &ref ) : m_ref( ref ) {} auto setValue( std::string const &arg ) -> ParserResult override { return convertInto( arg, m_ref ); @@ -5786,10 +5771,10 @@ namespace detail { }; template - struct BoundRef> : BoundValueRefBase { + struct BoundValueRef> : BoundValueRefBase { std::vector &m_ref; - explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} + explicit BoundValueRef( std::vector &ref ) : m_ref( ref ) {} auto isContainer() const -> bool override { return true; } @@ -5834,12 +5819,12 @@ namespace detail { template inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { - ArgType temp; + ArgType temp{}; auto result = convertInto( arg, temp ); return !result ? result : LambdaInvoker::ReturnType>::invoke( lambda, temp ); - }; + } template struct BoundLambda : BoundValueRefBase { @@ -5888,6 +5873,9 @@ namespace detail { public: template auto operator|( T const &other ) const -> Parser; + + template + auto operator+( T const &other ) const -> Parser; }; // Common code and state for Args and Opts @@ -5895,16 +5883,16 @@ namespace detail { class ParserRefImpl : public ComposableParserImpl { protected: Optionality m_optionality = Optionality::Optional; - std::shared_ptr m_ref; + std::shared_ptr m_ref; std::string m_hint; std::string m_description; - explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} public: template ParserRefImpl( T &ref, std::string const &hint ) - : m_ref( std::make_shared>( ref ) ), + : m_ref( std::make_shared>( ref ) ), m_hint( hint ) {} @@ -5945,10 +5933,10 @@ namespace detail { class ExeName : public ComposableParserImpl { std::shared_ptr m_name; - std::shared_ptr m_ref; + std::shared_ptr m_ref; template - static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { return std::make_shared>( lambda) ; } @@ -5956,7 +5944,7 @@ namespace detail { ExeName() : m_name( std::make_shared( "" ) ) {} explicit ExeName( std::string &ref ) : ExeName() { - m_ref = std::make_shared>( ref ); + m_ref = std::make_shared>( ref ); } template @@ -5999,7 +5987,10 @@ namespace detail { if( token.type != TokenType::Argument ) return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - auto result = m_ref->setValue( remainingTokens->token ); + assert( dynamic_cast( m_ref.get() ) ); + auto valueRef = static_cast( m_ref.get() ); + + auto result = valueRef->setValue( remainingTokens->token ); if( !result ) return InternalParseResult( result ); else @@ -6072,20 +6063,22 @@ namespace detail { if( remainingTokens && remainingTokens->type == TokenType::Option ) { auto const &token = *remainingTokens; if( isMatch(token.token ) ) { - if( m_ref->isFlag() ) { - auto result = m_ref->setFlag( true ); + if( auto flagRef = dynamic_cast( m_ref.get() ) ) { + auto result = flagRef->setFlag( true ); if( !result ) return InternalParseResult( result ); if( result.value() == ParseResultType::ShortCircuitAll ) return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { + assert( dynamic_cast( m_ref.get() ) ); + auto valueRef = static_cast( m_ref.get() ); ++remainingTokens; if( !remainingTokens ) return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; if( argToken.type != TokenType::Argument ) return InternalParseResult::runtimeError( "Expected argument following " + token.token ); - auto result = m_ref->setValue( argToken.token ); + auto result = valueRef->setValue( argToken.token ); if( !result ) return InternalParseResult( result ); if( result.value() == ParseResultType::ShortCircuitAll ) @@ -6161,6 +6154,12 @@ namespace detail { return Parser( *this ) |= other; } + // Forward deprecated interface with '+' instead of '|' + template + auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } + template + auto operator+( T const &other ) const -> Parser { return operator|( other ); } + auto getHelpColumns() const -> std::vector { std::vector cols; for (auto const &o : m_options) { @@ -6200,6 +6199,8 @@ namespace detail { for( auto const &cols : rows ) optWidth = (std::max)(optWidth, cols.left.size() + 2); + optWidth = (std::min)(optWidth, consoleWidth/2); + for( auto const &cols : rows ) { auto row = TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + @@ -7086,6 +7087,17 @@ namespace Catch { return Catch::Detail::stringify( [exception description] ); } #else + // Compiling a mixed mode project with MSVC means that CLR + // exceptions will be caught in (...) as well. However, these + // do not fill-in std::current_exception and thus lead to crash + // when attempting rethrow. + // /EHa switch also causes structured exceptions to be caught + // here, but they fill-in current_exception properly, so + // at worst the output should be a little weird, instead of + // causing a crash. + if (std::current_exception() == nullptr) { + return "Non C++ exception. Possibly a CLR exception."; + } return tryTranslators(); #endif } @@ -9148,6 +9160,9 @@ namespace Catch { if( Option listed = list( config() ) ) return static_cast( *listed ); + // Note that on unices only the lower 8 bits are usually used, clamping + // the return value to 255 prevents false negative when some multiple + // of 256 tests has failed return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); } catch( std::exception& ex ) { @@ -10689,7 +10704,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 1, 0, "", 0 ); + static Version version( 2, 1, 1, "", 0 ); return version; } diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 730773e4..174beba9 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.1.0@%s/%s" % (username, channel) + requires = "Catch/2.1.1@%s/%s" % (username, channel) def build(self): cmake = CMake(self)