Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/extras
diff options
context:
space:
mode:
authorMartin Hořeňovský2025-09-30 10:54:31 +0200
committerMartin Hořeňovský2025-09-30 10:54:31 +0200
commitb3fb4b9feafcd8d91c5cb510a4775143fdbef02f (patch)
tree46a08efa7b84ca625bb83d1845def3e79586115e /extras
parent6500dc81496878a02e1dfef8ed358257a209fdaf (diff)
downloadcatch3-3.11.0.tar.gz
v3.11.0v3.11.0
Diffstat (limited to 'extras')
-rw-r--r--extras/catch_amalgamated.cpp268
-rw-r--r--extras/catch_amalgamated.hpp76
2 files changed, 214 insertions, 130 deletions
diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp
index c85f39b3..892d637d 100644
--- a/extras/catch_amalgamated.cpp
+++ b/extras/catch_amalgamated.cpp
@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch v3.10.0
-// Generated: 2025-08-24 16:18:04.775778
+// Catch v3.11.0
+// Generated: 2025-09-30 10:49:12.549018
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -825,6 +825,8 @@ namespace Catch {
m_data.reporterSpecifications.push_back( std::move( *parsed ) );
}
+ // Reading bazel env vars can change some parts of the config data,
+ // so we have to process the bazel env before acting on the config.
if ( enableBazelEnvSupport() ) {
readBazelEnvVars();
}
@@ -889,6 +891,8 @@ namespace Catch {
bool Config::showHelp() const { return m_data.showHelp; }
+ std::string const& Config::getExitGuardFilePath() const { return m_data.prematureExitGuardFilePath; }
+
// IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; }
StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
@@ -950,6 +954,26 @@ namespace Catch {
m_data.shardCount = bazelShardOptions->shardCount;
}
}
+
+ const auto bazelExitGuardFile = Detail::getEnv( "TEST_PREMATURE_EXIT_FILE" );
+ if (bazelExitGuardFile) {
+ m_data.prematureExitGuardFilePath = bazelExitGuardFile;
+ }
+
+ const auto bazelRandomSeed = Detail::getEnv( "TEST_RANDOM_SEED" );
+ if ( bazelRandomSeed ) {
+ auto parsedSeed = parseUInt( bazelRandomSeed, 0 );
+ if ( !parsedSeed ) {
+ // Currently we handle issues with parsing other Bazel Env
+ // options by warning and ignoring the issue. So we do the
+ // same for random seed option.
+ Catch::cerr()
+ << "Warning: could not parse 'TEST_RANDOM_SEED' ('"
+ << bazelRandomSeed << "') as proper seed.\n";
+ } else {
+ m_data.rngSeed = *parsedSeed;
+ }
+ }
}
} // end namespace Catch
@@ -975,28 +999,26 @@ namespace Catch {
ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
- m_info( CATCH_MOVE(builder.m_info) ) {
- m_info.message = builder.m_stream.str();
- getResultCapture().pushScopedMessage( m_info );
+ m_messageId( builder.m_info.sequence ) {
+ MessageInfo info( CATCH_MOVE( builder.m_info ) );
+ info.message = builder.m_stream.str();
+ IResultCapture::pushScopedMessage( CATCH_MOVE( info ) );
}
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
- m_info( CATCH_MOVE( old.m_info ) ) {
+ m_messageId( old.m_messageId ) {
old.m_moved = true;
}
ScopedMessage::~ScopedMessage() {
- if ( !m_moved ){
- getResultCapture().popScopedMessage(m_info);
- }
+ if ( !m_moved ) { IResultCapture::popScopedMessage( m_messageId ); }
}
Capturer::Capturer( StringRef macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType resultType,
- StringRef names ):
- m_resultCapture( getResultCapture() ) {
+ StringRef names ) {
auto trimmed = [&] (size_t start, size_t end) {
while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
++start;
@@ -1042,8 +1064,8 @@ namespace Catch {
case ',':
if (start != pos && openings.empty()) {
m_messages.emplace_back(macroName, lineInfo, resultType);
- m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
- m_messages.back().message += " := ";
+ m_messages.back().message += trimmed(start, pos);
+ m_messages.back().message += " := "_sr;
start = pos;
}
break;
@@ -1052,20 +1074,20 @@ namespace Catch {
}
assert(openings.empty() && "Mismatched openings");
m_messages.emplace_back(macroName, lineInfo, resultType);
- m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
- m_messages.back().message += " := ";
+ m_messages.back().message += trimmed(start, names.size() - 1);
+ m_messages.back().message += " := "_sr;
}
Capturer::~Capturer() {
assert( m_captured == m_messages.size() );
- for ( size_t i = 0; i < m_captured; ++i ) {
- m_resultCapture.popScopedMessage( m_messages[i] );
+ for (auto const& message : m_messages) {
+ IResultCapture::popScopedMessage( message.sequence );
}
}
void Capturer::captureValue( size_t index, std::string const& value ) {
assert( index < m_messages.size() );
m_messages[index].message += value;
- m_resultCapture.pushScopedMessage( m_messages[index] );
+ IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
m_captured++;
}
@@ -1149,7 +1171,6 @@ namespace Catch {
}
void cleanUp() {
cleanupSingletons();
- cleanUpContext();
}
std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
@@ -1161,6 +1182,8 @@ namespace Catch {
#include <cassert>
+#include <cstdio>
+#include <cstdlib>
#include <exception>
#include <iomanip>
#include <set>
@@ -1275,6 +1298,50 @@ namespace Catch {
}
}
+ // Creates empty file at path. The path must be writable, we do not
+ // try to create directories in path because that's hard in C++14.
+ void setUpGuardFile( std::string const& guardFilePath ) {
+ if ( !guardFilePath.empty() ) {
+#if defined( _MSC_VER )
+ std::FILE* file = nullptr;
+ if ( fopen_s( &file, guardFilePath.c_str(), "w" ) ) {
+ char msgBuffer[100];
+ const auto err = errno;
+ std::string errMsg;
+ if ( !strerror_s( msgBuffer, err ) ) {
+ errMsg = msgBuffer;
+ } else {
+ errMsg = "Could not translate errno to a string";
+ }
+
+#else
+ std::FILE* file = std::fopen( guardFilePath.c_str(), "w" );
+ if ( !file ) {
+ const auto err = errno;
+ const char* errMsg = std::strerror( err );
+#endif
+
+ CATCH_RUNTIME_ERROR( "Could not open the exit guard file '"
+ << guardFilePath << "' because '"
+ << errMsg << "' (" << err << ')' );
+ }
+ const int ret = std::fclose( file );
+ CATCH_ENFORCE(
+ ret == 0,
+ "Error when closing the exit guard file: " << ret );
+ }
+ }
+
+ // Removes file at path. Assuming we created it in setUpGuardFile.
+ void tearDownGuardFile( std::string const& guardFilePath ) {
+ if ( !guardFilePath.empty() ) {
+ const int ret = std::remove( guardFilePath.c_str() );
+ CATCH_ENFORCE(
+ ret == 0,
+ "Error when removing the exit guard file: " << ret );
+ }
+ }
+
} // anon namespace
Session::Session() {
@@ -1393,6 +1460,7 @@ namespace Catch {
static_cast<void>(std::getchar());
}
int exitCode = runInternal();
+
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << '\n' << std::flush;
static_cast<void>(std::getchar());
@@ -1433,6 +1501,10 @@ namespace Catch {
CATCH_TRY {
config(); // Force config to be constructed
+ // We need to retrieve potential Bazel config with the full Config
+ // constructor, so we have to create the guard file after it is created.
+ setUpGuardFile( m_config->getExitGuardFilePath() );
+
seedRng( *m_config );
if (m_configData.filenamesAsTags) {
@@ -1462,9 +1534,12 @@ namespace Catch {
TestGroup tests { CATCH_MOVE(reporter), m_config.get() };
auto const totals = tests.execute();
+ // If we got here, running the tests finished normally-enough.
+ // They might've failed, but that would've been reported elsewhere.
+ tearDownGuardFile( m_config->getExitGuardFilePath() );
+
if ( tests.hadUnmatchedTestSpecs()
&& m_config->warnAboutUnmatchedTestSpecs() ) {
- // UnmatchedTestSpecExitCode
return UnmatchedTestSpecExitCode;
}
@@ -1974,35 +2049,35 @@ namespace Detail {
std::string ret;
// This is enough for the "don't escape invisibles" case, and a good
// lower bound on the "escape invisibles" case.
- ret.reserve(string.size() + 2);
+ ret.reserve( string.size() + 2 );
- if (!escapeInvisibles) {
+ if ( !escapeInvisibles ) {
ret += '"';
ret += string;
ret += '"';
return ret;
}
+ size_t last_start = 0;
+ auto write_to = [&]( size_t idx ) {
+ if ( last_start < idx ) {
+ ret += string.substr( last_start, idx - last_start );
+ }
+ last_start = idx + 1;
+ };
+
ret += '"';
- for (char c : string) {
- switch (c) {
- case '\r':
- ret.append("\\r");
- break;
- case '\n':
- ret.append("\\n");
- break;
- case '\t':
- ret.append("\\t");
- break;
- case '\f':
- ret.append("\\f");
- break;
- default:
- ret.push_back(c);
- break;
+ for ( size_t i = 0; i < string.size(); ++i ) {
+ const char c = string[i];
+ if ( c == '\r' || c == '\n' || c == '\t' || c == '\f' ) {
+ write_to( i );
+ if ( c == '\r' ) { ret.append( "\\r" ); }
+ if ( c == '\n' ) { ret.append( "\\n" ); }
+ if ( c == '\t' ) { ret.append( "\\t" ); }
+ if ( c == '\f' ) { ret.append( "\\f" ); }
}
}
+ write_to( string.size() );
ret += '"';
return ret;
@@ -2279,7 +2354,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 3, 10, 0, "", 0 );
+ static Version version( 3, 11, 0, "", 0 );
return version;
}
@@ -2367,8 +2442,14 @@ namespace Catch {
namespace Catch {
+ namespace Detail {
+ void missingCaptureInstance() {
+ CATCH_INTERNAL_ERROR( "No result capture instance" );
+ }
+ } // namespace Detail
+
IResultCapture::~IResultCapture() = default;
-}
+} // namespace Catch
@@ -3361,6 +3442,9 @@ namespace Catch {
| Opt( config.allowZeroTests )
["--allow-running-no-tests"]
( "Treat 'No tests run' as a success" )
+ | Opt( config.prematureExitGuardFilePath, "path" )
+ ["--premature-exit-guard-file"]
+ ( "create a file before running tests and delete it during clean exit" )
| Arg( config.testsOrTags, "test name|pattern|tags" )
( "which test or tests to use" );
@@ -3515,7 +3599,11 @@ namespace {
#endif // Windows/ ANSI/ None
-#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC ) || defined( __GLIBC__ ) || defined(__FreeBSD__)
+#if defined( CATCH_PLATFORM_LINUX ) \
+ || defined( CATCH_PLATFORM_MAC ) \
+ || defined( __GLIBC__ ) \
+ || defined( __FreeBSD__ ) \
+ || defined( CATCH_PLATFORM_QNX )
# define CATCH_INTERNAL_HAS_ISATTY
# include <unistd.h>
#endif
@@ -3639,20 +3727,10 @@ namespace Catch {
namespace Catch {
- Context* Context::currentContext = nullptr;
-
- void cleanUpContext() {
- delete Context::currentContext;
- Context::currentContext = nullptr;
- }
- void Context::createContext() {
- currentContext = new Context();
- }
+ Context Context::currentContext;
Context& getCurrentMutableContext() {
- if ( !Context::currentContext ) { Context::createContext(); }
- // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
- return *Context::currentContext;
+ return Context::currentContext;
}
SimplePcg32& sharedRng() {
@@ -3757,7 +3835,7 @@ namespace Catch {
#endif
} // namespace Catch
-#elif defined(CATCH_PLATFORM_LINUX)
+#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
#include <fstream>
#include <string>
@@ -4091,23 +4169,27 @@ namespace Catch {
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
};
+ // Since we do not support multiple instantiations, we put these
+ // into global variables and rely on cleaning them up in outlined
+ // constructors/destructors
+ static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
+
+
static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
for (auto const& def : signalDefs) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
reportFatal(def.name);
}
}
- // If its not an exception we care about, pass it along.
+ // If a filter was previously registered, invoke it
+ if (previousTopLevelExceptionFilter) {
+ return previousTopLevelExceptionFilter(ExceptionInfo);
+ }
+ // Otherwise, pass along all exceptions.
// This stops us from eating debugger breaks etc.
return EXCEPTION_CONTINUE_SEARCH;
}
- // Since we do not support multiple instantiations, we put these
- // into global variables and rely on cleaning them up in outlined
- // constructors/destructors
- static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
-
-
// For MSVC, we reserve part of the stack memory for handling
// memory overflow structured exception.
FatalConditionHandler::FatalConditionHandler() {
@@ -5565,6 +5647,7 @@ ReporterSpec::ReporterSpec(
#include <cstdio>
#include <sstream>
+#include <tuple>
#include <vector>
namespace Catch {
@@ -5576,16 +5659,16 @@ namespace Catch {
std::ostringstream m_referenceStream; // Used for copy state/ flags from
Detail::Mutex m_mutex;
- auto add() -> std::size_t {
+ auto add() -> std::pair<std::size_t, std::ostringstream*> {
Detail::LockGuard _( m_mutex );
if( m_unused.empty() ) {
m_streams.push_back( Detail::make_unique<std::ostringstream>() );
- return m_streams.size()-1;
+ return { m_streams.size()-1, m_streams.back().get() };
}
else {
auto index = m_unused.back();
m_unused.pop_back();
- return index;
+ return { index, m_streams[index].get() };
}
}
@@ -5599,10 +5682,10 @@ namespace Catch {
}
};
- ReusableStringStream::ReusableStringStream()
- : m_index( Singleton<StringStreams>::getMutable().add() ),
- m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
- {}
+ ReusableStringStream::ReusableStringStream() {
+ std::tie( m_index, m_oss ) =
+ Singleton<StringStreams>::getMutable().add();
+ }
ReusableStringStream::~ReusableStringStream() {
static_cast<std::ostringstream*>( m_oss )->str("");
@@ -6085,28 +6168,6 @@ namespace Catch {
m_reporter->benchmarkFailed( error );
}
- void RunContext::pushScopedMessage( MessageInfo const& message ) {
- Detail::g_messages.push_back( message );
- }
-
- void RunContext::popScopedMessage( MessageInfo const& message ) {
- // Note: On average, it would probably be better to look for the message
- // backwards. However, we do not expect to have to deal with more
- // messages than low single digits, so the optimization is tiny,
- // and we would have to hand-write the loop to avoid terrible
- // codegen of reverse iterators in debug mode.
- Detail::g_messages.erase(
- std::find_if( Detail::g_messages.begin(),
- Detail::g_messages.end(),
- [id = message.sequence]( MessageInfo const& msg ) {
- return msg.sequence == id;
- } ) );
- }
-
- void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
- Detail::g_messageScopes.emplace_back( CATCH_MOVE(builder) );
- }
-
std::string RunContext::getCurrentTestName() const {
return m_activeTestCase
? m_activeTestCase->getTestCaseInfo().name
@@ -6433,11 +6494,26 @@ namespace Catch {
}
}
- IResultCapture& getResultCapture() {
- if (auto* capture = getCurrentContext().getResultCapture())
- return *capture;
- else
- CATCH_INTERNAL_ERROR("No result capture instance");
+ void IResultCapture::pushScopedMessage( MessageInfo&& message ) {
+ Detail::g_messages.push_back( CATCH_MOVE( message ) );
+ }
+
+ void IResultCapture::popScopedMessage( unsigned int messageId ) {
+ // Note: On average, it would probably be better to look for the message
+ // backwards. However, we do not expect to have to deal with more
+ // messages than low single digits, so the optimization is tiny,
+ // and we would have to hand-write the loop to avoid terrible
+ // codegen of reverse iterators in debug mode.
+ Detail::g_messages.erase( std::find_if( Detail::g_messages.begin(),
+ Detail::g_messages.end(),
+ [=]( MessageInfo const& msg ) {
+ return msg.sequence ==
+ messageId;
+ } ) );
+ }
+
+ void IResultCapture::emplaceUnscopedMessage( MessageBuilder&& builder ) {
+ Detail::g_messageScopes.emplace_back( CATCH_MOVE( builder ) );
}
void seedRng(IConfig const& config) {
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp
index a67743b3..d5eb1bb7 100644
--- a/extras/catch_amalgamated.hpp
+++ b/extras/catch_amalgamated.hpp
@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch v3.10.0
-// Generated: 2025-08-24 16:18:04.055916
+// Catch v3.11.0
+// Generated: 2025-09-30 10:49:11.225746
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -101,6 +101,9 @@
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
+#elif defined(__QNX__)
+# define CATCH_PLATFORM_QNX
+
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
# define CATCH_PLATFORM_WINDOWS
@@ -308,13 +311,17 @@
# endif
// Universal Windows platform does not support SEH
-// Or console colours (or console at all...)
-# if defined(CATCH_PLATFORM_WINDOWS_UWP)
-# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
-# else
+# if !defined(CATCH_PLATFORM_WINDOWS_UWP)
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif
+// Only some Windows platform families support the console
+# if defined(WINAPI_FAMILY_PARTITION)
+# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
+# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
+# endif
+# endif
+
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
@@ -564,11 +571,9 @@ namespace Catch {
IConfig const* m_config = nullptr;
IResultCapture* m_resultCapture = nullptr;
- CATCH_EXPORT static Context* currentContext;
+ CATCH_EXPORT static Context currentContext;
friend Context& getCurrentMutableContext();
friend Context const& getCurrentContext();
- static void createContext();
- friend void cleanUpContext();
public:
constexpr IResultCapture* getResultCapture() const {
@@ -579,21 +584,14 @@ namespace Catch {
m_resultCapture = resultCapture;
}
constexpr void setConfig( IConfig const* config ) { m_config = config; }
-
};
Context& getCurrentMutableContext();
inline Context const& getCurrentContext() {
- // We duplicate the logic from `getCurrentMutableContext` here,
- // to avoid paying the call overhead in debug mode.
- if ( !Context::currentContext ) { Context::createContext(); }
- // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
- return *Context::currentContext;
+ return Context::currentContext;
}
- void cleanUpContext();
-
class SimplePcg32;
SimplePcg32& sharedRng();
}
@@ -1069,10 +1067,9 @@ namespace Catch {
virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
virtual void benchmarkFailed( StringRef error ) = 0;
- virtual void pushScopedMessage( MessageInfo const& message ) = 0;
- virtual void popScopedMessage( MessageInfo const& message ) = 0;
-
- virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
+ static void pushScopedMessage( MessageInfo&& message );
+ static void popScopedMessage( unsigned int messageId );
+ static void emplaceUnscopedMessage( MessageBuilder&& builder );
virtual void handleFatalErrorCondition( StringRef message ) = 0;
@@ -1108,7 +1105,18 @@ namespace Catch {
virtual void exceptionEarlyReported() = 0;
};
- IResultCapture& getResultCapture();
+ namespace Detail {
+ [[noreturn]]
+ void missingCaptureInstance();
+ }
+ inline IResultCapture& getResultCapture() {
+ if (auto* capture = getCurrentContext().getResultCapture()) {
+ return *capture;
+ } else {
+ Detail::missingCaptureInstance();
+ }
+ }
+
}
#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
@@ -3800,6 +3808,8 @@ namespace Catch {
std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun;
+
+ std::string prematureExitGuardFilePath;
};
@@ -3827,6 +3837,8 @@ namespace Catch {
bool showHelp() const;
+ std::string const& getExitGuardFilePath() const;
+
// IConfig interface
bool allowThrows() const override;
StringRef name() const override;
@@ -3961,6 +3973,7 @@ namespace Catch {
std::string message;
SourceLineInfo lineInfo;
ResultWas::OfType type;
+ // The "ID" of the message, used to know when to remove it from reporter context.
unsigned int sequence;
DEPRECATED( "Explicitly use the 'sequence' member instead" )
@@ -4020,13 +4033,12 @@ namespace Catch {
ScopedMessage( ScopedMessage&& old ) noexcept;
~ScopedMessage();
- MessageInfo m_info;
+ unsigned int m_messageId;
bool m_moved = false;
};
class Capturer {
std::vector<MessageInfo> m_messages;
- IResultCapture& m_resultCapture;
size_t m_captured = 0;
public:
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
@@ -4074,7 +4086,7 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
- Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
+ Catch::IResultCapture::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
@@ -7466,7 +7478,7 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
-#define CATCH_VERSION_MINOR 10
+#define CATCH_VERSION_MINOR 11
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -7882,8 +7894,9 @@ namespace Generators {
class FilterGenerator final : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
Predicate m_predicate;
+ static_assert(!std::is_reference<Predicate>::value, "This would most likely result in a dangling reference");
public:
- template <typename P = Predicate>
+ template <typename P>
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
m_generator(CATCH_MOVE(generator)),
m_predicate(CATCH_FORWARD(pred))
@@ -7915,7 +7928,7 @@ namespace Generators {
template <typename T, typename Predicate>
GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
- return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, Predicate>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
+ return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, typename std::remove_reference<Predicate>::type>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
}
template <typename T>
@@ -9555,7 +9568,7 @@ namespace Catch {
#define CATCH_TRAP() __asm__(".inst 0xde01")
#endif
-#elif defined(CATCH_PLATFORM_LINUX)
+#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
// If we can use inline assembler, do it because this allows us to break
// directly at the location of the failing check instead of breaking inside
// raise() called from it, i.e. one stack frame below.
@@ -10718,11 +10731,6 @@ namespace Catch {
void benchmarkEnded( BenchmarkStats<> const& stats ) override;
void benchmarkFailed( StringRef error ) override;
- void pushScopedMessage( MessageInfo const& message ) override;
- void popScopedMessage( MessageInfo const& message ) override;
-
- void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
-
std::string getCurrentTestName() const override;
const AssertionResult* getLastResult() const override;