Compare commits

..

10 Commits

Author SHA1 Message Date
Martin Hořeňovský
d10b9bd02e v2.11.1 2019-12-28 21:24:04 +01:00
Martin Hořeňovský
55794e9b27 Avoid detecting Clang as having MSVC's traditional preprocessor
Fixes #1806
2019-12-28 18:57:24 +01:00
ptc-tgamper
fa6211bfc2 catch_debugger.h - implement break into debugger assembler instructions for iOS 2019-12-23 21:26:13 +01:00
ptc-tgamper
4e90f910dc catch_console_colour.cpp - adjust useColourOnPlatform for iOS 2019-12-23 21:26:13 +01:00
ptc-tgamper
0c59cc83cf catch_debugger.cpp - debugger detection is identical on Mac OS X and iOS 2019-12-23 21:26:13 +01:00
Martin Hořeňovský
e4004e0adb Provide const overload of ObjectStorage::stored_object()
Fixes #1820
2019-12-23 21:22:32 +01:00
Joe Burzinski
6c9a255dc2 Fix forwarding in SingleValueGenerator and generator creation
Fixes #1809
2019-12-15 20:50:43 +01:00
Joe Burzinski
9a8963133f Update single header generation script to warn about unused headers 2019-11-21 16:22:04 +01:00
Joe Burzinski
cfba9dce97 Fix wrong namespacing of benchmarking constructor helpers 2019-11-21 16:22:04 +01:00
Martin Hořeňovský
a537ccae22 Suppress using-namespace lint in GENERATE* macros
Closes #1799
2019-11-16 17:39:28 +01:00
16 changed files with 242 additions and 144 deletions

View File

@@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.11.0)
project(Catch2 LANGUAGES CXX VERSION 2.11.1)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

View File

@@ -5,11 +5,11 @@
[![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/HU1MkiBgFetFQJU4)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/Fj98nizVNqgaWH3i)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.11.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.11.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!

View File

@@ -168,7 +168,7 @@ Note that it is not possible to simply use the same instance for different runs
and resetting it between each run since that would pollute the measurements with
the resetting code.
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
the same semantics as providing a callable to `meter.measure` with `int` argument:
```c++
@@ -189,19 +189,17 @@ construct and destroy objects without dynamic allocation and in a way that lets
you measure construction and destruction separately.
```c++
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter)
{
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
})
};
BENCHMARK_ADVANCED("destroy", [](Catch::Benchmark::Chronometer meter)
{
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
})
};
```
`Catch::Benchmark::storage_for<T>` objects are just pieces of raw storage suitable for `T`

View File

@@ -31,6 +31,18 @@
[Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br>
## 2.11.1
### Improvements
* Breaking into debugger is supported on iOS (#1817)
* `google-build-using-namespace` clang-tidy warning is suppressed (#1799)
### Fixes
* Clang on Windows is no longer assumed to implement MSVC's traditional preprocessor (#1806)
* `ObjectStorage` now behaves properly in `const` contexts (#1820)
* `GENERATE_COPY(a, b)` now compiles properly (#1809, #1815)
* Some more cleanups in the benchmarking support
## 2.11.0

View File

@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 11
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header

View File

@@ -14,60 +14,66 @@
#include <type_traits>
namespace Catch {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
namespace Benchmark {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
new(&data) T(other.stored_object());
}
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
ObjectStorage() : data() {}
~ObjectStorage() { destruct_on_exit<T>(); }
ObjectStorage(const ObjectStorage& other)
{
new(&data) T(other.stored_object());
}
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
~ObjectStorage() { destruct_on_exit<T>(); }
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
T& stored_object()
{
return *static_cast<T*>(static_cast<void*>(&data));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
TStorage data;
};
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data));
}
T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data));
}
TStorage data;
};
}
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
}
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
}
#endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED

View File

@@ -149,9 +149,12 @@
// 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
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif
# if !defined(__clang__) // Handle Clang masquerading for msvc
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif // MSVC_TRADITIONAL
# endif // __clang__
#endif // _MSC_VER
#if defined(_REENTRANT) || defined(_MSC_VER)

View File

@@ -167,7 +167,7 @@ namespace {
bool useColourOnPlatform() {
return
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
!isDebuggerActive() &&
#endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))

View File

@@ -12,7 +12,7 @@
#include "catch_stream.h"
#include "catch_platform.h"
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h>
# include <stdbool.h>

View File

@@ -19,6 +19,17 @@ namespace Catch {
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(CATCH_PLATFORM_IPHONE)
// use inline assembler
#if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3")
#elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
#elif defined(__arm__)
#define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
#endif
#elif defined(CATCH_PLATFORM_LINUX)
// 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

View File

@@ -57,7 +57,6 @@ namespace Generators {
class SingleValueGenerator final : public IGenerator<T> {
T m_value;
public:
SingleValueGenerator(T const& value) : m_value( value ) {}
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
T const& get() const override {
@@ -120,21 +119,21 @@ namespace Generators {
m_generators.emplace_back(std::move(generator));
}
void populate(T&& val) {
m_generators.emplace_back(value(std::move(val)));
m_generators.emplace_back(value(std::forward<T>(val)));
}
template<typename U>
void populate(U&& val) {
populate(T(std::move(val)));
populate(T(std::forward<U>(val)));
}
template<typename U, typename... Gs>
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
populate(std::forward<U>(valueOrGenerator));
populate(std::forward<Gs>(moreGenerators)...);
}
public:
template <typename... Gs>
Generators(Gs... moreGenerators) {
Generators(Gs &&... moreGenerators) {
m_generators.reserve(sizeof...(Gs));
populate(std::forward<Gs>(moreGenerators)...);
}
@@ -166,7 +165,7 @@ namespace Generators {
struct as {};
template<typename T, typename... Gs>
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
}
template<typename T>
@@ -174,11 +173,11 @@ namespace Generators {
return Generators<T>(std::move(generator));
}
template<typename T, typename... Gs>
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
}
template<typename T, typename U, typename... Gs>
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
}
@@ -204,10 +203,10 @@ namespace Generators {
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED

View File

@@ -37,7 +37,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 11, 0, "", 0 );
static Version version( 2, 11, 1, "", 0 );
return version;
}

View File

@@ -181,7 +181,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
const auto step = .1;
auto gen = range(rangeStart, rangeEnd, step);
auto expected = rangeStart;
auto expected = rangeStart;
while( (rangeEnd - expected) > step ) {
INFO( "Current expected value is " << expected )
REQUIRE(gen.get() == Approx(expected));
@@ -198,7 +198,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
const auto step = .3;
auto gen = range(rangeStart, rangeEnd, step);
auto expected = rangeStart;
auto expected = rangeStart;
while( (rangeEnd - expected) > step ) {
INFO( "Current expected value is " << expected )
REQUIRE(gen.get() == Approx(expected));
@@ -214,7 +214,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
const auto step = .3;
auto gen = range(rangeStart, rangeEnd, step);
auto expected = rangeStart;
auto expected = rangeStart;
while( (rangeEnd - expected) > step ) {
INFO( "Current expected value is " << expected )
REQUIRE(gen.get() == Approx(expected));
@@ -223,7 +223,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
expected += step;
}
REQUIRE_FALSE(gen.next());
}
}
}
}
SECTION("Negative manual step") {
@@ -311,6 +311,21 @@ TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
REQUIRE(value == value2);
}
TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
// Verify Issue #1809 fix, only needs to compile.
auto a = GENERATE_COPY(1, 2);
(void)a;
auto b = GENERATE_COPY(as<long>{}, 1, 2);
(void)b;
int i = 1;
int j = 2;
auto c = GENERATE_COPY(i, j);
(void)c;
auto d = GENERATE_COPY(as<long>{}, i, j);
(void)d;
SUCCEED();
}
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
SECTION("Integer") {
auto random1 = Catch::Generators::random(0, 1000);

View File

@@ -126,5 +126,19 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
REQUIRE(v[i] == generated);
}
}
SECTION("construct and destroy example") {
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
};
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
};
}
}
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING

View File

@@ -23,6 +23,7 @@ def generate(v):
blankParser = re.compile( r'^\s*$')
seenHeaders = set([])
possibleHeaders = set([])
rootPath = os.path.join( catchPath, 'include/' )
outputPath = os.path.join( catchPath, 'single_include/catch2/catch.hpp' )
@@ -52,8 +53,20 @@ def generate(v):
if globals['includeImpl'] or globals['implIfDefs'] == -1:
out.write( line )
def getDirsToSearch( ):
return [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters', 'internal/benchmark', 'internal/benchmark/detail']]
def collectPossibleHeaders():
dirs = getDirsToSearch()
for dir in dirs:
hpps = glob(os.path.join(dir, '*.hpp'))
hs = glob(os.path.join(dir, '*.h'))
possibleHeaders.update( hpp.rpartition( os.sep )[2] for hpp in hpps )
possibleHeaders.update( h.rpartition( os.sep )[2] for h in hs )
def insertCpps():
dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters', 'internal/benchmark', 'internal/benchmark/detail']]
dirs = getDirsToSearch()
cppFiles = []
for dir in dirs:
cppFiles += glob(os.path.join(dir, '*.cpp'))
@@ -103,6 +116,13 @@ def generate(v):
write( line.rstrip() + "\n" )
write( u'// end {}\n'.format(filename) )
def warnUnparsedHeaders():
unparsedHeaders = possibleHeaders.difference( seenHeaders )
# These headers aren't packaged into the unified header, exclude them from any warning
whitelist = ['catch.hpp', 'catch_reporter_teamcity.hpp', 'catch_with_main.hpp', 'catch_reporter_automake.hpp', 'catch_reporter_tap.hpp', 'catch_reporter_sonarqube.hpp']
unparsedHeaders = unparsedHeaders.difference( whitelist )
if unparsedHeaders:
print( "WARNING: unparsed headers detected\n{0}\n".format( unparsedHeaders ) )
write( u"/*\n" )
write( u" * Catch v{0}\n".format( v.getVersionString() ) )
@@ -117,11 +137,13 @@ def generate(v):
write( u"#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
write( u"#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
collectPossibleHeaders()
parseFile( rootPath, 'catch.hpp' )
warnUnparsedHeaders()
write( u"#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
out.close()
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
print( "Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
if __name__ == '__main__':

View File

@@ -1,6 +1,6 @@
/*
* Catch v2.11.0
* Generated: 2019-11-15 15:01:56.628356
* Catch v2.11.1
* Generated: 2019-12-28 21:22:11.930976
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 11
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header
@@ -241,9 +241,12 @@ namespace Catch {
// 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
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif
# if !defined(__clang__) // Handle Clang masquerading for msvc
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif // MSVC_TRADITIONAL
# endif // __clang__
#endif // _MSC_VER
#if defined(_REENTRANT) || defined(_MSC_VER)
@@ -3907,7 +3910,6 @@ namespace Generators {
class SingleValueGenerator final : public IGenerator<T> {
T m_value;
public:
SingleValueGenerator(T const& value) : m_value( value ) {}
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
T const& get() const override {
@@ -3970,21 +3972,21 @@ namespace Generators {
m_generators.emplace_back(std::move(generator));
}
void populate(T&& val) {
m_generators.emplace_back(value(std::move(val)));
m_generators.emplace_back(value(std::forward<T>(val)));
}
template<typename U>
void populate(U&& val) {
populate(T(std::move(val)));
populate(T(std::forward<U>(val)));
}
template<typename U, typename... Gs>
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
populate(std::forward<U>(valueOrGenerator));
populate(std::forward<Gs>(moreGenerators)...);
}
public:
template <typename... Gs>
Generators(Gs... moreGenerators) {
Generators(Gs &&... moreGenerators) {
m_generators.reserve(sizeof...(Gs));
populate(std::forward<Gs>(moreGenerators)...);
}
@@ -4015,7 +4017,7 @@ namespace Generators {
struct as {};
template<typename T, typename... Gs>
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
}
template<typename T>
@@ -4023,11 +4025,11 @@ namespace Generators {
return Generators<T>(std::move(generator));
}
template<typename T, typename... Gs>
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
}
template<typename T, typename U, typename... Gs>
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
}
@@ -4053,11 +4055,11 @@ namespace Generators {
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
// end catch_generators.hpp
// start catch_generators_generic.hpp
@@ -7320,60 +7322,65 @@ namespace Catch {
#include <type_traits>
namespace Catch {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
namespace Benchmark {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
new(&data) T(other.stored_object());
}
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
ObjectStorage() : data() {}
~ObjectStorage() { destruct_on_exit<T>(); }
ObjectStorage(const ObjectStorage& other)
{
new(&data) T(other.stored_object());
}
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
~ObjectStorage() { destruct_on_exit<T>(); }
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
T& stored_object()
{
return *static_cast<T*>(static_cast<void*>(&data));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
TStorage data;
};
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data));
}
T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data));
}
TStorage data;
};
}
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
}
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
}
// end catch_constructor.hpp
@@ -7854,6 +7861,17 @@ namespace Catch {
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(CATCH_PLATFORM_IPHONE)
// use inline assembler
#if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3")
#elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
#elif defined(__arm__)
#define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
#endif
#elif defined(CATCH_PLATFORM_LINUX)
// 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
@@ -10094,7 +10112,7 @@ namespace {
bool useColourOnPlatform() {
return
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
!isDebuggerActive() &&
#endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
@@ -10271,7 +10289,7 @@ namespace Catch {
// end catch_debug_console.cpp
// start catch_debugger.cpp
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h>
# include <stdbool.h>
@@ -15050,7 +15068,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 11, 0, "", 0 );
static Version version( 2, 11, 1, "", 0 );
return version;
}